Article Directory
Workspace
Folders for storing project development related files, which mainly include src, build, devel, and install folders.
Folder name | use |
---|---|
src | Code space (Source Space) |
build | Build Space |
devel | Development Space |
install | Install Space |
1. Create a workspace
mkdir -p ~/catkin_ws/src#创建文件夹
cd ~/catkin_ws/src#进入目录
catkin_init_workspace#初始化,使其成为ROS的工作空间
2. Compile the workspace
cd ..
catkin_make
3. Set environment variables
source /home/lyy/catkin_ws/devel/setup.bash#该环境变量设置只对当前终端有效,lyy是用户名
#将上面命令放置到~/.bashrc文件中,让其对所有终端都有效
sudo nano ~/.bashrc
4. Check environment variables
echo $ROS_PACKAGE_PATH
Feature pack
1. Create a feature package
cd ~/catkin_ws/src
catkin_create_pkg learning_communication std_msgs rospy roscpp
#catkin_create_pkg 功能包名字 依赖
#std_msgs:定义的标准的数据结构
#rospy:提供python编程接口
#roscpp:提供c++编程接口
2. Compile the function package
cd ~/catkin_ws
catkin_make
说明:
Function packages with the same name are not allowed in the same
workspace. Function packages with the same name can exist in different workspaces.
ROS communication programming
1. Topic programming
step:
- Create 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
- Publish messages in cycles at a certain frequency
- Create subscriber
- Initialize the ROS node
- Topics required for subscription
- Wait for the topic message in a loop, and perform a callback function after receiving the message
- Message processing is completed in the callback function
- Add compilation options
- Set the code to be compiled and the executable file generated
- Set up the link library
- Set up dependencies
- Run executable program
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;
}
listener.cpp
#include"ros/ros.h"
#include"std_msgs/String.h"
//接收到订阅的消息,会进入消息的回调函数
void chatterCallback(const std_msgs::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;
}
Set the CMakeLists.txt file,
compile and
run the executable file
roscore
rosrun learning_communication talker
rosrun learning_communication listener
Supplementary content
Custom topic message
-
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 compile options in CMakeLists.txt and
compile successfully
View custom message
rosmsg show Person
The following error appears.
Solution
source /home/lyy/catkin_ws/devel/setup.bash#Execute the command
2. Service programming
Define the way of service 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 CMakeLists.txt
Steps: -
Create server
- Initialize the ROS node
- Create Serve 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
-
Create a client
- Initialize the ROS node
- Create a Client instance
- Publish service request data
- Waiting for the response result after Serve processing
-
Add compilation options
- Set the code to be compiled and the executable file generated
- Set up the link library
- Set up dependencies
-
Run the executable program
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;
}
client.cpp
#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;
}
Set the CMakeLists.txt file to
compile (there are some warnings, you don’t need to worry about it)
Run the executable file
Run the server first, then the client
roscore
rosrun learning_communication server
rosrun learning_communication client 整数1 整数2
3. Motion programming
Action is a question-and-answer communication mechanism based on ROS messages. It contains continuous feedback and can stop running during the task.
Action interface
Interface name | Interface meaning |
---|---|
goal | Publish mission goals |
cancel | Request cancellation |
status | Notify the client of the current status |
feedback | Periodic feedback of monitoring data of task operation |
result | Send the execution result of the task to the client only once |
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>
-
Add compilation options in CMakeLists.txt
Steps: -
Create action server
- Initialize the ROS node
- Create an action server instance
- Start the server and wait for the 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
-
Create an action client
- Initialize the ROS node
- Create an action client instance
- Connect to action server
- Send action target
- Processing callback functions according to different types of server-side feedback
-
Add compilation options
- Set the code to be compiled and the executable file generated
- Set up the link library
- Set up dependencies
-
Run executable program
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;
}
DoDishes_client.cpp
#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;
}
Set the CMakeLists.txt file to
compile (there are some warnings, you can ignore it)
run the executable file
roscore
rosrun learning_communication DoDishes_client
rosrun learning_communication DoDishes_server