当前位置: 首页 > news >正文

aikit 2023 3D与机械臂结合!

引言

今天我们主要了解3D摄像头是如何跟机械臂应用相结合的。我们最近准备推出一款新的机械臂套装AI Kit 2023 3D,熟悉我们的老用户应该知道,我们之前的AI Kit 2023套装使用的是2D摄像头。

随着技术进步,市场需求和领域的扩大,2D的摄像头已经不能够满足很多场景。3D摄像头也在近些年间火了起来。随着我们的步伐,一起来认识一下3D摄像头带给我们的应用。

产品介绍

RealSence-Depth camera

我们今天涉及到的3D摄像头是RealSence是Intel公司开发的一种深度感知摄像头。可以从图片中看出来,这个相机有四个镜头,它们分别是一个红外激光投影仪,两个红外摄像头和一个彩色摄像头。这几个镜头具体有啥作用:

红外激光投影仪:

投射一个红外光点网格到场景中,然后这些光点被红外摄像头捕获。因为投影仪和摄像头的位置是固定的,所以通过计算光点在摄像头中的位置偏移,可以推算出每个光点对应的物体距离摄像头的距离,从而得到场景的深度信息。

红外摄像头:

红外摄像头是一种能够捕获红外光谱的摄像头。红外光谱是电磁谱中的一部分,其波长长于可见光,但短于微波。红外摄像头的主要作用是能够在无可见光照明的条件下进行成像,因为许多物体会发射、反射或透过红外光。

彩色摄像头:

通常用于捕获场景的常规视觉信息,而其他的摄像头则用于捕获额外的信息,如场景的深度信息或在低光照条件下的图像。这些信息可以与彩色摄像头捕获的图像相结合,以提供更丰富的视觉数据,支持更高级的功能,如面部识别、增强现实或3D建模等。

结合这四个摄像头的功能,能够获取一个物体的三维信息,这种技术可以用于人脸识别、手势识别、物体识别、测量物体的深度等多种应用。

Artificial Intelligence Kit 3D

人工智能3D套装是机械臂应用人工智能,机器视觉的入门款套装。套装使用了四种识别算法,颜色识别,形状识别,yolov8等,适配可视化的操作界面,使用3D摄像头解决了2D摄像头需要标志定位的短板,开源代码基于python平台,可通过开发软件实现机械臂的控制

该套装是搭配机械臂(myCobot,mechArm,myArm)进行使用,仿工业场景的构造。

myCobot 280

myCobot 280 M5是一款由Elephant Robotics和M5Stack联合开发的最小和最轻的六轴协作机器人。它采用集成模块化设计,重量仅为850克,非常轻巧,搭载6个高性能伺服电机,具有快速响应,惯性小和平滑旋转的特点。

3D摄像头应用领域

如果在同一个应用领域中,用2D摄像头和3D摄像头它们的表型性能会怎样。从我们身边常见的来了解:

从图标中可以知道,2D摄像头需要通过特定的算法来得到一些参数,而3D摄像头能够直接获取较多的信息,在同一应用领域下的性能更加精准。在未来的,3D摄像头的趋势必然是飞速增长的!

这也是我们推出3D人工智能套装的原因之一,跟上时代的步伐。

算法介绍

机械臂视觉识别,一定会涉及手眼标定。虽然两种版本的手眼标定的流程是一样的,但是他们在计算中还是会有一些差别,我们先看它们的识别区。

从中间的是被区域可以看到,3D版本已经没有了二维码的标识,在2D版本上二维码的标识的主要功能是确定识别的区域,以及提供一个固定高度的值。在获取了三维数据之后,就不需要用到二维码进行标识了,可以直接获取到相机距离平面高度的值。

这一点体现了3D摄像头能够直接获取深度的信息。

如何使用 realsence 在python中

environment build
operate system:window10/11
program language:python 3.9+
libraries:
from typing import Tuple, Optional
import pyrealsense2 as rs
import numpy as np
import cv2
import timeclass RealSenseCamera:
    def __init__(self):
        super().__init__()        # Configure depth and color streams
        self.pipeline = rs.pipeline()
        self.config = rs.config()
        self.config.enable_stream(rs.stream.color, 1920, 1080, rs.format.bgr8, 30)
        # Is the camera mirror image reversed
        self.flip_h = False
        self.flip_v = False        # Get device product line for setting a supporting resolution
        pipeline_wrapper = rs.pipeline_wrapper(self.pipeline)
        pipeline_profile = self.config.resolve(pipeline_wrapper)
        # set auto exposure
        color = pipeline_profile.get_device().query_sensors()[0]
        color.set_option(rs.option.enable_auto_exposure, True)        device = pipeline_profile.get_device()        sensor_infos = list(
            map(lambda x: x.get_info(rs.camera_info.name), device.sensors)
        )        # set resolution
        self.config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)
        self.config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)        align_to = rs.stream.color
        self.align = rs.align(align_to)    def capture(self):
        # Start streaming
        self.pipeline.start(self.config)        # warm up
        for i in range(60):
            pipeline = self.pipeline
            frames = pipeline.wait_for_frames()    def release(self):
        self.pipeline.stop()    def update_frame(self) -> None:
        pipeline = self.pipeline
        frames = pipeline.wait_for_frames()
        aligned_frames = self.align.process(frames)
        self.curr_frame = aligned_frames
        self.curr_frame_time = time.time_ns()    def color_frame(self) -> Optional[np.ndarray]:
        frame = self.curr_frame.get_color_frame()
        if not frame:
            return None
        frame = np.asanyarray(frame.get_data())
        if self.flip_h:
            frame = cv2.flip(frame, 1)
        if self.flip_v:
            frame = cv2.flip(frame, 0)
        return frame    def depth_frame(self) -> Optional[np.ndarray]:
        frame = self.curr_frame.get_depth_frame()
        if not frame:
            return None
        frame = np.asanyarray(frame.get_data())
        if self.flip_h:
            frame = cv2.flip(frame, 1)
        if self.flip_v:
            frame = cv2.flip(frame, 0)
        return frame

颜色识别和形状识别都是基于openCV提供的算法来识别物体抓取物体。只需要简单的做一个hsv的检测的算法就能够检测出来颜色。

# 初始化要识别的颜色
    def __init__(self) -> None:
        self.area_low_threshold = 15000
        self.detected_name = None
        self.hsv_range = {
            "green": ((40, 50, 50), (90, 256, 256)),
            # "blueA": ((91, 100, 100), (105, 256, 256)),
            # "yellow": ((20, 240, 170), (30, 256, 256)),
            "yellow": ((15, 46, 43), (30, 256, 256)),
            "redA": ((0, 100, 100), (6, 256, 256)),
            "redB": ((170, 100, 100), (179, 256, 256)),
            # "orange": ((8, 100, 100), (15, 256, 256)),
            "blue": ((100, 43, 46), (124, 256, 256)),
        }# 对图像的处理
result = []
        for color, (hsv_low, hsv_high) in self.hsv_range.items():
            hsv_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
            in_range = cv2.inRange(hsv_frame, hsv_low, hsv_high)            # 对颜色区域进行膨胀和腐蚀
            kernel = np.ones((5, 5), np.uint8)
            in_range = cv2.morphologyEx(in_range, cv2.MORPH_CLOSE, kernel)
            in_range = cv2.morphologyEx(in_range, cv2.MORPH_OPEN, kernel)            contours, hierarchy = cv2.findContours(
                in_range, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
            )            contours = list(
                filter(lambda x: cv2.contourArea(x) > self.area_low_threshold, contours)
            )            rects = list(map(cv2.minAreaRect, contours))
            boxes = list(map(cv2.boxPoints, rects))
            boxes = list(map(np.int32, boxes))            if len(boxes) != 0:
                if color.startswith("red"):
                    color = "red"
                for box in boxes:
                    result.append(ColorDetector.DetectResult(color, box))
                    # self.detected_name = result
                    self.detected_name = result[0].color
        return result

YOLOv8 和拆码垛

 我们在这个套装里面还使用到了目前比较火的一款识别模型YOLOv8,此模型还涉及到深度学习和模型训练等功能。

YOLOv8是一种目标检测算法,它是基于深度学习的YOLO(You Only Look Once)系列算法的最新版本。YOLO算法是一种实时目标检测算法,其特点是能够在一次前向传播中同时完成目标检测和定位,速度非常快。Home - Ultralytics YOLOv8 Docs

主要特点:

  • 高性能:YOLOv8在目标检测任务中具有较高的准确性和速度。它能够在实时或接近实时的速度下进行目标检测,适用于各种应用场景。
  • 简单而有效的设计:YOLOv8采用了简单而有效的设计,通过使用更深的网络结构和更多的特征层来提高检测性能。它还使用了一种自适应的训练策略,可以在不同的目标检测任务上进行快速训练和调整。
  • 多种规模的检测:YOLOv8提供了不同的模型大小,包括小型、中型和大型模型,以满足不同场景下的需求。这些模型可以在不同的硬件设备上进行部署和使用。
  • 开源和易用性:YOLOv8是开源的,代码和预训练模型都可以在GitHub上获得。它还提供了简单易用的API,使得用户可以方便地进行模型训练、推理和部署。

要使用YOLOv8是需要进行自定义训练模型的,在进行目标检测任务是,根据具体应用场景和需求,通过在自定义数据集上进行训练得到模型。

为什么要训练模型呢?训练模型的目的是让计算机能够自动识别和定位图像或视频中的目标物体。通过训练模型,我们可以让计算机学会如何识别不同种类的物体,并且能够准确地定位它们的位置。这对于许多应用场景非常重要,比如自动驾驶、安防监控、智能交通等。

对此我们的源码文件中已经包含了我们自己训练的模型,如果你对YOLOv8的技术很熟练了,你可以自己对识别物体进行训练。

下面的代码是程序中使用的代码

class YOLODetector:
    DetectResult = List[ultralytics.engine.results.Results]    def __init__(self) -> None:
        """
        init YOLO model。
        """
        self.model_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/resources/yolo/best.pt'
        self.model = YOLO(self.model_path)
        self.predict_args = {"conf": 0.2}        self.detected_name = None    def get_radian(self, res: DetectResult):
        return 0    def detect(self, frame: np.ndarray):
        """
        Perform object detection on input images.        Args:
            frame (np.ndarray): Input image frame.        Returns:
            List[DetectResult]: A list containing the detection results.
        """
        res = self.model.predict(frame, **self.predict_args)
        res = list(filter(lambda x: len(x.boxes) != 0, res))
        if len(res) == 0:
            return None
        else:
            names = self.get_names(res)
            self.detected_name = names
            return res    def draw_result(self, frame: np.ndarray, res: List[DetectResult]):
        """
        Draws the bounding box of the detection results on the image.        Args:
             frame (np.ndarray): Input image frame.
             res (List[DetectResult]): List of detection results.
        """
        res = list(filter(lambda x: len(x.boxes) != 0, res))
        for r in res:
            boxes = r.boxes.xyxy.numpy()
            for box in boxes:
                x1, y1, x2, y2 = box.astype(int)
                cv2.rectangle(frame, (x1, y1), (x2, y2), color=(0, 255, 0), thickness=1)
                cv2.putText(frame, "Name: " + str(self.detected_name), (20, 80),
                            cv2.FONT_HERSHEY_COMPLEX_SMALL, 1,
                            (0, 0, 255))
            # x1, y1, x2, y2 = np.squeeze(r.boxes.xyxy.numpy()).astype(int)
            # cv2.rectangle(frame, (x1, y1), (x2, y2), color=(0, 255, 0), thickness=1)    def target_position(self, res: DetectResult) -> Tuple[int, int]:
        """
        Extract the location information of the target from the detection results.         Args:
             res (DetectResult): detection result.         Returns:
             Tuple[int, int]: The position coordinates (x, y) of the target.
        """
        boxes = res.boxes.xywh.numpy()
        boxs_list = []
        for box in boxes:
            x, y, w, h = box.astype(int)
            boxs_list.append((x, y))
        boxs_list = tuple(boxs_list)
        return boxs_list    def get_rect(self, res: DetectResult):
        """
        Obtain the bounding box coordinate information of the target from the detection result.        Args:
             res (DetectResult): detection result.         Returns:
             List[Tuple[int, int]]: The bounding box coordinate information of the target, including four vertex coordinates.
        """
        boxes = res.boxes.xywh.numpy()
        box_list = []
        for box in boxes:
            x, y, w, h = box.astype(int)
            size = 3
            rect = [
                [x - size, y - size],
                [x + size, y - size],
                [x + size, y + size],
                [x - size, y + size],
            ]
            box_list.append(rect)
        return box_list    def get_names(self, res: DetectResult):
        """
        Get the category name in the detection results        Args:
             res (DetectResult): detection result.         Returns:
             List[names]: A list category names.
        """
        names_dict = {
            0: 'jeep', 1: 'apple', 2: 'banana1', 3: 'bed', 4: 'grape',
            5: 'laptop', 6: 'microwave', 7: 'orange', 8: 'pear',
            9: 'refrigerator1', 10: 'refrigerator2', 11: 'sofa', 12: 'sofa2',
            13: 'tv', 14: 'washing machine1'
        }        ids = [int(cls) for cls in res[0].boxes.cls.numpy()]  # Assuming you have only one result in the list
        names = [names_dict.get(id, 'Unknown') for id in ids]        return names

搭配上3D摄像头的特性,获取被识别的物体的高度实现拆码垛的demo,能够将他们像拆积木一样拆除。

总结

我们的机械臂和深度摄像头套装不仅是一款产品,更是一个开启学习之门的机会。这个套装以用户友好的方式,提供了一个理想的平台,让初学者可以在实践中探索和学习机械臂操作和机器视觉的知识,更重要的是,它提供了一个独特的机会,让用户能够深入理解和掌握3D相机算法。

随着科技的进步,3D摄像头的应用正在迅速扩展到多个领域,包括但不限于制造、安全、娱乐和医疗。我们坚信,通过使用我们的套装,用户将能够把握这一技术趋势,为自己的未来学习和职业生涯奠定坚实的基础。

相关文章:

aikit 2023 3D与机械臂结合!

引言 今天我们主要了解3D摄像头是如何跟机械臂应用相结合的。我们最近准备推出一款新的机械臂套装AI Kit 2023 3D,熟悉我们的老用户应该知道,我们之前的AI Kit 2023套装使用的是2D摄像头。 随着技术进步,市场需求和领域的扩大,2D的…...

模拟退火算法应用——求解TSP问题

仅作自己学习使用 一、问题 旅行商问题(TSP) 是要求从一个城市出发,依次访问研究区所有的城市,并且只访问一次不能走回头路,最后回到起点,求一个使得总的周游路径最短的城市访问顺序。 采用模拟退火算法求解TSP问题&#x…...

【LeetCode】每日一题 2023_11_28 设计前中后队列(数组/链表/双端队列)

文章目录 刷题前唠嗑题目:设计前中后队列题目描述代码与解题思路偷看大佬题解 结语 刷题前唠嗑 LeetCode?启动!!! 这道题的难度,才是我想象中的中等题的难度好吧,昨天那玩意对我来说还是太难了…...

python基于YOLOv8全系列模型【n/s/m/l/x】开发构建不同参数量级的钢铁产业产品智能自动化检测识别系统

在前文的项目开发实践中,我们已经以钢铁产业产品缺陷检测数据场景为基准,陆续开发构建了多款目标检测模型,感兴趣的话可以自行阅读即可。 《YOLOv3老矣尚能战否?基于YOLOv3开发构建建钢铁产业产品智能自动化检测识别系统&#xf…...

力扣142. 环形链表 II

文章目录 力扣142. 环形链表 II示例代码实现总结收获 力扣142. 环形链表 II 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达&#xff0c…...

【设计模式-2.2】创建型——简单工厂和工厂模式

说明:本文介绍设计模式中,创建型设计模式中的工厂模式; 飞机大战 创建型设计模式,关注于对象的创建,本文介绍的简单工厂和工厂模式同样也是。举一个游戏例子,如飞机大战游戏中,屏幕中敌人类型…...

将文件读入C中的字符数组

当您使用 C 编程语言时,您可能会遇到一些需要将文件读入字符数组的问题,例如分析每个字符的频率,或者将所有句子的每个起始词从小写转换为大写,反之亦然。该解决方案非常简单,但对于不太了解文件读取或写入的人来说可能…...

不小心删除了短信,如何在 Android 上恢复已删除的短信

不小心删除了文字消息在 Android 手机上使用可能会是一种令人痛苦的体验。这些消息可能包含有价值的信息、珍贵的回忆或重要的细节。幸运的是,您可以探索多种方法来恢复这些丢失的消息。在本文中,我们将深入研究可用于检索已删除短信的选项,并…...

Java电子招投标采购系统源码-适合于招标代理、政府采购、企业采购、等业务的企业

项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及审…...

springBoot的实现原理;SpringBoot是什么;使用SpringBoot的核心功能;springBoot核心注解以及核心配置文件

文章目录 springBootspringBoot的实现原理什么是 Spring Boot?SpringBoot是什么为什么要使用springBootSpring Boot的核心功能Spring Boot 主要有如下优点: SpringBoot启动过程-流程Spring Boot 的核心注解是哪个?什么是 JavaConfig&#xff…...

logback-spring.xml详解

《springboot使用logback日志框架超详细教程》文中,filter中最重要的两个过滤器LevelFilter(日志级别精确匹配)、ThresholdFilter(阈值过滤) 的描述非常准确: springboot使用logback日志框架超详细教程_sp…...

【Python】nn.BCEWithLogitsLoss函数详解

nn.BCEWithLogitsLoss() 是 PyTorch 中一个用于二元分类问题的损失函数,它结合了 Sigmoid 层(将输出映射到 [0,1] 范围内)和 Binary Cross Entropy(BCE)损失。这可以避免在正向和反向传播过程中可能出现梯度爆炸或梯度…...

【C++】日期类的实现

在上篇博客中我们已经学习了C中的运算符重载,我们说,操作符只能对于内置类型进行操作,对自定义类型我们需要自己定义函数去实现一系列的操作 那么这篇博客我们就专门把日期这个类单独拿出来写一下它都有哪些有意义的可以重载的运算符&#xf…...

带残差连接的ResNet18

目录 1 模型构建 1.1 残差单元 1.2 残差网络的整体结构 2 没有残差连接的ResNet18 2.1 模型训练 2.2 模型评价 3 带残差连接的ResNet18 3.1 模型训练 3.2 模型评价 4 与高层API实现版本的对比实验 总结 残差网络(Residual Network,ResNet)…...

【深入解析git和gdb:版本控制与调试利器的终极指南】

【本节目标】 1. 掌握简单gdb使用于调试 2. 学习 git 命令行的简单操作, 能够将代码上传到 Github 上 1.Linux调试器-gdb使用 1.1.背景 程序的发布方式有两种,debug模式和release模式release模式不可被调试,debug模式可被调试Linux gcc/g出来的二进制…...

CGAN原理讲解与源码

1.CGAN原理 生成器,输入的是c和z,z是随机噪声,c是条件,对应MNIST数据集,要求规定生成数字是几。 输出是生成的虚假图片。 生成器生成的图片被判别器认为是真实图片,那么标签就是1 其实判别器模型输出的是…...

C#实体类与XML互转以及List和DataTable转XML的使用

引言 在C#开发中,数据的存储和传输是非常常见的需求。使用XML作为数据格式有很多优点,例如可读性强、易于解析等。而实体类、List和DataTable是表示数据模型的常用方式。本文将介绍如何在C#中实现实体类、List和DataTable与XML之间的相互转换&#xff0c…...

uniapp的vue3的模版的setup函数内使用uniapp内置方法

vue2使用方式直接在method同级使用就行,但是在vue3的setup函数内直接使用会报错,本人找了好久,发现vue3需要导入uniapp模块才能使用,具体如下 使用uniapp上拉加载更多方法 <script>import {onReachBottom} from dcloudio/uni-apponReachBottom(() > {console.log(&qu…...

UI自动化的基本知识

一、UI自动化测试介绍 1、什么是自动化测试 概念&#xff1a;由程序代替人工进行系统校验的过程 1.1自动化测试能解决的问题&#xff1f; 回归测试 (冒烟测试) 针对之前老的功能进行测试 通过自动化的代码来实现。 针对上一个版本的问题的回归 兼容性测试 web实例化不同的浏…...

python实现C++简易自动压行

突发奇想&#xff0c;想要将自己的c压行之后交上去。但是苦于手动压行效率太低&#xff0c;在网上搜索压行网站没有找到&#xff0c;突然发现压行不就是检查检查去个换行符吗。于是心血来潮&#xff0c;用python实现了一个简易压行程序。 首先&#xff0c;宏定义等带#的文件不…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

认识CMake并使用CMake构建自己的第一个项目

1.CMake的作用和优势 跨平台支持&#xff1a;CMake支持多种操作系统和编译器&#xff0c;使用同一份构建配置可以在不同的环境中使用 简化配置&#xff1a;通过CMakeLists.txt文件&#xff0c;用户可以定义项目结构、依赖项、编译选项等&#xff0c;无需手动编写复杂的构建脚本…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...