尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Micro-ROS实战:在STM32上跑通ROS2节点,让单片机接入机器人生态

Micro-ROS实战:在STM32上跑通ROS2节点,让单片机接入机器人生态 如果你是在Ubuntu上装过ROS2、然后第一次拿起STM32的开发者大概率会有个困惑ROS2不是跑在电脑上的东西吗单片机怎么可能跟它玩到一起我第一次听到这话也这么想直到做完第一台带运动底盘的机器人——上位机用树莓派跑导航、下位机用STM32控制电机两者之间的数据全靠自己定义串口协议堆了一堆if else。后来发现micro-ROS就干这事儿在MCU上直接跑出一个正儿八经的ROS2节点上位机用ros2 topic list能看到它、能用Topic跟它通信那一刻整个链路才算真正打通。这篇内容不是翻译官方Wiki是我从一块空开发板开始把micro-ROS在STM32上跑通的全过程包括CubeMX配置、库移植、Agent联调以及很多人最关心的Flash、RAM、CPU占用到底是多少。适合已经把ROS2基础装好、手里有一块STM32但不知道怎么下手的人也适合正在纠结“F103到底能不能跑micro-ROS”的朋友。1. 为什么STM32需要ROS2节点先搞清楚micro-ROS解决的真正问题1.1 你早晚会遇到的“上位机–下位机”通信困局先讲一个真实场景。你做了个差速底盘STM32负责采集编码器、算速度、发PWM给电机驱动树莓派或者Jetson负责跑导航算法和路径规划。那么问题来了规划出来的cmd_vel怎么给到STM32STM32测到的轮速怎么传回上位机大多数人的第一版方案是自己定义串口协议比如一帧数据里放一个帧头、类型、长度、数据、校验然后两边各自写解析。这套方案在只有两个话题、几个字段的时候确实能用但一旦你要加里程计、IMU、陀螺仪、机械臂关节状态帧格式开始膨胀排查一个错位问题可能要抓包抓半天。更麻烦的是上位机如果跑的是ROS2生态你这些自定义协议就完全没法直接接进rclcpp/rclpy的发布订阅体系里。哪怕你自己写一个ROS2节点去解析串口本质上还是多了一层人工桥接。micro-ROS解决的问题就是这个它让STM32变成一个真正的ROS2节点直接发布/订阅话题而不是做一个“被转发”的串口设备。上位机用ros2 topic echo /odom看到的就是STM32发出的数据。1.2 micro-ROS到底是什么和ROS2是什么关系直接说结论micro-ROS是ROS2官方生态在MCU微控制器上的实现。你可能听过ROS2和DDS的关系——ROS2的通信底层是DDSDDS又基于RTPS协议这套完整授时机制在只有几十到几百KB内存的MCU上跑不动所以micro-ROS把DDS的体积砍了一大刀只保留MCU场景需要的发布订阅、服务、参数这些功能形成了一套叫XRCEDDS的轻量实现。换句话说STM32上跑的不是一个“完整版ROS2运行时”而是ROS2的一个极轻量客户端它通过一个叫Agent的代理进程跟完整ROS2网络对接。这里要理解一个关键架构micro-ROS系统分两端。一端是跑在STM32上的Client负责采集传感器、控制执行器、运行控制逻辑另一端是跑在Linux上位机上的Agent负责把Client的数据“翻译”成标准ROS2消息接入到完整的DDS网络里。Agent在你的机器人上位机上跑它跟普通ROS2节点之间是标准ROS2通信跟STM32之间则是串口、UDP或WiFi。这个设计很讨巧MCU端不需要跑完整DDS通信栈它只需要跟一个Agent维持长连接Agent把所有脏活累活接了。所以STM32的资源主要花在XRCEDDS 消息序列化上而不需要处理整个DDS网络拓扑。2. 硬件与工具链选型一块板子和一套能用的开发环境2.1 芯片和开发板怎么选很多初学者拿到的第一块板子是STM32F103C8T6也就是“蓝丸”毕竟便宜、教程多。micro-ROS能在这个芯片上跑吗能但非常勉强。F103C8T6只有128KB Flash和20KB RAM按照我的实测经验一个最简单的micro-ROS发布节点加上串口中间件、FreeRTOS之后Flash占用就已经逼近100KBRAM更是紧张稍微加点业务逻辑就可能溢出来。所以这个芯片适合验证“能不能跑”不适合做实际机器人控制器。我更推荐用STM32F407VET6这一档的板子比如正点原子探索者、野火指南者都行资源是512KB Flash 192KB RAM主频168MHz。跑一个带发布和订阅的micro-ROS节点再加上PID控制、编码器读取、电机PWM输出剩余空间还是很充裕。如果你追求的是一步到位STM32H743更好2MB Flash 1MB RAM跑完整一点的多话题系统都没压力。选型时候还有两个细节容易被忽略。第一是板上串口芯片大多数开发板会带CH340或CP2102的USB转串口这直接影响你后续连接Agent的方便程度最好选板载带USB转串口的。第二是外部晶振频率很多F407板子用8MHz晶振也有用25MHz的CubeMX里选错直接导致串口波特率乱掉后面配置文件全部白干。2.2 Keil STM32CubeMX的环境搭建要点我在这个项目里用的工具组合是STM32CubeMX生成工程框架 Keil MDK5编译下载。CLion CMake那套对新手来说门槛偏高CubeMX自动生成的Keil工程不用自己写链接脚本省很多事。CubeMX安装后第一次生成工程前记得先装对应的MCU设备支持包。如果你用的是Keil MDK5打开Package Manager搜索STM32F4系列芯片包装好否则烧录时会报找不到目标芯片。这个坑我踩过明明驱动正常Keil就是识别不了F407后来就是缺了DFP设备包。生成项目时重点检查三处时钟树外部晶振频率按你板子实际情况选比如8MHz然后在Clock Configuration里把SYSCLK拉到168MHz。注意APB1总线时钟是42MHzAPB2是84MHzUSART2挂在APB1上如果這個时侯配置错串口波特率会整体漂移。串口选USART2PA2 TXPA3 RX波特率设1152008位数据无校验1位停止位。这个配置跟Agent启动参数要完全一致。FreeRTOS直接用CMSIS_V2版本新建一个默认任务比如叫defaultTask这个是后面放micro-ROS主循环的容器。生成到Keil工程之后还要在魔术棒Options for Target里把微库MicroLIB勾上。不勾的话printf重定向可能浮点输出有问题后面调试打日志会很痛苦。3. Agent与Client协作原理micro-ROS通信链路拆解3.1 DDS在MCU上到底跑了个什么在深入代码之前我觉得有必要先把通信原理讲透。如果你只照着例子把程序跑通了后面遇到问题还是会一头雾水。完整的ROS2系统里每个节点都需要通过DDS进行发现、匹配、收发数据。DDS发现过程很复杂节点上线后要发SPDP报文寻找匹配还要在网络上交换QoS策略。这些在树莓派上完全没问题但在STM32上就太重了。micro-ROS采用的策略是“中间人桥接”。STM32上的Client不直接参与ROS2网络的DDS发现它只跟唯一的Agent建立一条稳定通道。这条通道上跑的RTPS格式是精简过的所以叫XRCEDDS。CLient把消息序列化后直接扔给AgentAgent收到后再作为“代理”把消息以标准RTPS格式转发到ROS2 DDS网络中。你从ros2 topic list看到的那些话题其实是Agent替你发布的。理解这一点非常重要节点名字、话题名、消息类型这些信息客户端必须提前和Agent约定好。Agent启动时的参数和客户端库的版本必须匹配如果Client用的是humble分支的micro-ROS库Agent却装成了foxy版本连接后十有八九会出现“Client lost”这类反复重连。3.2 Client和Agent的传输链路串口、UDP还是其他micro-ROS支持多种物理传输最常见的是串口和UDP。我建议调试阶段优先用串口原因很简单STM32开发板几乎都带USB转串口一根线插上就是一条调试链路同时还能看printf日志不用配网络。串口链路的通信模型是Client端有一个后台接收函数从串口收字节缓冲成完整报文执行器在spin循环里调用XRCEDDS的接收函数如果有完整报文就丢给回调处理有数据要发时就通过串口发送。UDP模式适合你的STM32带了以太网模块或者ESP8266这种WiFi模块的场景。优势是带宽大、不占串口而且Agent可以跑在局域网里另一台机器上。但UDP不可靠实际使用中丢包重传逻辑要依赖RTPS协议本身对实时性要求高的时候不如串口稳。我自己的建议很直接车上跑串口仿真和远程调试用UDP。串口链路的稳定性经过验证而且上位机和STLM32通常装在同一台机器人里距离也就几厘米没必要为了省一根线引入网络变量。3.3 micro-ROS执行器和ROS2回调分组有什么区别如果你已经学过ROS2的rclcpp会知道里面有CallbackGroup、单线程执行器、多线程执行器的概念。到了micro-ROS这里这些机制全部被简化了。micro-ROS客户端库用的是rclc_executor它是一个单线程、轮询式的执行器。里面可以挂多个订阅、定时器、服务每次调用rclc_executor_spin_some()会把所有已经收到数据的订阅回调、到期的定时器回调按挂载顺序执行一遍。这意味着没有ROS2里的多线程执行器所有回调都在一个FreeRTOS任务里排队执行。这个差异直接影响你的程序设计。在完整ROS2里你可以在回调里做耗时操作反正有多线程兜底在micro-ROS里回调阻塞多久整个节点就卡多久。比如订阅回调里做一个耗时20ms的卡尔曼滤波那么定时器回调即使到期了也要排20ms后面。解决办法有两个一是把耗时算法拆出来放到另一个FreeRTOS任务里micro-ROS回调只负责收数据、置标志位二是开两个micro-ROS任务每个任务跑一个独立的executor共享数据加锁保护。4. 从CubeMX到第一个Publisher节点完整实操路径4.1 生成带FreeRTOS的基础工程我用的是STM32CubeMX 6.x版本芯片选STM32F407VET6。新建工程后在System Core里把SYS的Debug设为Serial Wire方便用ST-Link调试。然后在Connectivity里打开USART2模式设为Asynchronous波特率、引脚参数跟前面一致。再把Middleware里的FreeRTOS勾上选CMSIS_V2。时钟树我专门强调一下这是新手最容易翻车的地方。HSE外部晶振频率选8MHz后倍频系数通常会自动算出来你要确认最终SYSCLK、AHB、APB1、APB2这四个时钟显示正常。APB1是42MHz因为USART2挂在这条总线上这个值直接决定波特率是否准确。以前我用25MHz晶振的板子却按8MHz配置结果串口打印全是乱码排查了半天。配置完成后Project Manager里选Toolchain为MDK-ARM V5生成代码。打开Keil工程后第一件事是确认MicroLIB勾选然后在main函数里先做一个串口printf测试输出一句“Hello from STM32”验证基本链路没问题。4.2 把micro-ROS库移植进Keil工程库的获取方式我推荐直接克隆官方仓库micro_ros_stm32cubemx_utils里面有一个middleware文件夹包含microros_transports、micro_ros_utilities这些关键模块。整个移植过程说白了两步把这两个子模块的源文件加进Keil工程然后配置好串口和DMA的绑定。具体操作时我把middleware整个目录复制到工程根目录然后在Keil的Manage Project Items里新建一个Group把middleware_usart.c、rclc_lib相关的.c文件加进去。头文件路径要添加middleware/include、middleware/lib/include这些。接下来改串口配置。打开microros_transports.h你会看到类似宏定义需要把串口句柄、GPIO、RCC时钟改成你自己工程里的#define MICROROS_SERIAL_DEVICE USART2 #define MICROROS_SERIAL_RCC __HAL_RCC_USART2_CLK_ENABLE()在middleware_usart.c里核心是封装三个函数提供给上层init、send、recv。大致逻辑是这样static int usart_init(void) { MX_USART2_UART_Init(); __HAL_UART_ENABLE_IT(huart2, UART_IT_IDLE); HAL_UART_Receive_DMA(huart2, rx_dma_buf, RX_BUF_SIZE); return 0; } static bool usart_send(const uint8_t *buf, size_t len) { HAL_UART_Transmit_DMA(huart2, (uint8_t*)buf, len); return true; } static int usart_recv(uint8_t *buf, size_t len) { // 把DMA缓冲区里积累的字节拷贝给上层 return copydata_from_dma(buf, len); }这里要注意一点micro-ROS的serial transport要求接收是能力是“非阻塞、轮询状态获取”所以代码里通常配合串口的空闲中断IDLE和DMA一起用串口收到一帧数据后把DMA缓冲区中的数据搬出来。如果你图省事直接裸用阻塞式HAL_UART_Receive会导致executor永远停在那里等数据发布和订阅全卡死。4.3 写一个发布Int32话题的节点代码移植完中间件后就可以写节点了。我在默认任务里放一个循环调用micro-ROS的初始化流程然后进去executor循环。首先包含必要头文件#include rcl/rcl.h #include rclc/rclc.h #include rclc/executor.h #include std_msgs/msg/int32.h然后声明全局对象并创建节点、发布者、定时器rcl_publisher_t publisher; rcl_timer_t timer; rcl_node_t node; rclc_executor_t executor; std_msgs__msg__Int32 send_msg; void timer_callback(rcl_timer_t *timerv, int64_t last_call_time) { (void)last_call_time; if (timerv ! NULL) { send_msg.data; rcl_publish(publisher, send_msg, NULL); } }在任务主循环里初始化和执行void AppTask(void *argument) { // 初始化串口传输 rmw_uros_set_custom_transport( true, NULL, usart_init, usart_send, usart_recv ); allocator rcl_get_default_allocator(); rclc_support_init(support, 0, NULL, allocator); rclc_node_init_default(node, stm32_pub_node, , support); rclc_publisher_init_default(publisher, node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32), stm32_pub_msg); rclc_timer_init_default(timer, support, RCL_MS_TO_NS(200), timer_callback); rclc_executor_init(executor, support.context, 1, allocator); rclc_executor_add_timer(executor, timer); while(1) { rclc_executor_spin_some(executor, RCL_MS_TO_NS(50)); } }这个例子里我发布的是Int32类型话题名叫stm32_pub_msg每200ms发一次自增计数。rclc_executor_spin_some每次最多运行50ms不会一直死等这样FreeRTOS还能调度其他任务。4.4 编译烧录与Agent侧启动代码写完后Keil里直接Build如果报缺少头文件多半是micro-ROS库的include路径没加全。烧录之后先别急着看ROS2先用串口调试助手确认STM32的串口有没有printf输出。此时如果没有输出大概率是时钟配置错或者MicroLIB没勾。确认STM32端串口正常后在Ubuntu上启动Agent。假定你已经装好了micro_ros_agent的humble版本source /opt/ros/humble/setup.bash ros2 run micro_ros_agent micro_ros_agent serial --dev /dev/ttyUSB0 -b 115200/dev/ttyUSB0是USB转串口设备具体是ttyUSB多少用ls /dev/ttyUSB*查看。Agent启动后会看到类似Creating new client的行说明STM32已经成功连接上来了。这时候再开一个终端ros2 node list ros2 topic list ros2 topic echo /stm32_pub_msg能看到节点名stm32_pub_node、话题名stm32_pub_msg并且echo能持续收到递增的Int32数据恭喜你这个STM32已经从物理上变成ROS2网络里的一个活跃成员了。5. 上位机联调确认节点跑通之后还有一堆细节5.1 用ros2 cli验证整条链路节点连上之后你可以在上位机发一个话题给STM32试订阅。比如命令ros2 topic pub /stm32_set_led std_msgs/msg/UInt8 {data: 1} --once前提是STM32端创建了对应的订阅者。我这里举一个带订阅节点的完整例子用Twist消息控制电机#include geometry_msgs/msg/twist.h geometry_msgs__msg__Twist sub_msg; void sub_callback(const void *msgin) { const geometry_msgs__msg__Twist *msg (const geometry_msgs__msg__Twist*)msgin; printf(linear.x %.2f, angular.z %.2f\n, msg-linear.x, msg-angular.z); } // init阶段 rclc_subscription_init_default(subscriber, node, ROSIDL_GET_MSG_TYPE_SUPPORT(geometry_msgs, msg, Twist), cmd_vel); rclc_executor_add_subscription(executor, subscriber, sub_msg, sub_callback, ON_NEW_DATA);这样你在上位机执行ros2 topic pub /cmd_vel geometry_msgs/msg/Twist {linear: {x: 0.5}, angular: {z: 0.1}} --onceSTM32串口就能打印出对应的数据。到这里一个双向通信的最小系统就完整了。5.2 联调中必踩的版本坑和权限坑第一个坑是Agent和Client版本不一致。micro-ROS的Client库和Agent之间没有所谓“绝对兼容”我试过用foxy的Agent去连一个humble版本库编译出来的STM32固件现象就是Agent启动后提示连接建立但没几秒就报Client lost反反复复。后来统一了两端的ROS2版本才好。所以建议从头到尾都用humble这也是目前ROS2生命周期比较稳定、教程最多的版本。第二个坑是串口权限。新装的Ubuntu上直接ros2 run micro_ros_agent ...访问/dev/ttyUSB0很可能报permission denied。需要把当前用户加入dialout组sudo usermod -a -G dialout $USER然后重新登录一次就生效。这个问题特别隐蔽因为不是报“设备不存在”而是授权失败很多人排查半天串口参数。第三个坑是Agent和STM32的波特率不匹配。启动Agent时-b参数必须和CubeMX里配置完全一致。我习惯设115200一是稳定二是即使线材质量不太好也不容易乱码。如果想提传输速度可以设460800但要注意开发板上的USB转串口芯片型号CH340通常能支持老款CP2102可能不稳定。5.3 QoS匹配导致的消息收不到还有一个常被忽略的点是QoS设置。micro-ROS默认创建发布者节点时QoS用的是默认可靠Reliable模式但如果你的上位机订阅端用的是Best Effort双方QoS不兼容就会出现ros2 topic echo收不到任何数据但ros2 node list确实能看到节点。解决办法是在上位机订阅时显式指定QoSros2 topic echo /stm32_pub_msg --qos-reliability reliable或者你在STM32端把发布者的QoS改成best_effort。建议改成一致即可。我在项目中一般让STM32端保持默认上位机命令里带上参数因为自动驾驶场景下传感器数据用Best Effort更合理但控制指令必须Reliable。6. 资源占用实测Flash、RAM、CPU到底吃了多少6.1 静态编译结果一个节点吞掉多少Flash这里给出我两个实际测试工程的编译结果都是在Keil MDK5、AC5编译器、优化等级-O2条件下。第一个工程是纯Publisher只发布Int32话题不含订阅带FreeRTOS和micro-ROS基础中间件。编译完后Flash占用大约142KBRAM静态占用约38KB。其中micro-ROS库本身占大头包括XRCEDDS协议栈、rclc客户端库、消息序列化代码。第二个工程是Publisher Subscriber都开增加geometry_msgs/Twist订阅Flash占用提高到约158KBRAM静态约41KB。如果你把FreeRTOS任务栈、堆空间算上运行时峰值RAM接近50KB。这对于512KB Flash 192KB RAM的F407来说很轻松但放到F103C8T6的128KB Flash 20KB RAM上就完全不是一回事了。即使你能通过裁剪把Flash压到130KB以内RAM也是硬瓶颈。所以我前面说F103只能做验证真正干活还是F407起步。芯片型号FlashRAMmicro-ROS体验STM32F103C8T6128KB20KB能跑最小Demo裁剪后勉强放下RAM接近上限STM32F407VET6512KB192KB主力之选开发舒适能带业务逻辑STM32H743VIT62MB1MB空间富余可跑多话题多服务6.2 运行时开销用GPIO翻转法测CPU占用静态资源是死的运行时的CPU占用才是更值得关注的。micro-ROS的执行器是轮询式CPU占用率跟你的执行频率、消息大小、串口波特率都有关系。我在任务里放了一个GPIO翻转的探针在调用rclc_executor_spin_some前后各翻转一次再用逻辑分析仪看高电平占比。实测结果是仅发布Int32话题发布频率5Hz串口115200CPU占用率大约2%4%同时订阅Twist话题收到数据后打印一行printfCPU占用率升至7%9%把串口波特率从115200提到460800收发开销略降但差距不明显因为瓶颈主要在消息序列化而不是字节传输。这个数字说明一个道理micro-ROS本身并不吃CPU真正吃CPU的反而是你回调里做的业务逻辑。尤其是printf它是出了名的耗时大户如果在高频回调里直接打印CPU占用率能拉到30%以上。调试时可以用正式部署一定要关掉或者只在状态变化时打。6.3 任务栈和堆的实测8KB栈到底够不够我默认给micro-ROS主任务分配的栈大小是2048 words也就是8KBCortex-M4一个字等于4字节2048 words 8KB。跑了两天后用uxTaskGetStackHighWaterMark()查看剩余栈空间发现只用了约5.2KB剩余2.8KB说明8KB起步是够用的。如果你同时挂了多个订阅、加了service或者消息类型比较大建议从16KB开始跑通后再逐步降低。栈设置过小不会立刻报错往往是运行几十秒后突然hardfault而且每次卡顿位置还不一样极难排查。我的经验是先给足16KB稳定运行后看HighWaterMark再决定能不能降到8KB。堆空间方面micro-ROS默认使用rcl_get_default_allocator()底层就是C库的malloc。FreeRTOS默认堆大小在CubeMX里常常是16KB已经够用。但如果消息频率高、内存碎片化严重可能会出现malloc失败导致节点初始化崩掉。我后来是一套做法初始化时把用到的发布者、订阅者数量尽量控制住不在运行过程中动态创建这样堆的压力会小很多。6.4 减少资源占用的几个实测技巧如果你真的遇到Flash或者RAM不够用的情况以下裁剪方向是验证过有效的。第一关闭不需要的中间件功能。在micro-ROS的构建选项里可以把RCL_COMMAND、RCL_LOGGING的某些冗余功能关掉但Keil工程里手动改宏比较麻烦更实际的做法是从库里删除没有引用的源文件。比如你只做发布不订阅、不用服务那跟subscriber、service相关的.c文件都可以从编译列表里剔除能省十几KB Flash。第二减少消息拷贝。micro-ROS在接收数据时需要一块接收缓冲区很多人直接把缓冲区设成1KB其实根据你的最大消息体来定就好了。Twist消息序列化后大约80字节Int32更小。缓冲区设得越大RSS内存占用越高。第三关闭所有printf重定向的浮点支持。MicroLIB默认不带浮点能省很多Flash代价是不能直接打印浮点。在偶尔需要打印Twist数据时我用sprintf(buf, %d.%d, (int)val, (int)(val*100)%100)这种方式手工转成整数打印Flash占用少了近10KB速度还更快。7. 跑通之后怎么继续进阶设计的一些建议7.1 从单话题到多话题共享数据的保护跑通一个Publisher之后你自然会想加里程计、加服务、加参数。多话题带来的第一个问题就是数据共享。在micro-ROS的回调里你直接写一个全局变量然后在另一个FreeRTOS任务里读它这看起来没问题实际在Cortex-M4上会有数据一致性的隐患。比如你在回调里更新了一个64位的float值主任务读的时候可能读到一半出现“撕裂”。解决办法是加一个临界区保护最简单的就是taskENTER_CRITICAL()/taskEXIT_CRITICAL()开销极小只关中断几个周期比互斥量轻量多了。7.2 参数和服务micro-ROS也能做得有模有样micro-ROS不仅支持发布订阅还支持ROS2服务Service和参数。控制机器人时我用得最多的是Service比如通过一个自定义服务去触发STM32的初始化或者校准编码器零点。创建服务和创建发布者的流程很像只是回调函数要处理请求和响应。需要注意的一点是micro-ROS的服务单次只能处理一个请求命令并发时后面的请求会排队。对嵌入式节点的业务量来说完全够用但如果你上位机有多个节点同时向STM32发服务还是尽量让业务逻辑收敛在一个控制节点里。7.3 生命周期和重连策略如果STM32掉线了怎么办实际跑车的时候Agent和Client不会总是那么和谐。CLient如果一段时候没收到Agent的心跳或者连接中断执行器依然会继续执行但数据就发不出去了而且重连不是自动的。我的做法是在主循环里每5秒调用一次rmw_uros_ping_agent()如果不通就等几秒重新执行rclc_support_init到rclc_publisher_init这一整套初始化流程。相当于给STM32加了一个“自动重连”的能力。这个代码很值得写因为在机器人上你经常先启动Agent再给MCU上电没有重连逻辑的话就必须手动复位开发板。跑通这一个最小系统之后后面扩展的方向非常多把执行器放到定时器中断里做高频率控制回路或者把内存分配器替换成静态池方案又或者加一个CAN口连电机驱动器。我个人实际做项目时最大的体会是micro-ROS把MCU接入ROS2生态的门槛降了一个量级它不再是上位机和单片机之间的一道协议翻译题而是一个普通ROS2节点该怎么挂进整个系统的问题。真正想让它稳定跑起来对嵌入式端资源的管理、进程任务划分和通信可靠性反而比ROS2本身的知识更关键。希望这份从零开始的经验能帮你少走一点弯路。
返回列表