ROS学习笔记之八:尝试在FreeRTOS中使用ROSSerial

STM32 接入 ROS1 的 rosserial 实战记录(存量项目适用) 本文摘要(149字): 针对ROS1存量项目的STM32集成方案,介绍了基于rosserial的通信实现方法。主要内容包括:1)生成STM32可用的ROS消息和服务头文件;2)在MDK工程中配置C/C++混合编译环境;3)通过FreeRTOS任务实现ROS节点功能。特别指出该方案适用于维护已有ROS1系统,而新项目建议采用ROS2+micro-ROS架构。文中详细说明了移植过程中的关键技术点,如Python脚本修改、消息回调处理等,并提供了完整的代码实现示例,帮助开发者在资源受限的STM32平台上实现与RO 阅读详情

我理解 ROSSerial只是为MCU提供了一个和基于ROS主机(上位机)通讯的方式,而MCU要实现的功能还是要自己编写实现,这部分和以往需求一样,那么采用什么程序框架就是不可回避的问题。

现在由于STM32以极优的性价比提供了可以运行RTOS的硬件平台,使用RTOS已经不是一件奢侈的事情了,如果能在RTOS框架下使用ROSSerial应该是编写嵌入式控制程序的福音,故做此尝试。

为了便于实施,也便于围观者理解,还是基于前面的程序修改。

具体构思如下:

  1、构建以下任务:

     A)定时检测 rosserial 信息,并控制 LED 闪烁

     B)自检任务,执行一次后消除

     C)执行命令任务,等待ROS消息,根据消息执行。

  2、创建队列消息:

     在 rosserial 的 Callback 函数中产生队列消息,将收到的动作命令送给执行命令任务。

     因为 Callback 函数应该是在中断中产生的,故使用 xQueueSendFromISR()

     消息队列设计为 2个单元,每个单元 3 字节 :电机命令 PWM  舵机角度

按此定义消息单元数据类型:

typedefstruct

{

      uint8_t u8MotorCmd;

      uint8_t u8Pwm;

      uint8_t u8ServoVal;

}command_type;

 

三个任务如下:

// 任务 A:定时检测 rosserial 消息,控制 LED  闪烁

static voidtaskA(void* arg)

{

      UNUSED(arg);

  pinMode(LED_BUILTIN,OUTPUT);

  g_bLED_On = true;

  digitalWrite(LED_BUILTIN,HIGH);

  gc_i16DisplayTimeCnt = DISPLAY_TIME;

     

  while (1)

  {

    // Sleep for 10 milliseconds.

    vTaskDelay((10L * configTICK_RATE_HZ) /1000L);

 

    if(g_bSelfTest == false)

    {

         nh.spinOnce();                    // 检测rosserial

         gc_i16DisplayTimeCnt--;                       // LED Display

      if(gc_i16DisplayTimeCnt <= 0)

      {

        gc_i16DisplayTimeCnt = DISPLAY_TIME;

        g_bLED_On = !g_bLED_On;

        digitalWrite(LED_BUILTIN,g_bLED_On);

      }

    }

  }

}

这样编写逻辑似乎更清晰了。

// 任务 B:自检

static voidtaskB(void* arg)

{

      UNUSED(arg);

      uint8_t i,j;

     

      g_bSelfTest = true;

 

      for(i = 0; i< MAX_CMD_NO; i++)

      {

             j = 0;

             myServo.writeMicroseconds(correctServo(ga_u8TestCommand[i*4+ j]));

    j++;

   

    vTaskDelay((1000L* configTICK_RATE_HZ) / 1000L);   // 延时  1000ms, 等待舵机操作完成

   

    YM3.setRunDistance(ga_u8TestCommand[i*4+ j]);

    j++;

    YM3.run(ga_u8TestCommand[i*4 +j],ga_u8TestCommand[i*4 + j+1]);

   

    while(YM3.getMotorStat() ==ga_u8TestCommand[i*4 + j])

    {

         vTaskDelay((10L* configTICK_RATE_HZ) / 1000L);   // 延时  10ms  ,每10ms查询一下电机执行是否完成

    }

      }

  g_bSelfTest = false;

 

  vTaskDelete(NULL);

}

看客可以比较一下原来的自检处理逻辑,是不是这个直观了许多?

// 任务 C:执行命令

static voidtaskC(void* arg)

{

      UNUSED(arg);

 

  while(1)

  {

    if(g_bSelfTest== false)

    {

           xQueueReceive(xQueueCommand,&g_sCommand,portMAX_DELAY);

          

           if(g_sCommand.u8ServoVal!= g_ucServoVal)

           {

                  g_ucServoVal= g_sCommand.u8ServoVal;

                  myServo.writeMicroseconds(correctServo(g_ucServoVal));

                  vTaskDelay((1000L* configTICK_RATE_HZ) / 1000L);   // 延时  1000ms, 等待舵机操作完成

           }

           driveMotor(g_sCommand.u8MotorCmd,g_sCommand.u8Pwm);

          

           vTaskDelay((3000L* configTICK_RATE_HZ) / 1000L);   // 运行  3000ms,

          

           driveMotor(BRAKE,0);                 // 停止运行

    }

    else

    {

           vTaskDelay((1000L* configTICK_RATE_HZ) / 1000L);   // 延时  1000ms

    }

  }

}

任务执行也比原来更容易理解,尤其是原来定义的每个命令执行3s的处理,此处用RTOS的延时命令就很直观的处理了,看上去程序在此死等,实际上RTOS已经挂起此任务,执行别的任务(taskA),以保证控制逻辑正确。这就是使用RTOS的优势,调度交给系统了。

初始化(setup)中修改如下:

……..

  // ------ 190612 ---------------

  xQueueCommand =xQueueCreate(QUEUE_ITEM_NUM,QUEUE_ITEM_SIZE);

 

      // create taskA at priority 2

  h_taskA = xTaskCreate(taskA, NULL,configMINIMAL_STACK_SIZE, NULL, 2, NULL);

 

  // create taskB at priority 2

  h_taskB = xTaskCreate(taskB, NULL, configMINIMAL_STACK_SIZE,NULL, 2, NULL);

 

  // create taskC at priority 2

  h_taskC = xTaskCreate(taskC, NULL,configMINIMAL_STACK_SIZE, NULL, 2, NULL);

 

  // check for creation errors

  if (xQueueCommand == NULL || h_taskA !=pdPASS || h_taskB != pdPASS || h_taskC != pdPASS)

  {

    Serial.println(F("Creationproblem"));

    while(1);

  }

 

  // start scheduler

  vTaskStartScheduler();

  while(1); 

}

相应的消息接收处理回调函数修改为:

voidoneWheel_cb( const geometry_msgs::Twist& cmd_msg)

{

  int temp;

  static portBASE_TYPE  xHigherPriorityTaskWoken;

  command_type  sCommand;

 

  if(cmd_msg.linear.x == 0.0)

  {

    sCommand.u8MotorCmd= BRAKE;

    sCommand.u8Pwm= 0;

  }

  else

  {

       if(cmd_msg.linear.x > 0.0)

        {

           sCommand.u8MotorCmd = FORWARD;

           sCommand.u8Pwm = byte(cmd_msg.linear.x);

        }

       else

        {

           sCommand.u8MotorCmd = BACKWARD;

           sCommand.u8Pwm = byte(0 - cmd_msg.linear.x);

        }

      }

 

  temp = int(cmd_msg.angular.z);

      if(temp <0)

      {

       temp = 0;

      }

     

      if(temp >180)

      {

             temp = 180;

      }

     

      sCommand.u8ServoVal = byte(temp);

     

      xQueueSendFromISR(xQueueCommand,&sCommand,&xHigherPriorityTaskWoken);

      if(xHigherPriorityTaskWoken == pdTRUE)

      {

             // 激活任务切换

      }

}

上面那个“激活任务切换”部分还没吃透,暂时空着,其主要作用是在发送队列消息后,启动一次系统任务调度处理,以便等待此消息的任务可以立刻响应,这个在uCOS中是系统自己处理的,在系统的中断服务程序退出时,会自己启动一次任务切换处理。在 FreeRTOS中好像需要显性的操作一下,这个等实际编程时再琢磨。

此时原来Arduino的loop函数没有作用了:

// WARNINGidle loop has a very small stack (configMINIMAL_STACK_SIZE)

// loopmust never block

void loop(){

  // Not used.

}

程序运行全部由FreeRTOS管理了,在Arduino程序中只是体现在这一句:

#include<STM32FreeRTOS.h>     // 190612

应该说还是比在MDK中编写简化了很多。

上述程序编写完成后,只是修改了一些语法错误,程序就实现了原来的功能,编译后资源占用如下:


 

这比上一个程序占用的程序空间大了不少,用了约30k字节,即便这样,应该还是有足够的空间编写功能程序的。

如果真的遇到功能需求复杂,换一个MCU即可,STM32有充足的选择空间,支持STM32Duino的MCU也很多。

至此,已经验证了使用STM32+Arduino环境可以实现 ROS系统的外围功能硬件的构建,下一步可以回归到 ROS,看看如何使用程序实现通过 ROSSerial控制小车。现在测试使用的还是命令行发送。

不过这一关打通了,为后续ROS学习提供了足够的素材,否则我看网上很多人尝试ROS都是基于有限的几个平台,没有变化,关键是成本颇高,削弱了很多人的参与激情。

 

注:程序附在 QQ 群 32438885 的共享文件夹中,供参考。

(程序重点是测试这样是否可行,没有严格处理RTOS函数的返回值,请看客留意!)

STM32+FreeRTOS下混编C/C++的rosserial避坑指南:告别编译报错,保姆级配置流程 本文详细介绍了在STM32+FreeRTOS环境下混编C/C++实现rosserial通信的避坑指南。通过extern "C"包装、工程配置优化和FreeRTOS任务集成等实战技巧,帮助开发者解决混合编译报错问题,完成ROS1与嵌入式系统的高效集成。特别适合处理存量项目的升级改造需求。 阅读详情

相关推荐

Breadbot ROS库:Arduino轻量级rosserial实现

在嵌入式机器人开发中,ROS与微控制器的通信是关键瓶颈。rosserial协议作为ROS官方支持的串口通信标准,通过精简序列化、静态Topic ID映射和状态机驱动解析,实现了资源受限平台(如ATmega328P)上的低延迟、确定性交互。其技术价值在于规避运行时字符串处理开销,将消息序列化压缩至微秒级,并支持发布/订阅、服务调用等核心ROS抽象。典型应用场景涵盖电机控制闭环、多传感器数据融合及电池安全保护等实时任务。本文聚焦breadbot_ros_lib——一个面向Arduino优化的rosserial轻

weixin_36474001的博客 617

STM32CubeIDE + FreeRTOS下集成rosserial:手把手构建你的第一个ROS嵌入式节点

本文详细介绍了如何在STM32CubeIDE和FreeRTOS环境下集成rosserial,构建ROS嵌入式节点的完整流程。从环境配置、工程创建到rosserial库移植与FreeRTOS任务设计,提供了手把手的实践指导,帮助开发者实现ROS与嵌入式系统的无缝通信,特别适合机器人开发中需要低延迟、高响应的应用场景。

weixin_30316097的博客 1475

告别Makefile烦恼:用STM32CubeIDE一站式搞定ROS1 rosserial库的集成与编译

本文详细介绍了如何利用STM32CubeIDE高效集成ROS1 rosserial库,简化嵌入式机器人开发中的编译流程。通过环境准备、C++支持配置、硬件接口实现等步骤,开发者可以摆脱复杂的Makefile配置,专注于业务逻辑开发。文章还提供了性能优化和常见问题解决方案,助力STM32与ROS1的无缝对接。

weixin_42647395的博客 403

NOTES : ROS、FreeRTOS

一、关于ROS: ROS:Robot Operating System,,即机器人操作系统。 和普通OS不一样的是,ROS主要是针对机器人,是基于操作系统之上,提供一系列程序库和工具以帮助软件开发者创建机器人应用 软件。它提供了硬件抽象、设备驱动、库函数、可视化、消息传递和软件包管理等诸多功能。ROS遵守BSD开源许可协议。 ROS是基于Linux系统之上的运行的一套系统 FreeRTOS是开发micro ROS和Micro XRCE-DDS应用程序的理想选择 二、关于FreeRTO..

woodgril的博客 9213

ROSSerial实战:基于VCP虚拟串口打通STM32与ROS的通信壁垒

本文详细介绍了使用ROSSerial框架,通过USB虚拟串口(VCP)实现STM32与ROS系统稳定通信的实战方案。文章对比了传统USART的不足,阐述了VCP在速度、稳定性和可靠性上的显著优势,并提供了从环境搭建、STM32配置、关键代码修改到连接调试的完整步骤,帮助开发者高效打通嵌入式硬件与ROS的通信壁垒。

weixin_28278377的博客 195

ROSSerial实战:基于STM32与VCP的ROS机器人底层通信全解析

本文详细解析了如何利用STM32微控制器与USB虚拟串口(VCP)构建ROS机器人的底层通信节点。通过rosserial协议栈,将STM32高效接入ROS生态系统,实现与上位机(如运行ROS的工控机)的稳定数据交换。内容涵盖从ROS环境搭建、STM32工程配置(包括关键的外设设置与代码修改),到最终通信验证的全流程实战指南,并提供了常见的避坑方案与优化建议。

weixin_29169505的博客 236

ROS与STM32通信(一)-rosserial

rosserial是ROS中的一个重要模块,它实现了ROS通信协议与各类嵌入式硬件平台之间的桥接,大大简化了ROS在底层硬件上的移植和应用。rosserial通过消息序列化和常用串行通信接口,实现了ROS主机和嵌入式客户端之间的消息交互,为各种嵌入式平台提供了C++和Python的ROS客户端库,使得在这些硬件上也能方便地使用ROS的通信架构来进行节点管理、话题通信和服务调用。rosserial还支持动态主题和服务,以较小的代码占用实现ROS功能,具有很强的可移植性。出现以下内容则表示运行正常。

weixin_51002159的博客 5396

rosserial_mbed_lib:ARM Cortex-M上的轻量ROS 1串行通信库

rosserial 是 ROS 1 中用于资源受限设备的轻量级串行通信协议,其核心原理是基于帧同步、CRC校验与静态Topic ID映射的二进制消息交换机制。该技术显著降低嵌入式端内存与CPU开销,具备确定性实时响应能力,适用于无操作系统或RTOS环境。典型应用场景包括机器人电机控制板、无人机传感器节点及工业PLC ROS网关等边缘智能终端。本文聚焦于专为 mbed OS 和 ARM Cortex-M 微控制器(如 STM32、LPC、RA 系列)深度优化的 rosserial_mbed_lib 实现,详解

weixin_35749796的博客 188

ROS2和FreeRTOS区别和联系

(Robot Operating System)是。FreeRTOS与ROS 2本质是。:FreeRTOS是。

marico123的博客 409

还在用串口?手把手教你用STM32 USB虚拟串口(VCP)搞定ROS1 rosserial通信(附代码)

本文详细介绍了如何利用STM32 USB虚拟串口(VCP)替代传统串口,优化ROS1 rosserial通信性能。通过实战配置和代码示例,展示了VCP在带宽、稳定性和布线简化方面的显著优势,特别适合高频传感器数据传输和多节点通信场景,帮助开发者提升机器人系统性能。

weixin_33674976的博客 418

2024“华为杯”中国研究生数学建模竞赛(A题)深度剖析_数学建模完整过程+详细思路+代码全解析

目标是优化风力涡轮机的功率调度,使其在给定的实时风速数据下,最小化涡轮机关键组件(如塔架和主轴)的疲劳损伤。问题的挑战在于,考虑通信延迟和测量噪声的同时,要确保功率输出与风速变化的响应快速且准确。

2401_82549447的博客 6627

【杰发科技AC7802x测评】AC7802 + FreeRTOS+gcc实现Ros serial 控制电机速度

转速控制是计算出转速差值后经过PID计算,得到PWM占空比,输出给电压调制电路,电压调制电路输出对应电压,使直流电机产生对应扭矩达到一定的转速。电机转动带动正交编码器,产生经过正交编码脉冲,转速模块检测正交编码值变化规律,计算出转速和方向。本贴将用AC7802来实现直流电机PID调速,并通过串口实现ROS(Robot Operating System, 机器人操作系统) Serial通信,通过ROS可以发送目标速度,由7802实现电机速度控制,并将实时速度返回给ROS。

ic2121的博客 348

数据讲述中国故事!和鲸助力中国综合社会调查(CGSS)数据分析与可视化大赛圆满收官

用数据研究中国问题、总结中国道路、讲述中国故事。和鲸作为协办单位全程支持本次大赛,为中国人民大学中国调查与数据中心实施全套赛事系统,同时提供完备而周全的赛事运营服务。

ModelWhale的博客 1410

ROS学习笔记之七:ROSSerial初试

总体来说,ROS更偏重软件,其涉及的控制、算法都是偏策略或复杂的,但机器人是要和现实世界打交道的,必须有相应的执行机构,使ROS所能做的那些“高、大、上”的工作落地。真正能够和执行硬件打交道、操控起来得心应手的还是MCU,所以如何将MCU控制的硬件和ROS系统相连,可以基于ROS的信息交互机制实现控制和反馈,是学习ROS、基于ROS完成一些任务必须首先化解的问题。 很早我就做了一个4轮全向小车平...

embedream的专栏 1833

【Niagara Vykon N4 】物联网学习 03照明控制及照明时间表

3.1 设计思路 3.2逻辑组件添加 ①依据原有控制照明逻辑,打开palette,找到schedule模块,添加BoolenSchedule。 ②打开kitContrl,找到Util,并添加BoolenSwitch。 ③剪切到原有的逻辑线,并进行逻辑连接,如下图。 ④新建BooleanWritable,命名为Switch,设置参数并进行逻辑连接,若下图。 3.3界面设计 ⑤至此完成了逻辑的设...

weixin_45217107的博客 2863

PID循迹控制算法

前言  让小车进行循迹最重要的是获取车相对于循迹线的位置,关于循迹模块的原理我已经在之前的一篇博客上讲过,如果大家没看过的话可以点此链接:PID循迹模块原理。 PID循迹原理简介 图1 循迹车寻线行走图示 图2 市场常见循迹传感器  PID循迹的原理我们大致可以用常识性思维去思考下,如图1所示为循迹车寻线行走图示,现在小车要按照中间那条黑线循迹行走,如果车头往左偏则需要控制方向盘让车往右转,车头往又偏则需要让车往左转。但是仅仅只有左转和右转的话,车一到左边就向右转,一到右边就向左转,则车会来回在线左右晃动

Dinvent的博客 7万+

ROS - rosserial实战:从零搭建STM32与ROS的VCP通信框架

本文详细介绍了如何从零搭建STM32与ROS的rosserial VCP通信框架。涵盖环境准备、rosserial库配置、STM32硬件设置、USB CDC通信适配、FreeRTOS任务集成及调试优化,帮助开发者实现稳定高效的嵌入式ROS通信。

u6v7w8x的博客 654

【图像去噪】论文精读:Restormer: Efficient Transformer for High-Resolution Image Restoration

论文题目:Restormer: Efficient Transformer for High-Resolution Image Restoration —— Restormer:用于高分辨率图像恢复的高效变压器高效Transformer模型用于图像恢复!由于卷积神经网络 (CNN) 在从大规模数据中学习可泛化的图像先验方面表现良好,因此这些模型已广泛应用于图像恢复和相关任务。最近,另一类神经架构 Transformer 在自然语言和高级视觉任务中显示出显着的性能提升。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 1524

从零构建嵌入式ROS节点:rosserial与STM32的USB-VCP通信实战

本文详细介绍了如何通过rosserial协议和USB-VCP技术实现STM32与ROS系统的高效通信。从环境配置、硬件设置到代码改造,提供了一套完整的嵌入式ROS节点开发方案,显著提升通信速率和稳定性,适用于机器人多传感器数据采集等应用场景。

docker7nomad的博客 370

白鲸优化算法(BWO)详解:从生物灵感 to 工程实践

白鲸优化算法(BWO)是一种新型的群体智能优化算法,模拟白鲸的游泳、捕食和鲸落行为。该算法通过平衡因子控制探索与开发阶段的转换:探索阶段采用正弦/余弦函数模拟白鲸的同步游泳,开发阶段引入莱维飞行增强局部搜索,鲸落阶段通过随机更新避免局部最优。BWO具有参数少、实现简单、收敛速度快等优点,已在多个优化问题上展现出优异性能。其数学模型将白鲸的三种核心行为抽象为位置更新公式,实现了全局搜索与局部开发的自然平衡。

qq_42212808的博客 290

告别混合编译坑:在STM32的MDK项目里优雅嵌入rosserial C++库(FreeRTOS版)

本文详细介绍了在STM32的MDK项目中无缝集成rosserial C++库的实战指南,特别针对FreeRTOS环境下的混合编译问题提供了解决方案。通过合理的项目架构设计、接口隔离和关键配置调整,帮助开发者避免常见陷阱,实现高效的ROS1通信。文章还包含调试技巧和进阶优化策略,适用于存量项目的升级改造。

weixin_30552811的博客 180

40、5G NR射频要求解析

本文详细解析了5G NR射频相关要求,包括参考灵敏度与动态范围的定义、接收机对干扰信号的抗扰性要求(如阻塞、邻道选择性等)、辐射射频要求在FR1和FR2频段的差异,以及多标准无线电基站(MSR)的发展及其对射频要求的影响。内容涵盖测试模型、干扰场景、具体指标和实现挑战,为理解和应用5G NR射频规范提供了全面指导。

qsc901234的博客 245

ros_lib_jade:Mbed平台ROS Jade串口通信库详解

ROSSerial是一种轻量级ROS嵌入式通信协议,通过串行二进制帧实现Linux主机与微控制器间的Topic/Service交互。其核心原理是基于静态内存管理的分层协议栈,规避STL依赖以适配Cortex-M等资源受限MCU。技术价值在于无需完整Linux环境即可接入ROS生态,显著降低机器人底层硬件的开发门槛。典型应用场景包括STM32电机控制板、IMU传感器节点、机械臂关节驱动器等实时性要求高的嵌入式系统。本文聚焦ros_lib_jade这一专为Mbed OS优化的Jade版本实现,深入解析其UART

weixin_35266799的博客 478

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

STM32 ROS控制器底层代码讲解

APP是由FreeRTOS作为嵌入式系统,使用rosserial(roslib库)和ROS1进行交互,使用标准的接口协议,让ROS的开发者不需要去了解底层的通行层,只需要关注底层控制器发布和订阅的节点名称即可,使用rosserial还可以使用ros的参数服务器,在ROS层即可对底层的一些开放参数进行修改(使用方法参考博主的另一篇博客。4、如何编写一个发布节点,发布节点第一步需要创建发布的消息类型变量;第三步创建发布的msgs,订阅的回调函数,发布的节点名称和订阅的节点名称。

qq_36349536的博客 4902

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

上一篇: ROS学习笔记之七:ROSSerial初试
下一篇: 掌上单片机实验室 – 构想(1)
嵌入之梦
博客等级 码龄21年 134粉丝 39原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入之梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值