[Ubuntu20.04] Installation and configuration of ROS, programming practice verification of topic communication and service communication

Installation and configuration of ROS under Ubuntu 20.04, programming practice verification of topic communication and service communication

1. ROS installation

1.1 Set the software source

Set the software source to a domestic server. It is recommended that I use the Alibaba Cloud server here.
The setting process is shown in the figure below: Open the system settings, pull down to the lowest end, click the about menu, click software update, select the download server, and select aliyun.
After confirming, prompt "Reload". Click the "Reload" button and wait for the update to complete.
insert image description here

1.2 Install ROS noetic

1.2.1 Add sources.list

To set up the system to receive software from packages.ros.org, the command is as follows:
sudo sh -c 'echo “deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main” > /etc/apt/sources .list.d/ros-latest.list'
insert image description here

Enter the password as prompted and press Enter. Note that the password will not be displayed. Do not press the Backspace key. If you make a mistake, press Enter to re-enter.
insert image description here

1.2.2 Set keys

The command is as follows: sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
insert image description here

After successful setup, the output shows:
insert image description here

gpg: total processed: 1
gpg: imported: 1

1.2.3 Update system software source

Enter the command: sudo apt update
insert image description here

insert image description here
insert image description here

1.2.4 install noetic

Enter the command to install the full version of noetic desktop:
sudo apt install ros-noetic-desktop-full
The software package is relatively large, and it may take a while.
insert image description here

just wait patiently
insert image description here

If the software package cannot be downloaded, return to step 1 to switch the software source, or switch the network connection to try.

1.2.5 Setting environment variables

Enter the following command to set the environment variable.
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc
insert image description here

2. Test ROS and run the little turtle

Run roscore
to enter the command, run ros, and the relevant information of ros can be displayed:
input roscore
insert image description here

输出信息部分如下:
…logging to /home/ddduan/.ros/log/73c1f360-6103-11ed-8ddf-996439fcd44d/roslaunch-DDDuan-Lenovo-PC-5841.log
Checking log directory for disk usage. This may take a while.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

started roslaunch server http://DDDuan-Lenovo-PC:44705/
ros_comm version 1.15.14
This is the self-test of the program, check the disk usage of the log directory, and then make a summary. For example, here, the parameters, process and other information are given. Indicates no error.

Open a new terminal window, enter the command, and run the sample program of the little turtle.
rosrun turtlesim turtlesim_node
can see the little turtle window displayed.
insert image description here

Open another terminal window and enter commands to control the movement of the little turtle.
rosrun turtlesim turtle_teleop_key
insert image description here

Keep this terminal window active and press the arrow keys on the keyboard to move the little turtle.
insert image description here

insert image description here
Run the little turtle, keep the focus of the keyboard in the terminal page of rosrun turtlesim turtle_teleop_key, control the movement of the little turtle through ↑, ↓, ←, →, and you can see that when the little turtle "hits the wall", our rosrun turtlesim The turtlesim_node terminal page will output prompt data.

3. Introduction to common usage of ros system

Start the ros kernel

roscore

View topic list

rostopic list

show a topic

rostopic echo /camera_raw

Display the header of a topic

rostopic echo /camera_raw/header

Convert compressed format to raw format

rosrun image_transport republish compressed in:=/Mate/camera/ raw out:=/Mate/camera_raw/

Limit topic frequency

rosrun topic_tools throttle messages /Mate/camera_raw 4.0 /left

Record rosbag package

rosbag record -O bagpath.bag /camera_raw /imu

Play and speed up playing rosbag

rosbag play -r 100 bagpath.bag
rosbag play bagpath.bag

start rviz

rviz

4. ROS communication

The core of ROS - the distributed communication mechanism
ROS is a distributed framework that provides users with communication services between multiple nodes (processes). All software functions and tools are built on this distributed communication mechanism, so the communication of ROS Mechanism is the bottom and core technology. In most application scenarios, although we don't need to pay attention to the implementation mechanism of the underlying communication, understanding its related principles will definitely help us better use ROS in the development process. The three core communication mechanisms of ROS are as follows.

  • Topic mechanism
  • service mechanism
  • Shared parameter mechanism

4.1 Topic communication

Topic communication generally refers to: one node publishes a message, and another node subscribes to the message. It is suitable for data transmission scenarios that are constantly updated and less logically processed.

1. Three roles of topic communication

Topic communication involves three roles.

Talker (Publisher)

Responsible for publishing data to subscribers.

Listener (subscriber)

Responsible for receiving the publisher's data.

ROS Master (manager)

Responsible for keeping the registration information of publishers and subscribers, and matching publishers and subscribers with the same topic to help publishers and subscribers establish connections.

2. The process of topic communication establishment

The following figure is a schematic diagram of topic communication establishment, which is excerpted from the course notes.
insert image description here
step0 :
The publisher registers with the manager, which contains the topic name of the published message. The manager will add the registration information of the node to the registry.

step1 :
The subscriber registers with the manager, including the topic name that needs to subscribe to the message. The manager will add the registration information of the node to the registry.

step2 :
The manager matches the topic names of the publishers and subscribers in the registry, and tells the subscribers the address information of the publishers.

step3 :
The subscriber sends a connection request to the publisher, and transmits the subscribed topic name, message type and communication protocol (TCP/UDP).

step4 :
The publisher responds to the subscriber's request and sends its own TCP address information.

step5 :
The subscriber uses TCP to establish a network connection with the publisher according to the message returned in step 4.

step6 :
After the connection is established, the publisher sends information to the subscriber.

3. Precautions and instructions

1. There is no sequence requirement for step0 and step1, that is, there is no sequence requirement for the startup of publishers and subscribers

2. Topic communication can only be performed when the topic names of the publisher and the subscriber are the same

3. Publishers and subscribers can have multiple

4. After the publisher and subscriber are closed, the manager is no longer needed. Even if the manager is closed, the topic communication can still be carried out.

5. In code writing, we generally focus on topics, message transmission formats, etc., and the process of establishing a connection between a publisher and a subscriber is encapsulated.

4.2 Service communication

Service communication is based on the request-response mode, which is a response mechanism. That is: a node A sends a request to another node B, and B receives and processes the request and generates a response result and returns it to A. It is generally used in occasional data transmission scenarios that require timeliness and certain logical processing requirements.

1. Three roles of service communication

Similar to topic communication, service communication also has three roles

  • The client (client)
    is responsible for sending requests to the server and receiving data sent by the server.

  • The server (server)
    is responsible for receiving and processing requests and responding to clients.

  • ROS Master (manager)

    Responsible for keeping the registration information of the client and server, and matching the client and server with the same topic to help the client establish a connection with the server.

2. The process of service communication establishment

The figure below is a schematic diagram of the establishment of service communication, which is excerpted from the course notes.

insert image description here

step0 :
The server starts and registers with the manager, which contains the name of the provided service. The manager will add the registration information of the node to the registry.

step1 :
The client starts and registers with the manager, which contains the name of the requested service. The manager will add the registration information of the node to the registry.

step2 :
The manager matches the service names of the server and the client, and informs the client of the address information of the server.

step3 :
The client makes a network connection with the server and sends related requests.

step4 :
The server processes the request data, generates a response and sends it to the client.

3. Precautions

1. When the client request is processed, ensure that the server has been started

2. Both the server and the client can have multiple

5. Programming implementation of service communication

1. Create a feature package

Create a function package in the src folder of the ROS workspace ROS_ws, name it communication_pkg, and compile it.

catkin_create_pkg communication_pkg rospy roscpp std_msgs std_srvs
catkin_mae
sourceROS_ws/devel/setup.bash

insert image description hereinsert image description here

2. Node programming and service data definition

2.1 Case Description

Define a client Client, send two integers to the server Server through a custom service request Request, and at the same time, the server Server adds the two integers, and then feeds back the sum of the two integers to the client through a custom service response Response Client.

insert image description here

2.2 Definition of service data

Create a new folder under the feature pack directory, name it srv, and create an empty file AddTwoInts.srv in this folder.
insert image description here

Enter the following code in the AddTwoInts.srv file to define the service message content.

int64 a
int64 b
---
int64 sum

insert image description here

illustrate:

  • Use three small horizontal bars "—" as separators, the above "—" represents the message content of the service request, and the bottom of "—" represents the message content of the service response. Attached relevant information: https://wiki.ros.org/srv

2.3 Create a .cpp file

Create an empty file client.cpp in the src folder directory under the function package.
insert image description here

2.4 Client Programming

Open the file client.cpp created above and enter the following code.

#include <cstdlib>
#include "ros/ros.h"
#include "communication_pkg/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;
	
	//创建一个客户端,定义服务请求数据类型communication_pkg::AddTwoInts
	ros::ServiceClient client = n.serviceClient<communication_pkg::AddTwoInts>("add_two_ints");
	
	//定义服务消息内容
	communication_pkg::AddTwoInts srv;
	srv.request.a = atoll(argv[1]);
	srv.request.b = atoll(argv[2]);
	
	//发布服务请求,等待应答结果
	if(client.call(srv))
	{
		ROS_INFO("Sum: %ld", (long int)srv.response.sum);
	}
	else
	{
		ROS_ERROR("Failed to call service add_two_ints");
		return 1;
	}
	
	return 0;
}

illustrate:

  • The header file cstdlib.h is a common function library in C++, which is equivalent to stdlib.h in C, and can provide some functions and symbol constants.
  • The header file ros/ros.h contains the declarations of the standard ROS classes that need to be included in every ROS program.
  • The header file communication_pkg/AddTwoInts.h is obtained by compiling and expanding AddTwoInts.srv, and contains definitions for C++ classes. It is stored in the communication_pkg folder under the devel/include path of the workspace.
  • int main(int argc, char **argv) is a definition form of the main function. Its parameters argc and argv are used to pass command line parameters into the main program at runtime, where arg refers to arguments, that is, parameters.
    • int argc: The English name is arguments count (parameter count), which indicates the total number of command line parameters sent to the main function by the running program, including the name of the executable program. When argc=1, it means that there is only one program name, which is stored in in argv[0].
    • char **argv: The English name is arguments value/vector (parameter value), which is used to store an array of pointers to string parameters. Each element points to a parameter, separated by spaces, and its length is argc. The array subscript starts from 0, argv[argc]=NULL. argv[0] points to the full path name when the program is running; argv[1] points to the first string after the program name in the DOS command; argv[2] points to the second string after the program name.
  • The function of ros::init(argc, argv, "add_two_ints_client") is to initialize the ROS node. The third parameter represents the node name, which is unique.
  • if(argc != 3){...} means that when the number of parameters input in the terminal command line is not equal to 3, this code will be executed.
  • ros::NodeHandle n; is used to create a handle and start a ROS node.
  • ros::ServiceClient client = n.serviceClient<communication_pkg::AddTwoInts>(“add_two_ints”); This is one of the methods for users to call ROS services. It creates a client, and the object client of the ros::ServiceClient class returned by it will be used to send a service request to the node named add_two_ints in the ROS network. The data type of the service request is communication_pkg::AddTwoInts.
communication_pkg::AddTwoInts srv;
srv.request.a = atoll(argv[1]);
srv.request.b = atoll(argv[2]);
  • This is one of the ways to create service requests and service responses. It defines an object of type service_example::AddTwoInts. The members in this object are just a, b, and sum defined in the srv file, and fill the two numbers entered in the terminal command line into the data members a and b. The function of the atoll() function is to convert the string into a long long integer (long long int), that is, srv.request.a = atoll(argv[1]) is the first number in the string entered on the command line Convert it to a long integer and assign it to member a. The same is true for srv.request.b = atoll(argv[2]).
  • if(client.call(srv)){...} means to initiate a service request to the ROS network. Since the service request is in a blocked state, it is necessary to wait for the request to be initiated before returning a value. If the service call was successful, call() will return true and the values ​​in srv.response will be valid. If the call fails, call() will return false and the value in srv.response will be invalid.
  • ROS_INFO() and ROS_ERROR() are used to output log information. Log messages are divided into five different severity levels, which are DEBUG, INFO, WARN, ERROR, and FATAL.

To sum up, the steps to implement a client can be roughly divided into the following points:

  1. Initialize the ROS node;
  2. Create a client instance;
  3. Publish service request data;
  4. Wait for the response result after processing by the Server.

2.5 Server Programming

Create an empty file server.cpp under the src folder and enter the following code.

#include "ros/ros.h"
#include "communication_pkg/AddTwoInts.h"
	
//服务回调函数,输入为服务请求Req,输出为服务应答Res
bool add(communication_pkg::AddTwoInts::Request  &req,
		 communication_pkg::AddTwoInts::Response &res)
{
	//将两个数相加,并将结果存放在变量sum中
	res.sum = req.a + req.b;
	ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
	ROS_INFO("sending back response: [%ld]", (long int)res.sum);
	
	return true;
}
	
int main(int argc, char **argv)
{
	//初始化ROS节点
	ros::init(argc, argv, "add_two_ints_server");
	
	//创建句柄
	ros::NodeHandle n;
	
	//创建服务器,登记回调函数
	ros::ServiceServer service = n.advertiseService("add_two_ints", add);
	
	//循环等待
	ROS_INFO("Ready to add two ints.");
	ros::spin();
	
	return 0;
}

insert image description here

illustrate:

  • The main function is similar at the beginning, initialize the ROS node, create a handle, and start the ROS node.
  • ros::ServiceServer service = n.advertiseService("add_two_ints", add); The function is to create a service and add the service to the ROS network. This service is named add_two_ints in the ROS network and is uniquely identified so that other nodes can request it through the service name. When the service request is received, the add() callback function is called.
  • The function of ros::spin() is to let the program enter the self-loop suspension state, so that the program can receive the client's request with the best efficiency and call the callback function.
  • The representation of the service callback function is as follows:

bool callback(MReq &request, MRes &response)

  • where MReq and MRes match the data type of the request/reply provided to advertiseService(). If the return value of the callback function is true, it means that the service request is successful, and the service response has been filled with necessary data. If the return value is false, it means that the service request failed, and the service response will not be sent to the client.
  • The function of the callback function add(communication_pkg::AddTwoInts::Request &req, communication_pkg::AddTwoInts::Response &res) is to implement the service of summing two int-type integers. The two integers are obtained from the request, and the summation result is filled into the response , the specific data types of request and response are defined in the srv file.

To sum up, the steps to implement a server can be roughly divided into the following points:

  1. Initialize the ROS node;
  2. Create a Server instance;
  3. Wait for the service request in a loop and enter the callback function;
  4. Complete the processing of the service function in the callback function, and feedback the response data.

3. Configuration and compilation

3.1 Add compilation options in CMaKeLists.txt

Open the CMaKeLists.txt file in the function package, and add the function package in the find_package in the following location, so that (nodes) can call them to generate messages.
insert image description here

Adding the relevant .srv files in the following locations ensures that CMake knows about these newly added .srv files when reconfiguring, and adds all dependencies (function packages) of the .srv files when generating messages.

add_service_files(FILES AddTwoInts.srv)

insert image description here

Remove the "#" in front of CATLIN_DEPENDS in the following positions.
insert image description here

Configure in the following location, the function of add_executable(client src/client.cpp) is to compile the client.cpp file under the src folder into an executable file named client. The role of target_link_libraries(client ${catkin_LIBRARIES}) is to link the client executable file with the ROS-related library. The role of add_dependencies(client ${PROJECT_NAME}_gencpp) is to link the client executable with some dynamically generated files.

add_executable(server /home/ddduan/ROS_ws/src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})
add_dependencies(server ${PROJECT_NAME}_gencpp)
	
add_executable(client /home/ddduan/ROS_ws/src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROJECT_NAME}_gencpp)

insert image description here

3.2 Add function package dependencies in package.xml

Open the package.xml file in the function package, and add the function package dependencies in the following locations.

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

insert image description here

illustrate:

<buildtool_depend>catkin</buildtool_depend>

这条语句表示需要依赖catkin工具包用于使用catkin_make指令进行编译。

<build_export_depend>roscpp</build_export_depend>

这条语句表示编译后导出相关文件需要依赖roscpp功能包。

<build_depend>message_generation</build_depend>

这条语句表示在编译时会依赖一个动态产生message的功能包。

<exec_depend>message_runtime</exec_depend>

这条语句表示在运行时会依赖message_runtime的功能包。

3.3 Compile the file

Open a new terminal under the /ROS_ws folder path, and enter the following code to compile.

$ catkin_make

insert image description here

After the compilation is complete, enter the following code to run the master node.

$ roscore

insert image description here

Open a new terminal, after configuring the environment variables, enter the following code to run the node.

$ rosrun communication_pkg client integer1 integer2

Open a new terminal, after configuring the environment variables, enter the following code to run the node.

$ rosrun communication_pkg server

insert image description here

6. Programmatic implementation of topic communication

1. Create a feature package

Create a function package in the src folder of the ROS workspace ROS_ws, name it test_pkg, and compile it.
Refer to the routine for modification here
insert image description here

ddduan@DDDuan-Lenovo-PC:~$ mkdir -p ~/ROS_ws/src
ddduan@DDDuan-Lenovo-PC:~$ cd ~/ROS_ws/src
ddduan@DDDuan-Lenovo-PC:~/ROS_ws/src$ cd ..
ddduan@DDDuan-Lenovo-PC:~/ROS_ws$ catkin_make

insert image description here```
source devel/setup.bash
echo $ROS_PACKAGE_PATH
`
insert image description here

insert image description here

catkin_create_pkg test_pkg rospy roscpp std_msgs std_srvs
catkin_make
source ~/ROS_ws/devel/setup.bash

insert image description hereinsert image description here
insert image description here

2. Node programming and message definition

2.1 Case Description

Define a Publisher, and send the message data name, sex, and age to the Subscriber through a custom message Person, and the Subscriber will print the message content to the terminal interface.

insert image description here

2.2 Definition of topic message

Create a new folder under the function package directory, name it msg, and create an empty file Person.msg in this folder. You can use the right mouse button to select New Document>Empty Document, or use the terminal command touch to create an empty file under the src path.
insert image description here

Enter the following code in the Person.msg file to define the topic message.

string name
uint8 sex
uint8 age

uint8 unknown = 0
uint8 male = 1
uint8 female = 2
insert image description here

2.3 Create a .cpp file

Create an empty file Publisher_test.cpp under the src folder directory under the function package.
insert image description here

2.4 Topic publisher programming

Open the file Publisher_test created above and enter the following code.

#include "ros/ros.h"
#include "test_pkg/Person.h"
	
int main(int argc, char **argv)
{
	//初始化ROS节点
	ros::init(argc, argv, "Publisher_test");
	
	//创建句柄
	ros::NodeHandle n;
	
	//创建一个发布者Publisher,发布名为/person_info的topic,消息类型为test_pkg::Person,队列长度为10
	ros::Publisher person_info_pub = n.advertise<test_pkg::Person>("/person_info", 10);
	
	//设置消息发布频率
	ros::Rate loop_rate(1);
	
	int count = 0;
	while(ros::ok())
	{
		//初始化消息内容
		test_pkg::Person person_msg;
		person_msg.name = "Tom";
		person_msg.age  = 18;
		person_msg.sex  = test_pkg::Person::male;
	
		//发布消息
		person_info_pub.publish(person_msg);
		
		ROS_INFO("Publish Person Info: name:%s  age:%d  sex:%d",
			  person_msg.name.c_str(), person_msg.age, person_msg.sex);
	
		//按照设置的频率延时
		loop_rate.sleep();
	
	}
}

insert image description here

illustrate:

  • The header file ros/ros.h contains the declarations of the standard ROS classes that need to be included in every ROS program.
  • The header file test_pkg/Person.h is obtained by compiling and expanding Person.msg, and contains definitions for C++ classes, etc. It is stored in the devel folder of the workspace.
  • The function of ros::init(argc, argv, "Publisher_test") in the main function is to initialize the ROS node. The third parameter represents the node name, which is unique.
  • ros::NodeHandle n; is used to create a handle and start a ROS node.
  • ros::Publisher person_info_pub = n.advertise<test_pkg::Person>(“/person_info”, 10); Use the ros::Publisher class to define a publisher object person_info_pub, and the data type of the published message is test_pkg::Person, Expressed with <>. /person_info indicates the topic name of the published message data, which must be the same as the topic name subscribed by the subscriber. The second argument to advertise() indicates the length of the message queue used to publish messages. If messages are published faster than the underlying response, the number here specifies how many recent messages to buffer before discarding some. After calling the advertise() function, the master node (ROS Master) will notify any nodes that try to subscribe to this topic name, and then they will negotiate with this node. Meanwhile advertise() will return a Publisher object that allows you to publish a message on the topic by calling publish().
  • The function of ros::Rate loop_rate(1); is to set the message publishing frequency to 1Hz.
  • int count = 0; Indicates how many messages we have sent, used to create a unique string for each message.
  • If ros::ok() returns false, the following events may have occurred:
    (1) SIGINT was triggered (Ctrl-C);
    (2) Kicked out of the ROS network by another node with the same name;
    (3) ros::shutdown( ) is called by another part of the program;
    (4) All ros::NodeHandles in the node have been destroyed.
test_pkg::Person person_msg;
person_msg.name = "Tom";
person_msg.age  = 18;
person_msg.sex  = test_pkg::Person::male;
  • The role of this part is to initialize the message content, first create an object of the test_pkg::Person class, and then set the name, age and sex in this object.
  • person_info_pub.publish(person_msg); is to publish the message person_msg.
  • ROS_INFO() is similar to the printf() function in C language, which prints the content on the terminal interface.
  • The function of loop_rate.sleep(); is to delay to ensure that the message can be published according to the previously set publishing frequency.

To sum up, the steps to implement a topic publisher can be roughly divided into the following points:

初始化ROS节点;
向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型;
按照一定频率循环发送消息。

2.5 Topic Subscriber Programming

Create an empty file Subscriber_test.cpp under the src folder and enter the following code.
insert image description here

#include "ros/ros.h"
#include "test_pkg/Person.h"
	
//收到消息时进入回调函数
void personInfoCallback(const test_pkg::Person::ConstPtr& msg)
{
	//打印消息
	ROS_INFO("Subscribe Person Info: name:%s  age:%d  sex:%d",
		      msg->name.c_str(), msg->age, msg->sex);
}
	
int main(int argc, char **argv)
{
	//初始化ROS节点
	ros::init(argc, argv, "Subscriber_test");
	
	//创建句柄
	ros::NodeHandle n;
	
	//创建一个订阅者Subscriber
	ros::Subscriber person_info_sub = n.subscribe("/person_info", 10, personInfoCallback);
	
	//循环接收消息
	ros::spin();
	
	return 0;
}

illustrate:

  • personInfoCallback(const test_pkg::Person::ConstPtr& msg) is a callback function that will be executed once the subscriber receives the message. In the callback function, print the message content name, age and sex.
  • In the main function, the same as the publisher at the beginning, initialize the ROS node and create the handle.
  • ros::Subscriber person_info_sub = n.subscribe(“/person_info”, 10, personInfoCallback); Use the ros::Subscriber class to define a subscriber object person_info_sub. The first parameter in the subscribe() function indicates the topic name that needs to be subscribed, and the second parameter indicates the length of the message queue. If the message arrives faster than the processing speed, the message that will be buffered before the oldest message is discarded number. The third parameter of the subscribe() function is the callback function name, and the message is passed to the callback function.
  • ros::spin() will not return after being called, that is, the main program will not be executed down here, and it is generally placed at the end of the main function instead of in the while() loop.

To sum up, the steps to implement a topic subscriber can be roughly divided into the following points:

初始化ROS节点;
订阅需要的话题;
循环等待话题消息,接收到消息后进入回调函数;
在回调函数中完成消息处理。

3. Configuration and compilation

3.1 Add compilation options in CMaKeLists.txt

Open the CMaKeLists.txt file in the feature pack. Add the message_generation function package in the find_package in the following location, so that (nodes) can call them to generate messages.
insert image description here

Adding the relevant .msg files in the following locations ensures that CMake knows about these newly added .msg files when reconfiguring, and adds all dependencies (function packages) of the .msg files when generating messages.

add_message_files(FILES Person.msg)
generate_messages(DEPENDENCIES std_msgs)

insert image description here

Remove the "#" in front of CATLIN_DEPENDS in the following positions.

insert image description here

Configure it in the following location. The function of add_executable(Publisher_test src/Publisher_test.cpp) is to compile the Publisher_test.cpp file under the src folder into an executable file named Publisher_test. The role of target_link_libraries(Publisher_test ${catkin_LIBRARIES}) is to link the Publisher_test executable with the ROS-related libraries. What add_dependencies(Publisher_test ${PROJECT_NAME}_generate_messages_cpp) does is link the Publisher_test executable with some dynamically generated files.

add_executable(Publisher_test /home/ddduan/ROS_ws/src/Publisher_test.cpp)
target_link_libraries(Publisher_test ${catkin_LIBRARIES})
add_dependencies(Publisher_test ${PROJECT_NAME}_generate_messages_cpp)
	
add_executable(Subscriber_test /home/ddduan/ROS_ws/src/Subscriber_test.cpp)
target_link_libraries(Subscriber_test ${catkin_LIBRARIES})
add_dependencies(Subscriber_test ${PROJECT_NAME}_generate_messages_cpp)

insert image description here

3.2 Add function package dependencies in package.xml

Open the package.xml file in the function package, and add the function package dependencies in the following locations.

<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>

insert image description here

illustrate:

<build_depend>message_generation</build_depend>

This statement indicates that a function package that dynamically generates messages will be relied upon at compile time.

<exec_depend>message_runtime</exec_depend>

This statement indicates that the function package of message_runtime will be relied on at runtime.

3.3 Compile the file

Open a new terminal under the /ROS_ws folder path, and enter the following code to compile.

catkin_make

insert image description here

insert image description here

After the compilation is complete, enter the following code to run the master node.

roscore

insert image description here

4. Realize

Open a new terminal, first configure the environment variables, and then enter the following code to run the node.

source devel/setup.bash

 rosrun test_pkg Publisher_test

insert image description here

Open a new terminal, first configure the environment variables, and then enter the following code to run the node.

source devel/setup.bash
rosrun test_pkg Subscriber_test

insert image description here

5. Topic visualization

Open a new terminal and enter the following code.

rqt_graph	

From this, the following Qt-based GUI interface can be obtained, and the publishing and subscribing nodes and messages of topic communication can be seen intuitively.

insert image description here

Summarize

This experiment is to install ROS and program to realize topic communication and service communication. Due to the requirements of other courses, dual-system Ubuntu 20.04 was installed, so this experiment was carried out under Ubuntu 20.04. In the experiment, I did not know why and Terminal could not be opened. In the end, there was no way to enter the command mode. I installed Xterm, and successfully ran Terminal through Xterm. In general, this experiment has learned topic communication and service communication, and I have gained a lot

reference

2021-09-29 Use Android phone Camera and IMU information to run ORBSLAM3
ROS three kinds of communication programming introduction: [topic communication] [service communication] [action communication]
ROS basics - three basic communication mechanisms of topic, service and action programming
ROS
ROS | Programming Implementation of Topic Communication
Programming Implementation of Service Communication

Guess you like

Origin blog.csdn.net/qq_52201641/article/details/128557949