ROS basics-topic, service, action programming

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的工作空间

Insert picture description here
2. Compile the workspace

cd ..
catkin_make

Insert picture description here
Insert picture description here
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

Insert picture description here

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++编程接口

Insert picture description here
Insert picture description here

2. Compile the function package

cd ~/catkin_ws
catkin_make

Insert picture description here

说明:
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,
Insert picture description here
compile and
Insert picture description here
Insert picture description here
run the executable file

roscore
rosrun learning_communication talker
rosrun learning_communication listener

Insert picture description here
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
    Insert picture description here
    Insert picture description here
    Insert picture description here
    compile successfully
    Insert picture description here

View custom message

rosmsg show Person

Insert picture description here
The following error appears.
Insert picture description here
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
    Insert picture description here
    Insert picture description here
    Insert picture description here
    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
Insert picture description here
compile (there are some warnings, you don’t need to worry about it)
Insert picture description here
Insert picture description here
Run the executable file
Run the server first, then the client

roscore
rosrun learning_communication server
rosrun learning_communication client 整数1 整数2

Insert picture description here

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
    Insert picture description here
    Insert picture description here
    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
Insert picture description here
compile (there are some warnings, you can ignore it)
Insert picture description here
Insert picture description here
run the executable file

roscore
rosrun learning_communication DoDishes_client
rosrun learning_communication DoDishes_server

Insert picture description here

Reference

Getting started with ROS robot development

Guess you like

Origin blog.csdn.net/qq_43279579/article/details/114764633