ROS realizes simple communication programming
Overview
Use intelligent robots to realize simple communication programming——
话题、服务、动作。
1. Create a workspace
1. What is a workspace
The workspace (workplace) is a folder for storing project development-related files.
src
: Code space (source space)build
: Build spacedevel
:Development space (development space)install
: Install space
2. Create a workspace
The instructions are as follows:
mkdir -p ~/catkin_ws/src#创建文件夹
cd ~/catkin_ws/src#进入目录
catkin_init_workspace#初始化,使其成为ROS的工作空间
Compile workspace
cd ..
catkin_make
Set environment variables
source /home/zxw/catkin_ws/devel/setup.bash#该环境变量设置只对当前终端有效,zxw是用户名
#将上面命令放置到~/.bashrc文件中,让其对所有终端都有效
sudo nano ~/.bashrc
Check environment variables
echo $ROS_PACKAGE_PATH
3. Create a feature pack
The instructions are as follows:
cd ~/catkin_ws/src
catkin_create_pkg learning_communication std_msgs rospy roscpp
#catkin_create_pkg 功能包名字 依赖
#std_msgs:定义的标准的数据结构
#rospy:提供python编程接口
#roscpp:提供c++编程接口
Compile function package
cd ~/catkin_ws
catkin_make
同一个工作空间下,不允许存在同名功能包;不同空间下,允许存在同名功能包。
4. Coverage of working space
The overlaying mechanism of the ros workspace, that is, the coverage of the workspace;
- The path of the workspace is recorded in the ROS_PACKAGE_PATH environment variable in turn;
- The newly set path will be automatically placed at the forefront in ROS_PACKAGE_PATH;
- When running, ROS will first look for the specified function package in the front-end workspace;
- If it does not exist, other workspaces will be searched backward in sequence.
Two, communication programming-topic
1. Topic programming process
- Create publisher
- Create subscriber
- Add compilation options
- Run executable program
2. Implementation of the publisher
- Initialize the ROS node;
- Register node information with ROS Master, including the name of the published topic and the message type in the topic;
- Circulate news at a little frequency;
talker.cpp
#include<sstream>
#include"ros/ros.h"
#include"std_msgs/String.h"
int main(int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"talker");
//创建节点句柄
ros::NodeHandle n;
//创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::String
ros::Publisher chatter_pub=n.advertise<std_msgs::String>("chatter",1000);
//设置循环的频率
ros::Rate loop_rate(10);
int count=0;
while(ros::ok())
{
//初始化std_msgs::String类型的消息
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;
}
3. The realization of subscribers
- Initialize the ROS node;
- Subscribe to the topics needed;
- Wait for the topic message in a loop, and enter the callback function after receiving the message;
- Complete the message processing in the callback function;
listener.cpp
#include"ros/ros.h"
#include"std_msgs/String.h"
//接收到订阅的消息,会进入消息的回调函数
void chatterCallback(const std_mmsgs::String::ConstPtr& msg)
{
//将接收到的消息打印处理
ROS_INFO("I heard:{%s}",msg->data.c_str());
}
int main(int argc,char **argv)
{
//初始化ROS节点
ros::init(argc,argv,"listener");
//创建节点句柄
ros::NodeHandle n;
//创建一个Subscriber,订阅名为chatter的topic,注册回调函数chatterCallback
ros::Subscriber sub=n.subscribe("chatter",1000,chatterCallback);
//循环等待回调函数
ros::spin();
return 0;
}
4. Compile the code
Set the CMakeLists.txt file;
add_executable(talker src/talker.cpp)
target_link_libraries(talker ${
catkin_LIBRARIES})
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${
catkin_LIBRARIES})
Compile
catkin_make
Run the executable file
roscore
rosrun learning_communication talker
rosrun learning_communication listener
5. Custom topics
Define msg file
mkdir ~/catkin_ws/src/learning_communication/msg
sudo nano Person.msg
person.msg
string name
uint8 sex
uint8 age
uint8 unknown=0
uint8 male=1
uint8 female=2
Add function package dependency in package.xml
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
In some ROS versions, exec_depend needs to be modified to run_depend
Add compilation options in CMakeLists.txt
View custom messages
rosmsg show Person
Three, communication programming-service
1. Service programming process
- Create server
- Create a client
- Add compilation options
- Run the executable file
Custom server request and response
Define srv file
mkdir ~/catkin_ws/src/learning_communication/srv
sudo nano AddTwoInts.srv
AddTwoInts.srv
int64 a
int64 b
---
int64 sum
Add function package dependency in package.xml
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
In some ROS versions, exec_depend needs to be modified to run_depend
Add compilation options in cmakelist.txt
find_package(...... message_generation)
catkin_package(CATKIN_DEPENDS geometry roscpp rospy std_msgs message_runtime)
add_service_files(FILES AddTwolnts.srv)
2. The realization of the server
- Initialize the ROS node
- Create server instance
- Wait for the service request in a loop and enter the callback function
- Complete the processing of the service function in the callback function, and feedback the response data
server.cpp
#include<ros/ros.h>
#include"learning_communication/AddTwoInts.h"
//service回调函数,输入参数req,输出参数res
bool add(learning_communication::AddTwoInts::Request &req,learning_communication::AddTwoInts::Response &res)
{
//将输入的参数中的请求数据相加,结果放到应答变量中
res.sum=req.a+req.b;
ROS_INFO("request: x=%1d,y=%1d",(long int)req.a,(long int)req.b);
ROS_INFO("sending back response:[%1d]",(long int)res.sum);
return true;
}
int main(int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"add_two_ints_server");
//创建节点句柄
ros::NodeHandle n;
//创建一个名为add_two_ints的server,注册回调函数add()
ros::ServiceServer service=n.advertiseService("add_two_ints",add);
//循环等待回调函数
ROS_INFO("Ready to add two ints.");
ros::spin();
return 0;
}
3. Implementation of the client
- Initialize the ROS node
- Create a client instance
- Publish service request data
- Waiting for the response result
client.cpp after server processing
#include<cstdlib>
#include<ros/ros.h>
#include"learning_communication/AddTwoInts.h"
int main(int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"add_two_ints_client");
//从终端命令行获取两个加数
if(argc!=3)
{
ROS_INFO("usage:add_two_ints_client X Y");
return 1;
}
//创建节点句柄
ros::NodeHandle n;
//创建一个client,请求add_two_ints_service
//service消息类型是learning_communication::AddTwoInts
ros::ServiceClient client=n.serviceClient<learning_communication::AddTwoInts>("add_two_ints");
//创建learning_communication::AddTwoInts类型的service消息
learning_communication::AddTwoInts srv;
srv.request.a=atoll(argv[1]);
srv.request.b=atoll(argv[2]);
//发布service请求,等待加法运算的应答请求
if(client.call(srv))
{
ROS_INFO("sum: %1d",(long int)srv.response.sum);
}
else
{
ROS_INFO("Failed to call service add_two_ints");
return 1;
}
return 0;
}
4. Compile the code
Set up the CMakeLists.txt file
Four, communication programming-action
1. Custom action message
Define action file
mkdir ~/catkin_ws/src/learning_communication/action
sudo nano DoDishes.action
DoDishes.action
#定义目标信息
uint32 dishwasher_id
---
#定义结果信息
uint32 total_dishes_cleaned
---
#定义周期反馈的消息
float32 percent_complete
Add function package dependency in package.xml
<build_depend>actionlib</build_depend>
<build_depend>actionlib_msgs</build_depend>
<exec_depend>actionlib</exec_depend>
<exec_depend>actionlib_msgs</exec_depend>
2. Implement an action server
- Initialize the ROS node
- Create an action server instance
- Start the action server. Wait for action request
- Complete the processing of the action service function in the callback function, and feedback the progress information
- The action is complete, send the end message
DoDishes_server.cpp
#include "ros/ros.h"
#include "actionlib/server/simple_action_server.h"
#include "learning_communication/DoDishesAction.h"
typedef actionlib::SimpleActionServer<learning_communication::DoDishesAction> Server;
// 收到action的goal后调用该回调函数
void execute(const learning_communication::DoDishesGoalConstPtr &goal, Server *as)
{
ros::Rate r(1);
learning_communication::DoDishesFeedback feedback;
ROS_INFO("Dishwasher %d is working.", goal->dishwasher_id);
// 假设洗盘子的进度,并且按照1Hz的频率发布进度feedback
for(int i = 1; i <= 10; i++)
{
feedback.percent_complete = i * 10;
as->publishFeedback(feedback);
r.sleep();
}
// 当action完成后,向客户端返回结果
ROS_INFO("Dishwasher %d finish working.", goal->dishwasher_id);
as->setSucceeded();
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "do_dishes_server");
ros::NodeHandle hNode;
// 定义一个服务器
Server server(hNode, "do_dishes", boost::bind(&execute, _1, &server), false);
// 服务器开始运行
server.start();
ros::spin();
return 0;
}
3. Implement an action client
- Initialize the ROS node
- Create an action client instance
- Connect action server
- Send action target
- Process the callback function
DoDishes_client.cpp according to different types of server feedback
#include "ros/ros.h"
#include "actionlib/client/simple_action_client.h"
#include "learning_communication/DoDishesAction.h"
typedef actionlib::SimpleActionClient<learning_communication::DoDishesAction> Client;
// 当action完成后会调用该回调函数一次
void doneCallback(const actionlib::SimpleClientGoalState &state
, const learning_communication::DoDishesResultConstPtr &result)
{
ROS_INFO("Yay! The dishes are now clean");
ros::shutdown();
}
// 当action激活后会调用该回调函数一次
void activeCallback()
{
ROS_INFO("Goal just went active");
}
// 收到feedback后调用该回调函数
void feedbackCallback(const learning_communication::DoDishesFeedbackConstPtr &feedback)
{
ROS_INFO("percent_complete : %f", feedback->percent_complete);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "do_dishes_client");
// 定义一个客户端
Client client("do_dishes", true);
// 等待服务器端
ROS_INFO("Waiting for action server to start.");
client.waitForServer();
ROS_INFO("Action server started, sending goal.");
// 创建一个 action 的 goal
learning_communication::DoDishesGoal goal;
goal.dishwasher_id = 1;
// 发送action的goal给服务端,并且设置回调函数
client.sendGoal(goal, &doneCallback, &activeCallback, &feedbackCallback);
ros::spin();
return 0;
}
4. Compile the code
Set up the CMakeLists.txt file
Five, summary and reference materials
1. Summary
I have a certain understanding of the basics of ROS-communication programming, and it still feels a bit troublesome to do it, but there are similar tutorial materials on the Internet, and you can do it step by step. Baidu will solve the problem in the middle.
2. Reference materials
ROS operating system study notes under ubuntu16.04 (3 / 2) ROS basics-ROS communication programming .