寒假学习记录四(ROS基础)

本文介绍了ROS中的关键命令行工具,如rostopic用于话题管理,rosservice处理服务,rosnode查看节点信息,以及rosmsg和rosparam管理消息和参数。此外,还详细阐述了工作空间的创建、编译及环境变量设置,以及创建功能包的过程。同时,讨论了ROS中的话题和服务,包括它们的异步和同步通信机制,并展示了发布者、订阅者、客户端和服务端的编程实现。

ROS中的命令行工具

常用命令:

  1. rostopic

用于显示系统中所有与话题相关的消息

常用组合:

打印出当前所有话题

rostopic list

向话题发布内容 (输入话题名后可以使用Tab补齐)

rostopic pub 话题名 话题消息的类型 话题消息的内容

该组合还可以加上参数来表示发布频率,频率填的是一分钟发布的次数

rostopic pub -r  频率 话题名 话题消息的类型 话题消息的内容

2.rosservice

用于显示系统中所有与服务相关的消息

常用组合:

打印出当前所有服务

rosservice list

调用服务

rosservice call 服务名 服务内容

刷新服务

/clear

3.rosnode

用于显示系统中所有与节点相关的消息

常用组合:

列出系统中所有节点

rosnode list

查看xx节点信息

rosnode info /xx

4.rosmsg

用于显示系统中所有与消息相关的消息

常用组合:

显示xx的数据结构

rosmsg show xxx  

5.rosparam

用于显示系统中所有与参数相关的消息

常用组合:

列出当前有多少参数

rosparam list

显示某个参数值

rosparam get xxx

设置某个参数值

rosparam set xxx

保存参数到文件

rosparam dump xxx.xxx

从文件读取参数

rosparam load xxx.xxx

删除参数

rosparam delete xxx

6.rqt_graph

用图形表示当前活动节点与ROS网络上的传输的消息之间的相关性工具

创建工作空间和功能包

工作空间(workspace)是一个存放工程开发相关文件的文件夹

一个工作空间内包括:

src:代码空间

build:编译空间

devel:开发空间

install:安装空间

创建工作空间

  1. 创建名为myws的工作空间

mkdir myws
mkdir src   #这个一定要创建

也可以直接递归创建

mkdir -p myws/src

2.初始化工作空间

cd  ~/myws/src   #进入myws内的src目录
catkin_init_workspace

catkin_init_workspace:将这个文件夹初始化为ros的一个工作空间,命令执行后在src文件下生成了一个CMakeList.txt文件,它是告诉系统这是ros的一个工作空间,这也是区别于普通文件夹。

3.编译工作空间

cd ..   #返回myws目录,如果没有跟着步骤就重新进入
catkin_make

所有的cmake命令去完成编译的操作都是要在工作空间的根目录下也就是myws这样的根目录下操作的

catkin_make:在myws文件下生成了bulid文件夹和devel文件夹

4.设置环境变量

在主目录下,ctrl+h显示隐藏文件,找到".bashrc"文件,打开,在文件最后位置加上“source /home/xxx/myws/devel/setup.bash”(此处路径要全,xxx表示用户名)

也可以使用命令(但是这个命令只是临时告诉编译器,只在当前终端有效)

source devel/setup.bash

设置后可以检查环境变量

echo $ROS_PACKAGE_PATH

创建功能包

  1. 在myws工作空间下创建test_pkg功能包

cd ~/myws/src
catkin_create_pkg test_pkg std_msgs rospy roscpp

catkin_creat_pkg命令结尾跟上的std_msgs、rospy和roscpp是依赖包(必须要的)

std_msgs :标准ROS消息包---包括表示原始数据类型的通用消息类型和其他基本消息结构

rospy :是Python版本的ROS客户端库,提供了Python程序需要的接口

roscpp:ROS的C++库,是目前最广泛应用的ROS客户端库,执行效率高

2.编译

cd ..   #返回myws目录,如果没有跟着步骤就重新进入
catkin_make

3.设置环境变量

目的:使功能包能够被找到

如果在上面创建工作空间时已经在~/.bashrc文件里添加了内容就不要重新添加了。

话题记录和复现

  1. 话题记录

rosbag record -a -O 压缩包名称

-a all,记录所有

-O:保存成压缩包

且默认保存在主目录下

2.话题复现

rosbag play 压缩包名称.bag

话题

话题

·异步通信机制

·节点之间用来传输数据的重要总线

·使用发布/订阅模型,数据由发布者传输到订阅者,同一个话题的订阅者或发布者可以不唯一。

话题通过发布和订阅进行传输,是单向传输。

话题是节点间传输数据的桥梁

话题中的数据叫消息

消息:

·具有一定类型和数据结构,包括ROS提供的标准类型和用户自定义类型。

·使用编程语言无关的.msg文件定义,编译过程中生成对应的代码文件。

发布者Publisher的编程实现

以给海龟发布运动信息为例

  1. 创建功能包

cd  ~/myws/src
catkin_create_pkg  publisher_pkg  roscpp  rospy  std_msgs geometry_msgs turtlesim

roscpp rospy 这两个是c++和py的依赖包, std_msgs是标准的消息,geometry_msgs这是和海龟的运动的速度的消息有关的依赖包。

  1. 创建发布者代码(C++)

如何实现一个发布者

·初始化ROS节点

·向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型

·创建消息数据

·按照一定的频率循环发布消息

/*
代码将实现发布turtle1/cmd_vel话题
消息类型geometry_msgs::Twist
*/
#include<ros/ros.h>
#include<geometry_msgs/Twist.h>
int main(int argc,char **argv) {
    //ROS节点初始化
    ros::init(argc, argv, "velocity_publisher");
    //创建节点句柄
    ros::NodeHandle n;
    //创建一个publisher,发布名为/turtle1/cmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度为10
    ros::Publisher turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
    //设置循环频率
    ros::Rate loop_rate(10);
    int count = 0;
    while (ros::ok()) {
        //初始化geometry_sgs::Twist类型消息
        geometry_msgs::Twist vel_msg;
        vel_msg.linear.x = 0.5;
        vel_msg.angular.z = 0.2;
        //发布消息
        turtle_vel_pub.publish(vel_msg);
        ROS_INFO("Publish turtle velocity command[%0.2f m/s,%0.2 rad/s]",
        vel_msg.linear.x, vel_msg.angular.z);
        //按循环频率延时
        loop_rate.sleep();
    }
    return 0;
}

在publisher_pkg/src内创建普通文件publisher编写这段代码

cd ~/myws/publish_pkg/src
touch publish
vim
i
赋值黏贴代码(写好的),或者在linux内写
esc
:wq!(强制保存退出)
  1. 编译并运行

编译前先要在功能包publisher_pkg内的CMakeList.txt内配置编译规则

·设置需要编译的代码和生成的可执行文件

·设置链接库

add_executable(publisher src/publisher.cpp)
target_link_libraries(publisher ${catkin_LIBRARIES})

add_executable(publisher src/publisher.cpp),src/publisher.cpp是指的前面编写代码的文件,publisher是设置src/publisher.cpp编译后形成的可执行文件的名字

target_link_libraries(publisher ${catkin_LIBRARIES})是将可执行文件与对应的链接库链接。

将这两句话写在功能包publisher_pkg内的CMakeList.txt内的有关build的内容的最下面

然后保存退出。

接着到工作空间根目录下编译

cd myws
catkin_make

最后显示100%表示编译成功

之后就打开小海龟界面

开两个终端,分别执行代码
roscore
rosrun turtlesim turtlesim_node

再打开一个终端运行刚刚编译好的程序】

rosrun publisher_pkg publisher

海龟就会按照指令运动。

订阅者Subscriber的编程实现

1.创建订阅者代码(C++)

在之前创建的publisher_pkg功能包的src内创建新文件编写代码

cd  ~/myws/src/publisher/src
touch subscriber.cpp
vim subscriber.cpp
i
编写代码
esc
:wq!(强制保存退出)

如何实现一个订阅者

·初始化ROS节点

·订阅需要的话题

·循环等待话题消息,接收到消息后进入回调函数

·在回调函数中完成消息处理

具体代码

/*
该代码将实现订阅/turtle1/pose话题,消息类型turtle::Pose
*/
#include<ros/ros.h>
#include"turtlesim/Pose.h"
void poseCallback(const turtlesim::Pose::ConstPtr& msg)
{
    //将接受到的消息打印出来
    ROS_INFO("Turtle pose: x:%0.6f,y:%0.6f", msg->x, msg->y);
}
int main(int argc, char** argv)
{

    //初始化ROS节点
    ros::init(argc, argv, "pose_subscriber");
    //创建节点句柄
    ros::NodeHandle n;
    //创建一个Subscriber,订阅名为/turtle1/pose的topic,注册回调函数poseCallback
    ros::Subscriber pose_sub = n.subscribe("/turtle1/pose", 10, poseCallback);
    //循环等待回调函数
    ros::spin();
    return 0;
}

2.编译与运行

编译前的设置,原理同发布者一样

add_executable(subscriber src / subscriber.cpp)
target_link_libraries(subscriber ${catkin_LIBRARIES})

在相同地方添加进去

之后到工作空间根目录里编译

cd myws
catkin_make

编译完后一样出现100%的进度显示表示编译成功

运行

先还是打开海龟的界面

开两个终端,分别执行代码
roscore
rosrun turtlesim turtlesim_node

之后运行订阅者的代码程序

rosrun publisher_pkg subscriber

因为海龟一直没动,所以回调函数打印出的一直是同一个位置

这时候可以运行之前的发布者来改变海龟位置。

rosrun publisher_pkg publisher

就可以看见位置的变化

服务

服务

·同步通信机制

·使用客户端/服务器(C/S)模型,客户端发送数据,服务器完成处理后返回应答数据。

·使用编程语言无关的.srv文件定义请求和应答数据结构,编译过程生成对应代码文件。

服务展示的是节点之间的你问我答,是一种有反馈的数据通信。

话题和服务的区别:

客户端Client的编程实现

以请求添加一个新的海龟并且给他一个运动指令为例

  1. 在之前创建的工作空间内创建新的功能包

cd ~/myws/src
catkin_create_pkg  service_pkg  roscpp  rospy  std_msgs geometry_msgs turtlesim

2.创建客户端代码(c++)

如何实现一个客户端

·初始化ROS节点

·创建一个Client实例

·发布服务请求数据

·等待Server处理之后的应答结果

在myws/src/service_pkg/src内创建一个新文件client.cpp来写代码

cd myws/src/service_pkg/src
touch client.cpp
vim client.cpp
i
写代码
esc
:wq!(强制保存退出)

具体代码

#include<ros/ros.h>
#include<turtlesim/Spawn.h>
int main(int argc, char** argv) {
    //初始化ROS节点
    ros::init(argc, argv, "turtle_spawn");
    //创建节点句柄
    ros::NodeHandle node;
    //发现/spawn服务后,创建一个服务客户端,连接名为/spawn的service
    ros::service::waitForService("/spawn");
    ros::ServiceClient add_turtle = node.serviceClient<turtlesim::Spawn>("/spawn");
    //初始化turtle::Spawn的请求数据
    turtle::Spawn srv;
    srv.request.x = 2.0;
    srv.request.y = 2.0;
    srv.request.name = "turtle2";
    //请求服务调用
    ROS_INFO("Call service to spawn turtle[x:%0.6f,y:%0.6f,name:%s]", srv.request.x, srv.request.y, srv.request.name);
    add_turtle.call(srv);
    //显示服务调用的结果
    ROS_INFO("Spawn turtle successfully [name:%s]", srv.response.name.c_str());
    return 0;
}

3.编译并运行

设置编译规则,和之前相同,把下面两句话添加的对应位置

add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})

编译(在工作空间根目录下)

cd myws
catkin_make

运行

roscore
rosrun turtlesim turtlesim_node
rosrun service_pkg client

效果

服务端Server的编程实现

同样以海龟为例

1.创建文件编写代码

cd myws/src/service_pkg/src
touch server.cpp
  1. 创建服务器代码(C++)

如何实现一个服务器

·初始化ROS节点

·创建server实例

·循环等待服务请求,进入回调函数

·在回调函数中完成服务功能的处理,并反馈应答数据

具体代码

/*
 该代码实现执行/turtle_command服务,服务数据类型std_srvs/Trigger
*/
#include<ros/ros.h>
#include<geometry_msgs/Twist.h>
#include<std_srvs/Trigger.h>
ros::Publisher turtlr_vel_pub;
bool pubCommand = false;
//service回调函数。输入参数req,输出参数res
bool commandCallback(std_srvs::Trigger::Request& req, std_srvs::Trigger::Response& res) {
    pubCommand = !pubCommand;
    //显示请求数据
    ROS_INFO("Publish turtle velocity command[%s]", pubCommand == true ? "Yes" : "No");
    //设置反馈数据
    res.success = true;
    res.message = "Change turtle command state!";
    return true;
}
int main(int argc, char** argv)
{
    //ROS节点初始化
    ros::init(argc, argv, "turtle_command_server");
    //创建节点句柄
    ros::NodeHandle n;
    //创建一个名为/turtle_sommand的server,注册回调函数commandCallback
    ros::ServiceServer command_service = n.advertiseService("/turtle_command", commandCallback);
    //创建一个publisher,发布名为/turtle1/xmd_vel的topic,消息类型为geometry_msgs::Twist,队列长度为10
    turtle_vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
    //循环等待回调函数
    ROS_INFO("Ready to receive turtle command.");
    //设置循环的频率
    ros::Rate loop_rate(10);
    while (ros::ok()) {
        //查看一次回调函数队列
        ros::spinOnce();
        //如果标志是true,则发布速度指令
        if (pubCommand) {
            geometry_msgs::Twist vel_msg;
            vel_msg.linear.x = 0.5;
            vel_msg.angular.z = 0.2;
            turtle_vel_pub.publish(vel_msg);
        }
        //按循环频率延时
        loop_rate.sleep();

    }
}

指令

vim server.cpp
i
写代码
esc
:wq!(强制保存退出)

3.编译并运行

编译规则设置(与之前相同)

add_executable(server src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})

编译(在工作空间根目录下)

cd myws
catkin_make

运行

roscore
rosrun turtlesim turtlesim_node
rosrun service_pkg server
rosservice call turtle_command "{}"

效果

动作

动作是基于话题和服务设计的一种通信方式,是为了方便管理机器人某一个完整的行为流程。

动作通信能够实现的是可以获取到实时的反馈(在机器人接受请求后,反馈机器人此时的位置或其他信息),可以在请求行为完成前随时可以发送取消的命令。

·同步通信机制

·客户端/服务器模型(C/S)

也是由客户端发送数据,服务器完成处理后返回应答数据,且周期反馈动作执行的状态,结束后反馈一个动作结束的信息。

从图示看,动作的三个通信模块,两个是服务模块,一个是话题模块,客户端的命令发送以及服务器端的反馈接受到命令和最后的动作结束的反馈都是通过服务来实现。动作的实时反馈过程,是一个话题的周期发布,服务器端是发布者,客户端是订阅者。

没错,动作是一种应用层的通信机制,其底层就是基于话题和服务来实现的

·服务器唯一,客户端不唯一,即一对多通信

·动作过程中的数据通信接口,使用.action文件进行定义。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值