文章目录
1 rosserial简介
1.1 Why Arduino and ROS?
ROS(Robot Operation System)是一个开源机器人操作系统,它是一个分布式的计算架构,集成了底层硬件驱动、节点间通讯、机器人控制、仿真环境和跨平台等功能。
Arduino主要应用于控制电机驱动和各类传感器(比如超声波、IMU、里程计、电机转速PID控制等),然后通过 ros_topic 和 service、action 等方式与ROS上机位通讯,实现数据的双向传输。
ROS与Arduino通信方式可以分为两种:
-
基于ros的通信机制,如话题,服务,行为等方式,这个时候需要用到rosserial库,需要安装rosserial_arduino。这种方式的好处是不需要知道串口之间的通信协议,直接发布和订阅来传递参数,缺点是不稳定,偶尔出现订阅不上话题,或者与arduino设备连接不上的问题。——不推荐
-
直接利用串口通信的规则,即设置好串口的所有配置参数,然后打开串口,通过
write()
和read()
函数进行写和读,可以参考:ros_arduino_bridge。但是必须提前获知串口的通信协议,如“M01 30” 表示第一个关节,转30度。该方法上位机与下位机间通信稳定性高。——推荐
1.2 rosserial
rosserial 的作用是让嵌入式系统作为一个ros节点实现与其他节点的直接交互,在架构上更符合ros。rosserial
是用于非 ROS 设备与 ROS 设备进行通信的一种协议。它为非 ROS 设备的应用程序提供了 ROS 节点和服务的发布/订阅功能,是在非 ROS 环境中运行的应用能够通过串口或网络能够轻松地与 ROS 应用进行数据交互。
rosserial
分为客户端和服务器两部分。rosserial客户端运行在运行在没有安装 ROS 的环境的应用中,通过串口或网络与运行在 ROS 环境中的 rosserial服务器连接,并通过服务器节点在 ROS 中发布/订阅话题。
1.2.1 rosserial服务器
rosserial服务器是运行在 ROS 设备中的一个节点,通过串行协议和 ROS 网络建立连接。rosserial服务器有 C++ 和 Python 两种语言的实现。
1、rosserial_python
rosserial_python 是一个基于 Python 的 rosserial 协议实现。它包含主机端 rosserial 连接的 Python 实现,能够自动处理连接支持rosserial 的设备的设置、发布和订阅。
rosserial_python 功能包的 serial_node.py
节点,与启用了 rosserial 的设备通过串口通信。该节点根据存储在设备中的配置信息自动启动订阅者和发布者。如果想要使用不同的串口和波特率运行节点,必须在命令行上指定端口号和波特率,例如在 /dev/ttyACM0
,则必须在命令行上指定参数:
rosrun rosserial_python serial_node.py _port:/dev/ttyACM0 _baud:=57600
也可以将这些参数指定为启动文件的一部分:
<launch>
<node pkg="rosserial_python" type="serial_node.py" name="serial_node">
<param name="port" value="/dev/ttyACM0"/>
<param name="baud" value="57600"/>
</node>
</launch>
2、rosserial_server
rosserial_server功能包包含主机端 rosserial 连接的 C ++实现。它会自动处理已连接的启用rosserial 的设备的设置,发布和订阅。
rosserial_server 提供 serial_node
和 socket_node
两个节点,分别用于串口连接和网络套接字连接,同时提供了相应的launch启动文件。serial_node
与启用了 rosserial 的一个设备通过串口通信,此节点尝试在1Hz的基础上连接和握手,并在重新连接或其他故障时自动重新连接,连接之后,它会根据设备中存储的配置信息启动订阅者和发布者。socket_node
可以与启用了 rosserial TCP 的多个设备通信。
这些节点使用 topic_tools/ShapeShifter 元消息来重新发布来自客户端的消息,而不必在编译时了解它们。这种方法唯一需要注意的是,服务器没有消息的完整文本定义(因为它没有存储在客户机或rosserial协议的一部分中)。它使用rosserial_python 功能包中的
message_info_service.py
节点提供的辅助服务,该服务允许C ++驱动程序查找消息定义和散列字符串,而这些消息定义和散列字符串在编译时是未知的,从而使其可以完全发布来自微控制器的话题。
目前,推荐的使用方法是在消息信息节点旁边启动主服务器节点。启动文件用于启动串行链接。如果未指定端口,则默认为 /dev/ttyACM0
。
启动方法如下:
roslaunch rosserial_server serial.launch port:=/dev/ttyUSB0
还有一个启动文件用于启动socket链接,默认为监听端口11411。
roslaunch rosserial_server socket.launch
仅服务器启动的基本用法是:
rosrun rosserial_server serial_node _port:=/dev/ttyUSB0
缺点:
目前,rosserial_server还在实验中,与rosserial_python相比有一些局限性, 推荐用于高性能应用。此外,它缺少了rosserial_python提供的节点的关键功能,包括参数、日志和服务。如果您需要这些功能,请暂时使用标准的Python服务器。
1.2.2 rosserial客户端库
rosserial_client
包含通用的客户端 rosserial 实现,它是专门为微控制器设计的,用户可以轻松地在各种系统上建立和运行ROS节点。它可以运行在任何处理器上,你需要一个ANSI C++编译器和一个串口连接到运行ROS的计算机。目前,主要软件包包括:
- rosserial_arduino:支持Arduino兼容板,包括UNO、Leonardo、MEGA、DUE、Teensy 3.x和LC、Spark、STM32F1、STM32Duino、ESP8266和ESP32
- rosserial_embeddedlinux:支持嵌入式Linux(如路由器)
- rosserial_windows:支持与Windows应用程序通信
- rosserial_mbed:支持mbed开发平台
- rosserial_tivac:支持TI的启动板,TM4C123GXL和TM4C1294XL
- rosserial_vex_v5:支持VEX V5机器人大脑
- rosserial_vex_cortex:支持VEX Cortex板
- rosserial_stm32:支持基于STM32CubeMX HAL的STM32 mcu
- ros-teensy:支持teensy平台
更多详细使用,请参考:https://github.com/ros-drivers/rosserial
补充:
虽然rosserial可以让非ROS设备轻松的与ROS节点通信,但存在一些限制:
- 发布者和订阅者的数量被限制在25个;
- 对于rosserial_client,序列化和反序列化缓冲区的大小默认限制在512字节,即ROS消息的大小必须小于512字节。
2 rosserial_arduino
Arduino和Arduino IDE是快速方便地硬件编程的好工具。通过使用 rosserial_arduino 功能包,可以直接将ROS与Arduino IDE一起使用。rosserial提供了一个ROS通信协议,该协议通过串口实现了Arduino与运行ROS的设备进行通讯。它把Arduino作为一个ROS节点,用订阅话题的形式接收上位机规划出的理想位置或速度,用发布话题的形式,将电机或传感器的数据发布出去,以此方式将Arduino加入到整个控制系统中。
rosserial_arduino Tutorials 包含使用Arduino的各种传感器和执行器的一些示例。根据所用芯片的不同,rosserial_arduino 的缓冲区大小和发布服务器/订阅服务器的数量也会有所不同:
芯片型号 | 输入/输出缓冲区 | 发布者/订阅者 |
---|---|---|
ATMEGA168 | 150/150 bytes | 6/6 |
ATMEGA328P | 280/280 bytes | 25/25 |
其他的 | 512/512 bytes | 25/25 |
也可以手动更改这些数字和大小,请参阅教程:NodeHandle and ArduinoHardware
建立通信方式的步骤如下:
- 在ubuntu系统中安装Arduino IDE,安装指令为:
sudo apt-get install arduino
,完成后会生成arduino的文件目录; - 安装rosserial功能包,安装完成后,会生成rosserial_arduino文件夹,安装指令为:
sudo apt-get install ros-indigo-rosserial-arduino
; - 将rosserial_arduino文件夹下的ros_lib文件复制到Arduino库目录
sketchbook/libraries
; - 在arduino中编写程序时,添加
ros.h
头文件后,就可以调用ros类中的成员函数和变量,接着编写节点即可; - 编写完arduino中节点后,直接启动rosserial_python中的
serial_node.py
即可;
在Linux下安装Arduino IDE,并安装ros_lib到Arduino IDE环境下,请参考:Arduino & ROS
2.2 创建一个发布者
通过Arduino创建一个 hello world
程序来开始对rosserial的探索,可以通过从Arduino示例菜单中选择 ros_lib->HelloWorld
来打开下面的草图。
程序如下:
/*
* rosserial Publisher Example
* Print "hello world!"
*/
// 作为每个ROS Arduino程序的一部分,需要包含ROS.h头文件和将要使用的任何消息的头文件
#include <ros.h> // 包含ros头文件
#include <std_msgs/String.h> // 标准消息类型String.h
ros::NodeHandle nh; // 创建节点句柄
stg_msgs::String str_msg; // 声明一个消息对象str_msg。其参数data的内容为消息内容。
ros::Publisher chatter("chatter", &str_msg); // 在Arduino层声明一个Publisher,发布话题为chatter,消息为str_msg引用
char hello[13] = "hello world!";
void setup()
{
nh.initNode(); // 初始化Pub节点
nh.advertise(chatter); // 声明chatter话题
}
void loop()
{
str_msg.data = hello;
chatter.publish(&str_msg); //发布一个消息
nh.spinOnce();
delay(1000);
}
编译后在终端运行,分别打开三个终端,输入下面的命令:
$ roscore
接下来,运行rosserial客户机应用程序,将Arduino消息转发给ROS的其余部分。确保使用正确的串行端口:
$ rosrun rossrial_python serial_node.py /dev/ttyACM0
或者,如果您希望能够以编程方式重新启动Arduino,请使用以下命令运行:
$ rosrun rosserial_arduino serial_node.py /dev/ttyACM0
最后,打开一个新的终端窗口,进入:
$ rostopic echo chatter
输出结果如下图示:

2.3 创建一个订阅者
接下来,将创建一个订阅者,可以通过从Arduino示例菜单中选择 ros_lib->Blink
来打开下面的草图。
代码如下:
/*
* rosserial Subscriber Example
* Blinks an LED on callback
*/
#include <ros.h>
#include <std_msgs/Empety.h>
void messageCb( const std_msgs::Empty &toggle_msg)
{
digitalWrite(13, HIGH-digitalRead(13)); // blink the led
}
ros::Subscriber<std_msgs::Empty> sub("toggle_led",&messageCb);
void steup()
{
pinMode(13,OUTPUT);
nh.initNode();
nh.subscriber(sub);
}
void loop()
{
nh.spinOnce();
delay(1);
}
分别在三个端口,运行下面的代码:
$ roscore
运行rosserial客户端应用程序,将Arduino消息转发给ROS的其余部分。确保使用正确的串行端口:
$ rosrun rosserial_python serial_node.py /dev/ttyACM0
最后,使用rostopic触发LED高低电平转换:
$ rostopic pub toggle_led std_msgs/Empty --once
或者在终端输入rqt,在窗口里选择 Container->Message Publisher
,在topic选项里 /toggle_led
,选择后面的加号,就可以改变Arduino LED灯闪烁的频率。具体如下图所示:
小结
实现Arduino与ROS通信需要配置各自的开发环境,在ROS端安装串口驱动,并编译catkin_ws项目,生成相应的Arduino库文件;在Arduino端包含相应的消息头文件,声明并定义通信类型topic、action、service,并声明节点信息,如发布传感器信息的发布者、订阅底盘速度的订阅者节点等,烧录之后,在ROS端打开串口驱动,便可以实现ROS与arduino的通信。