ROS通信方式(保姆级教程)
- ROS通信方式
- 主题
- 前言
- 发布器编程实例:小海龟速度控制
- 步骤如下
- 注意:以下是拿小海龟的矩形来写,圆形也一样
- 实现效果
- 订阅器编程实例:小乌龟速度接收
- 服务
- 概述
- 前言
- 自定义src消息文件
- 步骤如下
- 服务端编程
- 步骤如下
- 实现效果
- 客户端编程
- 步骤如下
- 实现效果
- 主题
ROS通信方式
主题
前言
工作空间: catkin_ws1
ROS功能包: xhgpfk
c++文件: xhgfk.cpp和sudujieshou.cpp
定义一个可执行文件: luguoqin
发布器编程实例:小海龟速度控制
对ROS的小海龟来说,速度的控制主题为/turtle1/cmd_vel
,只需要对这个主题发送ge-ometry_msgs::Twist
这个信息包就可以对小海龟的速度进行调控了。
ge-ometry_msgs::Twist
:里面有两个部分速度值,第一个为linear,它表示在机器人的x、y、z、三个方向上,单位是m/s,第二个为angular,它表示在机器人的x、y、z、三个方向上,单位是弧度/s。
步骤如下
Ctrl+Alt+T
打开终端
i.创建ROS工作空间
mkdir -p ~/catkin_ws1/src
ii.切换到catkin_ws1 工作空间内的 src 目录
cd ~/catkin_ws1/src
iii.初始化一个新的 catkin 工作空间(前提一定要在“工作空间”下的“src 目录”)
catkin_init_workspace
iv.切换到catkin_ws1 工作空间
cd ~/catkin_ws1/
v.编译(前提一定要在“工作空间”下)
catkin_make
可以看到出现build、devel、src,3个文件夹
vi.使 ROS 工作空间的环境变量在每次打开新的终端时自动设置(里面的catkin_ws1要换成自己的“工作空间”)
echo "source ~/catkin_ws1/devel/setup.bash" >> ~/.bashrc
vii.重新执行 ~/.bashrc 文件中的所有命令
viii.切换到catkin_ws1 工作空间内的 src 目录
cd ~/catkin_ws1/src
ix.创建新的 ROS 包(xhgpfk
为包名,可以自己更改)
catkin_create_pkg
用于创建新的 ROS 包的命令行工具
catkin_create_pkg xhgpfk roscpp geometry_msgs
x.打开VSC(Visual Studio Code)点击File(文件)点击Open Folder(打开文件夹)选择“编译空间”的文件
xi.点击“编译空间”的文件的src看到ROS功能包的src鼠标右键单击创建一个c++文件(是在第二个src创建),例如:xhgfk.cpp
xii.i.小海龟的圆形代码如下:
#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;
// 创建一个发布者,发布/turtle1/cmd_vel话题,消息队列大小为20
ros::Publisher vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 20);
// 设置循环频率为10Hz
ros::Rate loop_rate(10);
while(ros::ok())
{
// 创建Twist消息
geometry_msgs::Twist vel_cmd;
vel_cmd.linear.x = 2;
vel_cmd.linear.y = 0;
vel_cmd.linear.z = 0;
vel_cmd.angular.x = 0;
vel_cmd.angular.y = 0;
vel_cmd.angular.z = 1.8;
// 发布消息
vel_pub.publish(vel_cmd);
// 处理回调函数
ros::spinOnce();
// 按照设定的循环频率休眠
loop_rate.sleep();
}
return 0;
}
xii.ii.小海龟的矩形代码如下:
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
int main(int argc, char** argv)
{
ros::init(argc, argv, "turtle_vel_ctrl_node");
ros::NodeHandle n;
ros::Publisher vel_pub = n.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 20);
ros::Rate loop_rate(2);
int count = 0;
while(ros::ok())
{
geometry_msgs::Twist vel_cmd;
vel_cmd.linear.x = 1.0;
vel_cmd.linear.y = 0.0;
vel_cmd.linear.z = 0.0;
vel_cmd.angular.x = 0.0;
vel_cmd.angular.y = 0.0;
vel_cmd.angular.z = 0.0;
if(count == 5)
{
vel_cmd.angular.z = 3.1415926; // Change angular velocity when count reaches 5
count = 0; // Reset count
}
else
{
count++; // Increment count
}
vel_pub.publish(vel_cmd);
ros::spinOnce();
loop_rate.sleep();
}
return 0;
}
注意:以下是拿小海龟的矩形来写,圆形也一样
xiii.在下面找到CMakeLists.txt,在最后面(第207行开始)添加代码进行编译(你的c++是什么名字就改为什么名字xhgfk.cpp
),(luguoqin
这个可以改一个随便的)
add_executable(luguoqin src/xhgfk.cpp)
add_dependencies(luguoqin ${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS})
target_link_libraries(luguoqin ${catkin_LIBRARIES})
xiv.切换到 catkin_ws1
工作空间
cd ~/catkin_ws1/
xv.在创建或修改了 ROS 包后,需要使用 catkin_make 来编译这些更改
catkin_make
xvi.Ctrl+Alt+T
打开终端
xvii.用于启动 ROS 的节点
roscore
xiii.用于运行 ROS 节点
rosrun turtlesim turtlesim_node
xix.运行小海龟跑矩形的指令
rosrun xhgpfk luguoqin
实现效果
订阅器编程实例:小乌龟速度接收
在ROS(机器人操作系统)中,订阅器(Subscriber)是一种节点,它订阅特定的话题(Topic),以接收并处理发布器(Publisher)发布的消息。
i.打开vscode
ii.点击“编译空间”的文件的src看到ROS功能包的src鼠标右键单击创建一个c++文件(是在第二个src创建),例如:xhgfk.cpp
iii.在创建的c++文件添加代码
#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
// 回调函数,用于处理接收到的消息
void callback(const geometry_msgs::Twist& cmd_vel) {
ROS_INFO("Received a /turtle1/cmd_vel message!");
ROS_INFO("Linear Velocity: [%f, %f, %f]",
cmd_vel.linear.x, cmd_vel.linear.y, cmd_vel.linear.z);
ROS_INFO("Angular Velocity: [%f, %f, %f]",
cmd_vel.angular.x, cmd_vel.angular.y, cmd_vel.angular.z);
}
int main(int argc, char** argv) {
// 初始化ROS节点
ros::init(argc, argv, "turtle_vel_rece_node");
// 创建节点句柄
ros::NodeHandle n;
// 创建一个订阅者,订阅/turtle1/cmd_vel话题,缓冲区大小为1000
ros::Subscriber sub = n.subscribe("/turtle1/cmd_vel", 1000, callback);
// 进入循环,等待回调函数被调用
ros::spin();
// 正常情况下,ros::spin()不会返回,除非ROS被关闭
// 所以这里实际上不会执行到return语句
return 0;
}
iv.在下面找到CMakeLists.txt,在最后面(第211行开始)添加代码进行编译(你的c++是什么名字就改为什么名字lihaitong.cpp
),(lihaitong
这个可以改一个随便的)
add_executable(lihaitong src/lihaitong.cpp)
add_dependencies(lihaitong ${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS})
target_link_libraries(lihaitong ${catkin_LIBRARIES})
v.切换到 catkin_ws1
工作空间
cd ~/catkin_ws1/
vi.在创建或修改了 ROS 包后,需要使用 catkin_make 来编译这些更改
catkin_make
vii.Ctrl+Alt+T
打开终端
viii.用于启动 ROS 的节点
roscore
ix.用于运行 ROS 节点
rosrun turtlesim turtlesim_node
x.运行小海龟跑矩形的指令
rosrun xhgpfk luguoqin
xi.运行小海龟速度接收的指令
rosrun xhgpfk lihaitong
xii.显示当前ROS里的节点网络情况
rqt_graph
服务
概述
与Topie(主题)不同,Service(服务)通信是双向的,它不仅可以发送反馈。一个服务(Service)被分成服务端(Server)和客户端(Client),分别对应节点A和节点B,两个都要到主节点管理器进行注册。在主节点管理器的管理下,节点B(客户端)向节点A(服务端)发送请求,节点A(服务端)响应该请求,实现节点之间的双向通信。在请求机器人执行特定操作时,或者根据特定条件需要产生响应事性时,通常使用Service(服务)。
前言
工作空间: catkin_ws1
(和上面是同一个工作空间)
ROS功能包: xhgpfk
c++文件: fuwu.cpp
和kewu.cpp
srv文件: ServiceClientExMsg.srv
定义一个可执行文件: fuwu
和kewu
自定义src消息文件
步骤如下
i.在上面的catkin_ws1
工作空间里创建新的ROS功能包,(service_client_pkg
为包名,可以自己更改)catkin_create_pkg
用于创建新的 ROS 包的命令行工具.
cd ~/catkin_ws1/src/
catkin_create_pkg service_client_pkg roscpp std_msgs
ii.进入service_client_pkg文件夹创建srv来放.srv文件
cd service_client_pkg
mkdir srv
iii.打开vscode再打开catkin_ws1文件,找到service_client_pkg子文件的srv文件,点击srv鼠标右键创建ServiceClientExMsg.srv,在里面写入代码
string name
---
bool in_class
bool boy
int32 age
string personality
iv.编写完成后在service_client_pkg文件下的package.xml,在59行开始添加下面语句
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
v.添加完成后在service_client_pkg文件下的CMakeLists.txt,内容修改。
#大概第10~18行
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
message_generation
std_msgs
std_srvs
)
#大概第61~65行
add_service_files(
FILES
ServiceClientExMsg.srv
# Service2.srv
)
#大概第75~78行
generate_messages(
DEPENDENCIES
std_msgs
)
#大概第109~115行
catkin_package(
INCLUDE_DIRS include
LIBRARIES service_client_pkg
CATKIN_DEPENDS roscpp std_msgs
DEPENDS system_lib
CATKIN_DEPENDS message_runtime
)
vi.在工作空间进行代码编译
cd ~/catkin_ws1
catkin_make
服务端编程
步骤如下
i.打开vscode再打开catkin_ws1文件,找到service_client_pkg子文件的src文件,点击src鼠标右键创建fuwu.cpp,在里面写入代码
#include <ros/ros.h>
#include <service_client_pkg/ServiceClientExMsg.h> // 注意文件扩展名应该是 .h 而不是 .hx
using namespace std;
bool infoInquiry(service_client_pkg::ServiceClientExMsgRequest& request,
service_client_pkg::ServiceClientExMsgResponse& response) {
ROS_INFO("Callback activated");
string inputName = request.name;
response.in_class = false;
if (inputName.compare("Tom") == 0) {
ROS_INFO("Student information about Tom");
response.in_class = true;
response.boy = true;
response.age = 20;
response.personality = "outgoing";
} else if (inputName.compare("Mary") == 0) {
ROS_INFO("Student information about Mary");
response.in_class = true;
response.boy = false;
response.age = 21;
response.personality = "introverted";
}
return true;
}
int main(int argc, char **argv) {
ros::init(argc, argv, "service_example_node");
ros::NodeHandle n;
ros::ServiceServer service = n.advertiseService("info_inquiry_by_name", infoInquiry);
ROS_INFO("Ready to inquiry names.");
ros::spin();
return 0;
}
ii.写完后在service_client_pkg文件下的CMakeLists.txt,在最后面添加编译规则
add_executable(fuwu src/fuwu.cpp)
add_dependencies(fuwu ${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS})
target_link_libraries(fuwu ${catkin_LIBRARIES})
iii.切换到 catkin_ws1
工作空间
cd ~/catkin_ws1/
iv.在创建或修改了 ROS 包后,需要使用 catkin_make 来编译这些更改
catkin_make
v.Ctrl+Alt+T
打开终端
x.用于启动 ROS 的节点
roscore
vi.用于运行 fuwu 节点
rosrun service_client_pkg fuwu
vii.测试节点是否正常反馈信息
rosservice call /info_inquiry_by_name "Tom"
实现效果
客户端编程
步骤如下
i.打开vscode再打开catkin_ws1文件,找到service_client_pkg子文件的src文件,点击src鼠标右键创建kehu.cpp,在里面写入代码
#include <ros/ros.h>
#include <service_client_pkg/ServiceClientExMsg.h>
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char **argv)
{
ros::init(argc, argv, "client_example_node");
ros::NodeHandle n;
ros::ServiceClient client = n.serviceClient<service_client_pkg::ServiceClientExMsg>("info_inquiry_by_name");
service_client_pkg::ServiceClientExMsg srv;
string input_name;
while(ros::ok())
{
cout << endl;
cout << "Enter a name (q to quit): ";
cin >> input_name;
if (input_name.compare("q") == 0)
{
return 0;
}
srv.request.name = input_name;
if (client.call(srv))
{
if (srv.response.in_class)
{
if (srv.response.boy)
{
cout << srv.request.name << " is a boy;" << endl;
}
else
{
cout << srv.request.name << " is a girl;" << endl;
}
cout << srv.request.name << " is " << srv.response.age << " years old;" << endl;
cout << srv.request.name << " has a " << srv.response.personality << " personality." << endl;
}
else
{
cout << srv.request.name << " is not in class" << endl;
}
}
else
{
ROS_ERROR("Failed to call service info_inquiry_byname");
return 1;
}
}
return 0;
}
ii.写完后在service_client_pkg文件下的CMakeLists.txt,在最后面添加编译规则
add_executable(kehu src/kehu.cpp)
add_dependencies(kehu ${${PROJECT_NAME}_EXPORTED_TARGETS}
${catkin_EXPORTED_TARGETS})
target_link_libraries(kehu ${catkin_LIBRARIES})
iii.切换到 catkin_ws1
工作空间
cd ~/catkin_ws1/
iv.在创建或修改了 ROS 包后,需要使用 catkin_make 来编译这些更改
catkin_make
v.Ctrl+Alt+T
打开终端
x.用于启动 ROS 的节点
roscore
vi.用于运行 fuwu 节点
rosrun service_client_pkg fuwu
vii.用于运行 kehu 节点
rosrun service_client_pkg kehu
viii.输入Tom