ROS学习过程(一)
1:基础知识
ros即机器人操作系统,用在机器人和自动驾驶较多,有ros1有ros2两个版本。
ros安装:在wiki.ros.org上即可下载安装, 在此网站上也有ROS软件包
ros按模块化设计,分为package和node,一个package中有多个Node,package是node的容器
roscd roscpp 可直接进入对应package的目录。
apt 可下载对应的软件包
ros用catkin工具创建package,举例:
catkin_create_pkg ssr_pkg rospy roscpp std_msgs
ssr_pkg是创建的包名,后面是依赖项,创建好新包后,在CMakeLists.txt会有对包的依赖,package.xml中也有依赖项。
在ssr_pkg的src目录下创建此文件
#include<ros/ros.h>
int main(int argc, char * argv[]) {
ros::init(args, argv, "test_node");
while(ros::ok()) {
puts("hello");
}
return 0;
}
然后在CMakeLists中添加 add_executable(test_node, src/test_node.cpp)指令, 然后使用Cmake编译,也可以使用catkin_make编译。
运行节点:
1:roscore
2:source ~/catkin_ws/devel/setup.bash
3:rosrun ssr_pkg test_node
打印出Hello。
总结:
1、使用catkin_create_pkg创建一个软件包
2、在软件包的src文件夹下创建一个节点的cpp源码文件
3、在节点的源码文件中include包含ROS的头文件
4、构建一个main函数,并在函数的开头执行ros::init()
5、构建while循环,循环条件为ros:ok()
6、在CMakeLists.txt中设置节点源码的编译规则
7、编译运行
2 Topic与Message
node之间通过topic和message进行通信
1:一个ROS节点网络中,可以同时存在多个话题
2 一个话题可以有多个发布者,也可以有多个订阅者
3 一个节点可以对多个话题进行订阅,也可以发布多个话题
4.不同的传感器消息通常会拥有各自独立话题名称,每个话题只有一个发布者。
5的机器人速度指令话题通常会有多个发布者,但是同一时间只能有一个发言人。
std_msgs 标准消息类型 https://index.ros.org/p/std_msgs/#humble
类似结构体,用不同的类型组成自己所需要的消息格式。
#include <ros/ros.h>
#include <std msgs/string.h>
int main(int argc, char *argv[]) {
ros::init(argc,argv,"chao node");
printf("我的枪去而复返,你的生命有去无回!\n");
ros::NodeHandle nh;
// 第一个参数是话题名,第二参数是消息缓存长度,当消息多,缓存不够用,丢弃最早发送的消息,发送端缓存
ros::Publisher pub = nh.advertise<std msgs::string>("test_topic",10);
ros::Rate loop_rate(10); //控制循环内消息发送频率,每秒10次
while(ros::ok()){
printf("我要开始刷屏了!\n");
std msgs::String msg;
msg.data="国服马超,带飞";
pub.publish(msg);
loop_state.sleep();
}
return 0;
}
roscore
rosrun ssr_pkg test_node
rostopic list #查看当前活跃的话题
rostopic echo /test_topic #查看话题内容
总结:
1.确定话题名称和消息类型。
2.在代码文件中包含消息类型对应的头文件。
3.在主函数中通过NodeHandler)大管家发布一个话题并得到消息发送对象。
4生成要发送的消息包并进行发送数据的赋值。
5.调用消息发送对象的publish()函数将消息包发送到话题当中。
rostopic list
列出当前系统中所有活跃着的话题
rostopic echo 主题名称
显示指定话题中发送的消息包内容
rostopic hz 主题名称
统计指定话题中消息包发送频率
创建订阅者节点:
catkin_create_pkg sub_pkg roscpp std_msgs
#include <ros/ros.h>
#include <std msgs/string.h>
void sub_callback(std msgs::string msg) {
printf(msg.data.c str());
printf("\n");
}
int main(int argc, char *argv[]) {
ros::init(argc, argv, "sub_node");
ros::NodeHandle nh;
ros::Subscriber sub = nh.subscribe("test_topic", 10, sub_callback);
while (ros::ok()) {
ros::spinOnce();
}
return 0;
}
spinOnce() 不会主动去接收新消息,而是让程序检查消息队列,如果有新消息,执行一次回调函数。如果没有消息,spinOnce() 什么都不做,继续往下执行。
如果队列里有多条消息,spinOnce() 只会触发一次回调函数,处理其中最早的一条,剩下的消息要等下次调用 spinOnce() 时才会继续处理。spinOnce() 会依次检查所有的订阅者,并调用每个订阅者的回调函数。
ros::spin():程序只处理消息,一直等着新消息来(阻塞)。
rqt_graph 图示显示发布者、订阅者、话题
topic属于handler,不管发布或者订阅了,使用rostopic list都能查到topic。
订阅总结:
1.确定话题名称和消息类型
2在代码文件中include<ros.h>和消息类型对应的头文件
3.在main函数中通过NodeHandler大管家订阅一个话题并设置消息接收回调函数。
4.定义一个回调函数,对接收到的消息包进行处理
5…main函数中需要执行ros::spinOnce(),让回调函数能够响应接收到的消息包。
3 lanuch文件
launch 文件使得一次性启动多个节点变得非常方便,尤其在处理复杂的系统时。如果你的系统中有多个子系统(如传感器、控制器、规划器等),你可以将每个子系统的节点配置到不同的 launch 文件中,并通过 标签将它们组合在一起。这样,你就可以一次性启动整个系统。
<launch>
<!-- 设置一个参数 -->
<param name="robot_speed" value="1.5" />
<!-- 启动发布者节点 -->
<node name="publisher_node" pkg="my_robot_pkg" type="publisher_node" output="screen" />
<!-- 启动订阅者节点 -->
<node name="subscriber_node" pkg="my_robot_pkg" type="subscriber_node" output="screen" />
</launch>
roslaunch my_robot_pkg my_robot.launch
1.使用launch文件,可以通过roslaunch指令一次启动多个节点。
2.在launch文件中,为节点添加output=“screen"属性,可以让节点信息输出在终端中。(ROS WARN不受该属性控制)
3.在launch文件中,为节点添加launch-prefix="gnome-terminal -e属性,可以让节点单独运行在一个独立终端中。