1 rosserial简介

1.1 Why Arduino and ROS?

        ROS(Robot Operation System)是一个开源机器人操作系统,它是一个分布式的计算架构,集成了底层硬件驱动、节点间通讯、机器人控制、仿真环境和跨平台等功能。

        Arduino主要应用于控制电机驱动和各类传感器(比如超声波、IMU、里程计、电机转速PID控制等),然后通过 ros_topic 和 service、action 等方式与ROS上机位通讯,实现数据的双向传输。

        ROS与Arduino通信方式可以分为两种:

  1. 基于ros的通信机制,如话题,服务,行为等方式,这个时候需要用到rosserial库,需要安装rosserial_arduino。这种方式的好处是不需要知道串口之间的通信协议,直接发布和订阅来传递参数,缺点是不稳定,偶尔出现订阅不上话题,或者与arduino设备连接不上的问题。——不推荐

  2. 直接利用串口通信的规则,即设置好串口的所有配置参数,然后打开串口,通过 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_nodesocket_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 的缓冲区大小和发布服务器/订阅服务器的数量也会有所不同:

芯片型号输入/输出缓冲区发布者/订阅者
ATMEGA168150/150 bytes6/6
ATMEGA328P280/280 bytes25/25
其他的512/512 bytes25/25

        也可以手动更改这些数字和大小,请参阅教程:NodeHandle and ArduinoHardware

        建立通信方式的步骤如下:

  1. 在ubuntu系统中安装Arduino IDE,安装指令为:sudo apt-get install arduino,完成后会生成arduino的文件目录;
  2. 安装rosserial功能包,安装完成后,会生成rosserial_arduino文件夹,安装指令为:sudo apt-get install ros-indigo-rosserial-arduino ;
  3. 将rosserial_arduino文件夹下的ros_lib文件复制到Arduino库目录 sketchbook/libraries
  4. 在arduino中编写程序时,添加 ros.h 头文件后,就可以调用ros类中的成员函数和变量,接着编写节点即可;
  5. 编写完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的通信。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐