ROS搭建基于Linux版本: Ubuntu 18.04 LTS
首先需要安装虚拟机和Linux操作系统,安装过程参考百度
1: message: 即消息.机器人需要传感器,传感器采集到的信息,即这儿的message. 假如我们的GPS采集到机器人位置消息,温度计采集到的温度等. 任何数据都能作为message.
2: topic: 假设我们有两个传感器,GPS和温度计.在ROS中我们得给采集到的消息取个名字用来区分不同的message,这就是topic了. 至于怎么取名字,后面的程序可见.
3: node: 节点. ROS中,通常来讲你写的c++或者python程序主函数所在的程序称为一个节点(并不准确,暂时这么理解).
4: package: 一个ROS package包含了你要完成的一个项目的所有文件.
5: workSpace: ROSworkspace,即ROS的工作空间.你当然需要ROS来完成很多不同的项目.你的ROS工作空间是用来存放很多不同package的.
6: publish, subscribe: ROS很大的一个作用就是传递message.为什么要传递消息呢? 打个比方你写了一个程序,用来获得GPS的讯息,写了另外一个程序,用来处理GPS的信息.这时你就是需要把采集到的信息传输到处理用的程序中.信息的传输在ROS中称为publish. 信息的订阅在ROS中称为subscribe.
好了,有了这几个概念,我们就可以开始撸第一个ROS程序了.(可能大佬们觉得还有好多没讲呢,没关系我们慢慢来.)
Packages:
软件包,是ROS应用程序代码的组织单元,每个软件包都可以包含程序库、可执行文件、脚本或者其它手动创建的东西。
Manifest (package.xml):
清单,是对于’软件包’相关信息的描述,用于定义软件包相关元信息之间的依赖关系,这些信息包括版本、维护者和许可协议等。
Launch (file.launch):
launch文件顾名思义就是启动文件,launch文件是描述一组节点及其话题重映射和参数的XML文件。launch允许同时启动多个节点
树莓派系统安装
Ubuntu mate 下载链接
这里使用ubuntu mate 18.04 raspberry版本,考虑到官方镜像Linux是基于Debian9发行的,使用ubuntu mate可以减少很多兼容性带来的麻烦
使用镜像烧录工具将系统拷入SD卡中,启动树莓派
这里分享了两种安装方式:
1- 快速安装:快速配置所有ROS系统以及所需软件
2- 分步安装:理解安装所需要的软件包和熟悉常用的Linux操作
创建工作区
cd ~/
mkdir catkin_ws/
cd catkin_ws
ROS安装器下载
在下载链接中选择保存->下载,然后吧下载好的.sh文件保存到刚创建好的catkin_ws文件夹下,在终端输入
chmod +x ros_install.sh
./ros_install.sh
此时开始进行安装程序,等待安装完成后就可以进入下一个环节
安装ROS主要步骤:
sudo sh -c 'echo "deb https://mirror.tuna.tsinghua.edu.cn/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
sudo apt update
sudo apt install ros-melodic-ros-base
sudo rosdep init
rosdep update
echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
source ~/.bashrc
为什么要用串口通信:
ROS运行在树莓派或其他嵌入式系统平台上,而机器人控制器大部分由底层的单片机或控制器组成的,多数控制算法的PID、滤波器、传感器姿态角都是重复的矩阵迭代运算,占用CPU和内存。这个时候为了降低系统资源使用,就会使用串口来与底层的驱动器通信。这样ROS就可以去处理其他的工作。
在linux上安装ArduinoIDE (网上很多教程,这里不多赘述).
安装rosserial库: 工具->管理库->搜索rosserial->安装.
打开Helloworld例程: 文件->示例->RosserialAdruinoLibary->HelloWorld:
烧录到Arduino中,选择波特率为115200. 完成后测试ROS通信–>
sudo chmod 777 /dev/ttyACM0 //这里我的串口号是ttyACM0
roscore
rosrun rosserial_python serial_node.py /dev/ttyACM0
rostopic echo /chatter
这里终端在不停地打印:
---
data: "hello world!"
---
data: "hello world!"
---
data: "hello world!"
---
data: "hello world!"
到这里就说明串口通信已经成功了,下面开始自己尝试构建ROS通信的node和topic:
ROS通信模式主要是分布式结构,通过节点的话题通信来传递消息和指令,首先需要创建一个Workspace来放置自己的package,便于管理和维护。
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/
catkin_make
执行完成后,在catkin_ws目录下会生成3个文件夹/build、/devel、/src
这里一个工作空间就已经创建完了,后续的package都会存放在这个目录下面
使用命令: catkin_create_pkg 创建一个包
catkin_create_pkg topic_test std_msgs rospy roscpp
topic_test 就是我们需要创建的包名
std_msgs rospy roscpp 是包所需的依赖包,类似于C语言的#include “xxxxx.h”
进入到我们新创建的包中,创建src源文件目录
roscd topic_test
roscd: ROS工具之一,在编译通过后,就可以通过roscd快速进入包所在目录
这时你的终端的目录应该会跳转至:
~/catkin_ws/src/topic_test/:
我们创建一个发布者pub_test.cpp文件,并写入测试代码
touch pub_test.cpp
gedit pub_test.cpp
将下面代码放到pub_test.cpp文件中
#include "ros/ros.h"
#include "std_msgs/String.h"
#include
int main(int argc, char **argv)
{
ros::init(argc, argv, "talker");
ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise("chatter", 1000);
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
std_msgs::String msg;
std::stringstream ss;
ss << "hello world " << count;
msg.data = ss.str();
ROS_INFO("%s", msg.data.c_str());
chatter_pub.publish(msg);
ros::spinOnce();
loop_rate.sleep();
++count;
}
return 0;
}
同样, 创建一个订阅者, 将代码拷贝到.cpp文件中.
touch sub_test.cpp
gedit sub_test.cpp
将下面代码放到sub_test.cpp文件中
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000, chatterCallback);
ros::spin();
return 0;
}
关闭已经打开的编辑框,您在上一教程中使用过catkin_create_pkg,该教程为您创建了package.xml和CMakeLists.txt文件.
现在只需将以下几行添加到CMakeLists.txt的底部
add_executable(talker src/pub_test.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
add_dependencies(talker topic_test)
add_executable(listener src/sub_test.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
add_dependencies(listener topic_test)
进入catkin_ws目录, 重新编译生成
cd ~/catkin_ws
catkin_make
ROS中的通信方式有四种,主题、服务、参数服务器、动作库。每个通信方式都有自己的特点
ROS所有节点间通信都是以话题、订阅的方式,当发布话题者创建一个话题时,订阅者可以通过订阅这个话题来接收消息
经过上一章的试验,我们大概对ROS通信有了一定的概念,接下来我们分析一下在Arduino中,ROS是如何发布话题的:
在Arduino中选择文件-示例-Rosserial Arduino Library -> Helloworld
//Rosserial Arduino Library -> Helloworld
#include
#include
ros::NodeHandle nh;
std_msgs::String str_msg;
ros::Publisher chatter("chatter", &str_msg);
char hello[13] = "hello world!";
void setup()
{
nh.initNode();
nh.advertise(chatter);
}
void loop()
{
str_msg.data = hello;
chatter.publish( &str_msg );
nh.spinOnce();
delay(1000);
}
#include
#include
ros::NodeHandle nh;
std_msgs::String str_msg;
ros::Publisher chatter("chatter", &str_msg);
nh.initNode();
nh.advertise(chatter);
chatter.publish( &str_msg );
nh.spinOnce();
在Arduino中选择文件-示例-Rosserial Arduino Library -> Blink
// Rosserial Arduino Library -> Blink
#include
#include
ros::NodeHandle nh;
void messageCb( const std_msgs::Empty& toggle_msg){
digitalWrite(13, HIGH-digitalRead(13)); // blink the led
}
ros::Subscriber sub("toggle_led", &messageCb );
void setup()
{
pinMode(13, OUTPUT);
nh.initNode();
nh.subscribe(sub);
}
void loop()
{
nh.spinOnce();
delay(1);
}
#include
#include
void messageCb( const std_msgs::Empty& toggle_msg)
{
digitalWrite(13, HIGH-digitalRead(13)); // blink the led
}
ros::Subscriber sub("toggle_led", message);
示例创建了一个toggle_led订阅对象,当接收到来自toggle_led话题发布的消息时,调用message函数。
ros::Subscriber sub("toggle_led", &messageCb );