目录
1. 环境配置
简要概括上一篇文章https://blog.csdn.net/hhaowang/article/details/104659483中讲述的ROS+Arduino的环境配置和使用方法。
- 安装rosserial软件包
sudo apt-get install ros-kinetic-rosserial-arduino
sudo apt-get install ros-kinetic-rosserial
- 编译catkin_ws项目,source ~/.bashrc
- 安装ros_lib库,其中
<sketchbook>
是arduino的开发环境路径,也可以在~/Arduino路径下打开终端执行删除和安装库操作
cd <sketchbook>/libraries
rm -rf ros_lib
rosrun rosserial_arduino make_libraries.py .
- 重启arduino IDE,可以看到ros_lib的例子。官网上有rosserial_arduino教材,可以结合例子学习。
- 以Arduino为下位机,创建Publisher节点,在ROS上位机运行roscore并连接串口,就可以与Arduino通讯。
roscore
rosrun rosserial_python serial_node.py
串口信息和节点信息就可以显示出来,Arduino与ROS上位机连接成功。
2. 测试例子程序
2.1 hello world发布者节点
Arduino程序:
/*
* rosserial Publisher Example
* Prints "hello world!"
*/
#include <ros.h> //包含ros头文件
#include <std_msgs/String.h> //标准消息类型String.h
//声明节点句柄nh
ros::NodeHandle nh;
//声明std_msgs类型对象str_msg
std_msgs::String str_msg;
//在Arduino层声明一个Publisher,发布话题为chatter,消息为str_msg引用
ros::Publisher pub_str("chatter", &str_msg);
char hello[30] = "hello world! I am a publisher from Arduino!";
void setup()
{
nh.initNode(); //初始化Pub节点
nh.advertise(pub_str); //声明chatter话题
}
void loop()
{
str_msg.data = hello;
pub_str.publish( &str_msg );
nh.spinOnce();
delay(1000);
}
终端命令:
roscore
rosrun rosserial_python serial_node.py
新终端查看节点和话题详情:
rostopic list
rostopic echo chatter
rosnode list
2.2 订阅者节点
Arduino节点代码:
/*
* rosserial Subscriber Example
* Blinks an LED on callback
*/
#include <ros.h>
#include <std_msgs/Empty.h>
ros::NodeHandle nh;
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 setup()
{
pinMode(13, OUTPUT);
nh.initNode();
nh.subscribe(sub);
}
void loop()
{
nh.spinOnce();
delay(1);
}
ROS上位机:
rosrun rosserial_python serial_node.py
节点信息:端口/dev/ttyUSB0 波特率 57600
rqt
使用rqt向话题发布消息,观察arduino
分别以10hz和20hz的频率刷新Arduino LED灯闪烁频率。
2.3 自定义消息类型Point.msg
在ros_lib中已经有了Point.msg的自定义消息,使用Arduino发布消息至point_info话题。
生成的Point.h文件
#ifndef _ROS_msgs_demo_Point_h
#define _ROS_msgs_demo_Point_h
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "ros/msg.h"
namespace msgs_demo
{
class Point : public ros::Msg
{
public:
typedef float _x_type;
_x_type x;
typedef float _y_type;
_y_type y;
typedef float _z_type;
_z_type z;
Point():
x(0),
y(0),
z(0)
{
}
virtual int serialize(unsigned char *outbuffer) const
{
int offset = 0;
offset += serializeAvrFloat64(outbuffer + offset, this->x);
offset += serializeAvrFloat64(outbuffer + offset, this->y);
offset += serializeAvrFloat64(outbuffer + offset, this->z);
return offset;
}
virtual int deserialize(unsigned char *inbuffer)
{
int offset = 0;
offset += deserializeAvrFloat64(inbuffer + offset, &(this->x));
offset += deserializeAvrFloat64(inbuffer + offset, &(this->y));
offset += deserializeAvrFloat64(inbuffer + offset, &(this->z));
return offset;
}
const char * getType(){ return "msgs_demo/Point"; };
const char * getMD5(){ return "4a842b65f413084dc2b10fb484ea7f17"; };
};
}
#endif
Arduino程序:
#include <ros.h>
#include "msgs_demo/Point.h"
//声明句柄
ros::NodeHandle nh;
msgs_demo::Point point; //声明自定义消息类型对象point(x,y,z)-float64
//创建消息发布者,话题名
ros::Publisher pub("point_info", &point);
void setup() {
// put your setup code here, to run once:
//初始化节点信息和发布者
nh.initNode();
nh.advertise(pub);
point.x = 1.0;
point.y = 1.0;
point.z = 1.0;
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available()){
point.x += 0.1;
point.y += 0.2;
point.z += 0.3;
}
pub.publish(&point);
nh.spinOnce();
delay(1000);
}
ROS上位机:
查看消息内容:
rqt_graph:
3. 小结
实现Arduino与ROS通信需要配置各自的开发环境,在ROS端安装串口驱动,并编译catkin_ws项目,生成相应的Arduino库文件;在Arduino端包含响应的消息头文件,声明并定义通信类型topic、action、service,并声明节点信息,如发布传感器信息的发布者、订阅底盘速度的订阅者节点等,烧录之后,在ROS端打开串口驱动,便可以实现ROS与arduino的通信。