赞
踩
使用Autolabor官方入门教程,笔记内容为注意事项
首页 - Autolabor开源ROS机器人底盘 - 官方网站
_______________________________________________________
例如在生活中,我们在家里有一个放零食的箱子,而操作服务器就是这个箱子,无论是使用者还是开发者都可以共同使用他。
1.话题通信 是ROS中使用频率最高的一种通信模式,话题通信是基于发布订阅模式的,也即:一个节点发布消息,另一个节点订阅该消息
雷达------->导航(计算)-------->底盘
在传递消息和传递运动控制指令时,就使用了话题通信,那么
雷达就是发布, 导航是订阅发布,底盘是订阅。
简单的三要素,发布 - 订阅 - 中间要素
角色----> 流程 ----> 注意
(1)角色:
1. master -----> 管理者(媒婆)
2. talker ------>发布者 (男方)
3. listner ------->订阅者 (女方)
(2)流程 :
master 可以根据话题 建立发布者和订阅者之间的连接
0. 男方提交信息 (房,手机号) ——————发布者比订阅者信息多
1. 女方提交信息 (房)
2. 媒婆把男方电话发给女方
3. 女方打电话给男方(房 连接)
4. 男方响应(加微信/给微信)
5. 女方加男方微信
(3)注意:
1.使用的协议由RPC和TCP;
2.步骤1和步骤0没有顺序关系
3.talker 和 listener可以存在多个
4.建立连接后,master就可以关闭了
5.上述流程已经封装,直接调用就好
—————————————————————————
我们要设置 发布 和 订阅方(分别进行)- (我们的实操部分只进行C++实现案例)
接下来 将从头开始一一介绍(VScode的配置请参照上面的链接进行修改,否则无法正常调试)
-----------------
(1)建立工作空间
建立 demo02_ws 工作空间
键入 code. 可以直接用vs打开工作空间
--------------------
(2)添加包 (头文件)---第一次为文件名,第二次为我们添加的包(后面服务可作修改)
-----------------------------
(3)新建一个发布者文件(写代码的位置,在src目录下新建一个cpp文件)
内容如下:
- /*
- 需求: 实现基本的话题通信,一方发布数据,一方接收数据,
- 实现的关键点:
- 1.发送方
- 2.接收方
- 3.数据(此处为普通文本)
- PS: 二者需要设置相同的话题
- 消息发布方:
- 循环发布信息:HelloWorld 后缀数字编号
- 实现流程:
- 1.包含头文件
- 2.初始化 ROS 节点:命名(唯一)
- 3.实例化 ROS 句柄
- 4.实例化 发布者 对象
- 5.组织被发布的数据,并编写逻辑发布数据
- */
- // 1.包含头文件
- #include "ros/ros.h"
- #include "std_msgs/String.h" //普通文本类型的消息
- #include <sstream>
-
- int main(int argc, char *argv[])
- {
- //设置编码
- setlocale(LC_ALL,"");
-
- //2.初始化 ROS 节点:命名(唯一)
- // 参数1和参数2 后期为节点传值会使用
- // 参数3 是节点名称,是一个标识符,需要保证运行后,在 ROS 网络拓扑中唯一
- ros::init(argc,argv,"talker");
- //3.实例化 ROS 句柄
- ros::NodeHandle nh;//该类封装了 ROS 中的一些常用功能
-
- //4.实例化 发布者 对象
- //泛型: 发布的消息类型
- //参数1: 要发布到的话题
- //参数2: 队列中最大保存的消息数,超出此阀值时,先进的先销毁(时间早的先销毁)
- ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",10);
-
- //5.组织被发布的数据,并编写逻辑发布数据
- //数据(动态组织)
- std_msgs::String msg;
- // msg.data = "你好啊!!!";
- std::string msg_front = "Hello 你好!"; //消息前缀
- int count = 0; //消息计数器
-
- //逻辑(一秒10次)
- ros::Rate r(1);
-
- //节点不死
- while (ros::ok())
- {
- //使用 stringstream 拼接字符串与编号
- std::stringstream ss;
- ss << msg_front << count;
- msg.data = ss.str();
- //发布消息
- pub.publish(msg);
- //加入调试,打印发送的消息
- ROS_INFO("发送的消息:%s",msg.data.c_str());
-
- //根据前面制定的发送贫频率自动休眠 休眠时间 = 1/频率;
- r.sleep();
- count++;//循环结束前,让 count 自增
- //暂无应用
- ros::spinOnce();
- }
-
-
- return 0;
- }
------------------------
(4)在 CmakeLists 里面修改参数 (映射名字和定义名字最好一样)
修改下面两处
(1)
(2)
然后shift+ctrl+b调试看看有没出错
-----------------------------------------
(5)启动ros核心 roscore rosrun rostopic(下面还会有具体说明)
进入工作空间的方法:
————————————————————————————————————
(1)新建订阅方文件(在src文件里)
具体内容:
- /*
- 需求: 实现基本的话题通信,一方发布数据,一方接收数据,
- 实现的关键点:
- 1.发送方
- 2.接收方
- 3.数据(此处为普通文本)
- 消息订阅方:
- 订阅话题并打印接收到的消息
- 实现流程:
- 1.包含头文件
- 2.初始化 ROS 节点:命名(唯一)
- 3.实例化 ROS 句柄
- 4.实例化 订阅者 对象
- 5.处理订阅的消息(回调函数)
- 6.设置循环调用回调函数
- */
- // 1.包含头文件
- #include "ros/ros.h"
- #include "std_msgs/String.h"
-
- void doMsg(const std_msgs::String::ConstPtr& msg_p){
- ROS_INFO("我听见:%s",msg_p->data.c_str());
- // ROS_INFO("我听见:%s",(*msg_p).data.c_str());
- }
- int main(int argc, char *argv[])
- {
- setlocale(LC_ALL,"");
- //2.初始化 ROS 节点:命名(唯一)
- ros::init(argc,argv,"listener");
- //3.实例化 ROS 句柄
- ros::NodeHandle nh;
-
- //4.实例化 订阅者 对象
- ros::Subscriber sub = nh.subscribe<std_msgs::String>("chatter",10,doMsg);
- //5.处理订阅的消息(回调函数)
-
- // 6.设置循环调用回调函数
- ros::spin();//循环读取接收的数据,并调用回调函数处理
-
- return 0;
- }
-------------------------------
(2)修改 CmakeLists
与发布者相同,对比着上面修改一下名称即可
-------------------------------
(3)启动命令行
与上面相同,同时启动3个命令行
但是这次最后一个也是rosrun启动
---------------------------------
注意事项在所给的课件里面有提到
如果要使用计算图查看,就再建立一个命令行
就可以查看了
-----------------------------------------------
(1)在上面的基础上继续完成,建立一个新的文件夹和一个个人文件
(msg 与 person.msg)
内容如下:
(2)接着,进行配置 (两处)
package.xml
CmakeList
我们要配置依赖关系
接着编译一下,可以生成我们过程中需要的文件
——————————————————————————
1.前置步骤 配置vscode
在终端中打开
(2)新建一个自定义发布文件(仍然在之前建立的plu包下的src文件)
具体内容如下:
- #include "ros/ros.h"
- #include "plumbing_pub_sub/Person.h"
-
- int main(int argc,char *aegv[])
- {
- setlocale(LC_ALL,"");
- //1 初始化节点
- ros::init(argc,argv,"banZhuRen");
- //2 创建句柄
- ros::NodeHandle nh;
- //3 创立发布对象
- ros::Pulisher pub = nh.advertise<plumbing_pub_sub::Person>("liaoTian",10);
-
- // 4-1 创建发布数据
- plumbing_pub_sub::Person person;
- person.name = "张三";
- person.age = 1;
- person.height = 1.73;
- // 4-2 创建发布频率
- ros::Rate rate(1);
- // 4-3 循环发布
- while(ros::ok())
- {
- //修改被发布数据
- person.age+=1;
- //数据发布
- pub.publish(person);
- ROS_INFO("发布消为:%s,%d,%.2f",person.name.c_str(),person,age.c_str(),person.height.c_str());
- //休眠
- rate.sleep();
- // 最好写
- ros::spinOnce();
-
- }
-
-
- return 0;
- }
接下来的内容与上面一样,但是cmakelists里面多配置一个
添加完成后再编译一下
-----------------------
(3)运行
roscore
-------------------------------------------
对于订阅方也相同
新建一个文件,然后写内容
- void doPerson(const plumbing_pub_sub::Person::ConstPtr& person)
- {
- ROS_INFO("订阅消息为:%s,%d,%.2f",person.name.c_str(),person,age.c_str(),person.height.c_str());
- }
- int main(int argc.char *argv[])
- {
- setlocale(LC_ALL,"");
- ros::init(argc,argv,"jiaZhang");
- ros::NodeHandle nh;
- ros::Subscriber sub = nh/subscribe("liaoTian",10,doPerson);
-
- ros::spin();
- }
Cmakelist的三个配置也一样
自定义与官方的区别在于,多了一个配置,其它的东西都是大同小异
—————————————————————————————————————
服务通信也是ROS中一种极其常用的通信模式,服务通信是基于请求响应模式的,是一种应答机制。也即: 一个节点A向另一个节点B发送请求,B接收处理请求并产生响应结果返回给A。
机器人巡逻过程中,控制系统分析传感器数据发现可疑物体或人... 此时需要拍摄照片并留存
定义srv 文件内的可用数据类型与 msg 文件一致,且定义 srv 实现流程与自定义 msg 实现流程类似:
按照固定格式创建srv文件
编辑配置文件
编译生成中间文件
----------------------------------------------
接下来为详细操作:
(1)创建新的功能包
新建服务文件夹和文件(srv 与 Addints.srv)
package 和 Cmakelist下更改配置
--------------------------------------
在 src 目录下建立deno01_server.cpp
具体内容如下:
- /*
- 需求:
- 编写两个节点实现服务通信,客户端节点需要提交两个整数到服务器
- 服务器需要解析客户端提交的数据,相加后,将结果响应回客户端,
- 客户端再解析
- 服务器实现:
- 1.包含头文件
- 2.初始化 ROS 节点
- 3.创建 ROS 句柄
- 4.创建 服务 对象
- 5.回调函数处理请求并产生响应
- 6.由于请求有多个,需要调用 ros::spin()
- */
- #include "ros/ros.h"
- #include "demo03_server_client/AddInts.h"
-
- // bool 返回值由于标志是否处理成功
- bool doReq(demo03_server_client::AddInts::Request& req,
- demo03_server_client::AddInts::Response& resp){
- int num1 = req.num1;
- int num2 = req.num2;
-
- ROS_INFO("服务器接收到的请求数据为:num1 = %d, num2 = %d",num1, num2);
-
- //逻辑处理
- if (num1 < 0 || num2 < 0)
- {
- ROS_ERROR("提交的数据异常:数据不可以为负数");
- return false;
- }
-
- //如果没有异常,那么相加并将结果赋值给 resp
- resp.sum = num1 + num2;
- return true;
-
-
- }
-
- int main(int argc, char *argv[])
- {
- setlocale(LC_ALL,"");
- // 2.初始化 ROS 节点
- ros::init(argc,argv,"AddInts_Server");
- // 3.创建 ROS 句柄
- ros::NodeHandle nh;
- // 4.创建 服务 对象
- ros::ServiceServer server = nh.advertiseService("AddInts",doReq);
- ROS_INFO("服务已经启动....");
- // 5.回调函数处理请求并产生响应
- // 6.由于请求有多个,需要调用 ros::spin()
- ros::spin();
- return 0;
- }
接下来再第一个CMakeList里面继续修改(也就是大包的Cmake)
(P137)----修改内容如下
- P137
- add_excutable(demo01_server src/demo01_server.cpp)
-
- P147
- add_dependencies(demo01_server ${PROJECT_NAME}_gencpp)
-
- p150 开始 下面注释去掉
- target_link_libraries(demo01_server
- ${catkin_LIBRARIES})
配置完成后,打开三个命令行
- roscore
-
- cd demo03_ws/
- source ./devel/setup.bash
- rosrun plumbing_server_client demo01_server
就可以使用了
---------------------------------
参数服务器实现是最为简单的,该模型如下图所示,该模型中涉及到三个角色:
ROS Master 作为一个公共容器保存参数,Talker 可以向容器中设置参数,Listener 可以获取参数。
(直接再虚拟机上操作)
---------------------------------------------------------------------------
具体内容如下:
- /*
- 编写 ROS 节点,控制小乌龟画圆
- 准备工作:
- 1.获取topic(已知: /turtle1/cmd_vel)
- 2.获取消息类型(已知: geometry_msgs/Twist)
- 3.运行前,注意先启动 turtlesim_node 节点
- 实现流程:
- 1.包含头文件
- 2.初始化 ROS 节点
- 3.创建发布者对象
- 4.循环发布运动控制消息
- */
-
- #include "ros/ros.h"
- #include "geometry_msgs/Twist.h"
-
- int main(int argc, char *argv[])
- {
- setlocale(LC_ALL,"");
- // 2.初始化 ROS 节点
- ros::init(argc,argv,"control");
- ros::NodeHandle nh;
- // 3.创建发布者对象
- ros::Publisher pub = nh.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel",1000);
- // 4.循环发布运动控制消息
- //4-1.组织消息
- geometry_msgs::Twist msg;
- msg.linear.x = 1.0;
- msg.linear.y = 0.0;
- msg.linear.z = 0.0;
-
- msg.angular.x = 0.0;
- msg.angular.y = 0.0;
- msg.angular.z = 2.0;
-
- //4-2.设置发送频率
- ros::Rate r(10);
- //4-3.循环发送
- while (ros::ok())
- {
- pub.publish(msg);
-
- ros::spinOnce();
- }
-
-
- return 0;
- }
修改CMakeList配置:
启动命令行运行:
-----------------------------------------------
-------准备工作-------
1. 新建launch文件(节点)
2. 启动launch节点
3. 通过命令方式获得位姿
-----------------------------
以程序方式来打印位姿
package配置
CmakeList配置
添加功能包
-----------
2.新建文件:test02_sub_pose
内容如下:
- /*
- 订阅小乌龟的位姿: 时时获取小乌龟在窗体中的坐标并打印
- 准备工作:
- 1.获取话题名称 /turtle1/pose
- 2.获取消息类型 turtlesim/Pose
- 3.运行前启动 turtlesim_node 与 turtle_teleop_key 节点
- 实现流程:
- 1.包含头文件
- 2.初始化 ROS 节点
- 3.创建 ROS 句柄
- 4.创建订阅者对象
- 5.回调函数处理订阅的数据
- 6.spin
- */
-
- #include "ros/ros.h"
- #include "turtlesim/Pose.h"
-
- void doPose(const turtlesim::Pose::ConstPtr& p){
- ROS_INFO("乌龟位姿信息:x=%.2f,y=%.2f,theta=%.2f,lv=%.2f,av=%.2f",
- p->x,p->y,p->theta,p->linear_velocity,p->angular_velocity
- );
- }
-
- int main(int argc, char *argv[])
- {
- setlocale(LC_ALL,"");
- // 2.初始化 ROS 节点
- ros::init(argc,argv,"sub_pose");
- // 3.创建 ROS 句柄
- ros::NodeHandle nh;
- // 4.创建订阅者对象
- ros::Subscriber sub = nh.subscribe<turtlesim::Pose>("/turtle1/pose",1000,doPose);
- // 5.回调函数处理订阅的数据
- // 6.spin
- ros::spin();
- return 0;
- }
再次配置CMakeList
----------------------------------------
启动乌龟(启动launch文件)后,再新建命令行
- cd demo02_ws/
- source ./devel/setup.bash
- rosrun plumbing_test test02_sub_pose
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。