1, Create workspace
1. Create a new folder
Create a new catkin_ws folder and create src subdirectory in it.
mkdir -p ~/dev/catkin_ws/src cd ~/dev/catkin_ws/src
2. Initialize workspace
In the src subdirectory just created, use the following command to create a workspace, but there is no function package in the workspace at this time, only CMakeLists.txt.
catkin_init_workspace
3. Compile workspace
Go back to the top directory of the workspace, catkin_ws folder, using catkin_ The make command performs compilation. After compiling, you can see that the build and devel folders are generated by using the ll instruction.
cd .. catkin_make
4. Complete the configuration
Reload the setup.bash file to complete the last step of workspace creation configuration
source devel/setup.bash
In fact, if you add this command line to ~ /. bashrc, you can get the same effect by restarting the terminal. The added command is as follows, where noetic is the version number of my ros system. If your version is different, you must change it.
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
2, Create and compile ROS function package
1. Create function package
Function packs can be created manually, but catkin is usually used for convenience_ create_ PKG command creates a function package. The format of this command is as follows
catkin_create_pkg [package_name] [depend1] [depend2] [depend3]
The dependent dependencies include:
- std_msgs: contains common message types that represent basic data types and other basic message constructs.
- roscpp: use C + + to write various functions of ROS.
Example: cd ~dev/catkin_ws/src catkin_create_pkg test_package std_msgs roscpp
2. Compile function package
Back to catkin_ws folder. If no error is reported, the function package is compiled successfully.
cd .. catkin_make
3, Basic commands of ROS
3.1 nodes
1. rosnode instruction
The rosnode tool can print information about ROS nodes. The specific commands are as follows:
rosnode instruction | effect |
---|---|
rosnode ping NODE | Test connectivity of nodes |
rosnode list | List active nodes |
rosnode info NODE | Output information for this node |
rosnode machine | Print nodes running on a specific computer |
rosnode kill NODE | End node process |
rosnode cleanup | Clear the registration information of inaccessible nodes |
2. Operation node
First start the ros program with the roscore command, and then open a new terminal window to perform the next operation.
We can run a node using the rosrun instruction
Example: rosrun turtlesim turtlesim_node
After the node runs successfully, you can use the rosnode list again to see the running node. You can use rosnode info / turnlesim to view the details of the node, including Publications, Subscriptions and Services of the node.
3.2 subject
1. rostopic instruction
Nodes can realize data transmission through publishing topics and subscribing topics. Message transmission through topics does not require direct connection of nodes. A topic can have multiple subscribers and publishers. To realize the interaction between topics and nodes, you can use the rostopic instruction.
rostopic instruction | effect |
---|---|
rostopic bw TOPIC | Displays the bandwidth used by the topic |
rostopic echo TOPIC | Output the message of the subject to the screen |
rostopic find TOPIC | find topic |
rostopic hz TOPIC | Show topic publishing frequency |
rostopic info TOPIC | Output topic details |
rostopic list TOPIC | List activity topics |
rostopic pubs TOPIC | Publish data to topics |
rostopic type TOPIC | Type of output topic |
2. Release theme
You can list the topics of the current node through rostopic list. You can print messages sent by the node through the echo parameter, such as rostopic echo / turnle1 / CMD_ vel.
In addition, we can also publish topics directly through rostopic pub, as follows:
Example: rostopic pub -r 10 /turtle1/cmd_vel geometry_msgs/Twist -r 1 -- '{linear: {x: 1, y: 0, z: 0}, angular: {x: 0, y: 0, z: 1}}'
3.3 services
1. rosservice instruction
Services are another way for nodes to communicate with each other. Services allow nodes to send requests and receive responses. You can use the rosservice directive to manipulate services.
- roservice args /service: output service parameters
- rosservice call /service: call the service according to the command line parameters
- rosservice find msgtype: query services by service type
- rosservice info /service: output service information
- Ross service list: lists the active service list
- rosservice type /service: output service type
- rosservice uri /service: outputs the ROSRPC URI service
2. Use of services
Use rosservice list to list all services. Use rosservice call [service] [args] to call a service. For example, rosservice call /clear can clear the lines on the turtle map.
In addition, use rossrv show turnlesim / spawn to view the detailed parameters of the / spawn service.
With these parameters, you can call the / spawn service to create a second turtle.
rosservice call /spawn 3 3 0.5 "new_turtle"
3.4 parameter server
1. rosparam instruction
The parameter server stores the shared data that can be accessed by all nodes. The parameter server can be managed through the rosparam instruction.
rosparam instruction | effect |
---|---|
rosparam set parameter value | Set parameter value |
rosparam get parameter | Get parameter value |
rosparam load file | Load parameters from file |
rosparam dump file | Save parameters to file |
rosparam delete parameter | Delete parameter |
rosparam list | List all parameter names |
2. Use parameter server
Taking the Little Turtle program as an example, we can see that the background is the parameter of the turnlesim node by listing the parameter list through the rosparam list. Therefore, we can obtain the parameter value through the get instruction.
rosparam list rosparam get /turtlesim/background_g rosparam set /turtlesim/background_g 200
4, Creation and operation of nodes
This part will take a specific experiment as an example to introduce the method of creating nodes by creating a talker and a listener and realizing the information exchange between them.
4.1 creating source files
First enter the workspace ~ / dev / catkin_ Feature pack test in WS folder_ In the package / SRC / folder, create two CPP files here as the sender and receiver of the message. Here I will talk about two source files named talker.cpp and listener.cpp respectively.
//talker.cpp #include "ros/ros.h" // Contains the necessary files for the ROS node #include "std_msgs/String.h" // Contains the message type to use #include <sstream> int main(int argc, char **argv){ ros::init(argc, argv, "talker"); //Start the node and set the name ros::NodeHandle n; //Sets the handle of the node process ros::Publisher chatter_pub = n.advertise<std_msgs::String>("message", 1000); //Set the node as the publisher, set the subject name as message, and buffer 1000 messages ros::Rate loop_rate(10); //Data transmission frequency 10HZ while(ros::ok()){ std_msgs::String msg; std::stringstream ss; ss << "I'm talker node~~~"; msg.data = ss.str(); //A message variable was created ROS_INFO("%s", msg.data.c_str()); //Screen output message information chatter_pub.publish(msg); //Release news ros::spinOnce(); //If a subscriber appears, all topics are updated loop_rate.sleep(); } return 0; }
//listener.cpp #include "ros/ros.h" #include "std_msgs/String.h" //Callback function. The node will call this function every time it receives a message void messageCallback(const std_msgs::String::ConstPtr& msg){ ROS_INFO("I am listener, I heard: [%s]",msg->data.c_str()); } int main(int argc, char **argv){ ros::init(argc, argv, "listener"); ros::NodeHandle n; ros::Subscriber sub = n.subscribe("message", 1000, messageCallback); //Create a subscriber, get messages from the message topic, set 1000 messages in the buffer, and the callback function for processing messages is messageCallback ros::spin(); //Message callback processing, and it will not be returned after calling return 0; }
4.2 modify CMakeLists.txt
Edit catkin_ ws/src/test_ CMakeLists.txt in package /. Add the following content at the end.
#include_directories( include ${catkin_INCLUDE_DIRS} ) # Specifies the name of the compiled executable add_executable(talker src/talker.cpp) add_executable(listener src/listener.cpp) # Define the dependent files for the target add_dependencies(talker test_package_generate_messages_cpp) add_dependencies(listener test_package_generate_messages_cpp) target_link_libraries(talker ${catkin_LIBRARIES}) target_link_libraries(listener ${catkin_LIBRARIES})
4.3 compilation node
Go back to the workspace root directory and compile:
cd ~/dev/catkin_ws catkin_make
If The dependency target does not exist. Error occurs, change the cmake version beginning with CMakeLists.txt to 2.8.3.
Environment variables need to be set after compilation
echo "source ~/ros/tr3_6/devel/setup.bash" >> ~/.bashrc source ~/.bashrc
4.4 operation node
Then start running the node, running roscore first
roscore
Then open two windows to run separately
rosrun test_package example1_a rosrun test_package example1_b
You can see the acceptance and sending of messages.
5, Creation and use of services
In this section, two nodes will be created as server and client respectively. The data transmission of the two nodes and the function of digital summation will be realized through the call of services.
5.1 creating msg files
Before using the service, you first need to create msg and srv files, which are used to describe the data types and data values transmitted.
1. First create the msg file
In test_ Create the MSG folder under the package function package, and create a new file test in the MSG folder_ msg.msg. Enter the following in the file:
int32 num1 int32 num2 int32 num3
2. Edit the package.xml file
Find the following two lines in the package.xml file and uncomment them <! --- >
<!-- <build_depend>message_generation</build_depend> --> <!-- <exec_depend>message_runtime</exec_depend> -->
<build_depend>message_generation</build_depend> <exec_depend>message_runtime</exec_depend>
3. Edit the CMakeLists.txt file
Open the CMakeLists.txt file in the function pack directory.
find_package(), in which message is added_ Generation is as follows:
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs message_generation )
Find the following two paragraphs, uncomment them, and delete the test you just created_ Message.msg the message name is added
## Generate messages in the 'msg' folder add_message_files( FILES test_msg.msg )
## Generate added messages and services with any dependencies listed here generate_messages( DEPENDENCIES std_msgs )
4. Compilation test
After the above steps, compile with the following command:
cd ~/dev/catkin_ws/ catkin_make
After compilation, to check whether the msg file just created is successfully compiled, use the rosmsg show command:
rosmsg show test_package/test_msg
If the output is the same as test_ The contents in the msg.msg file are consistent, indicating that the compilation is correct.
5.2 creating srv files
1. Create srv file
In test_ Create an SRV folder under the package function package, and create a new file test in the SRV folder_ srv.srv. Enter the following in the file:
int32 num1 int32 num2 int32 num3 --- int32 sum
2. Edit the package.xml file
The package.xml file has been edited when the msg file is created. No additional modification is required here.
3. Edit CMakeLists.txt
Find catkin_package, uncomment it and add correct data as follows:
catkin_package( # INCLUDE_DIRS include # LIBRARIES test_package # CATKIN_DEPENDS roscpp std_msgs # DEPENDS system_lib CATKIN_DEPENDS message_runtime )
Cancel add_service_files and add the name of the service file just created.
## Generate services in the 'srv' folder add_service_files( FILES test_srv.srv )
4. Compilation test
After the above files are created and modified, use the following command to compile:
cd ~/dev/catkin_ws catkin_make
After compilation, to check whether the service file is compiled correctly, you can use the rossrv show command:
rossrv show test_package/test_srv.srv
If the print content is different from test_ The contents in the srv.srv file are consistent, indicating that the compilation is correct.
5.3 creating. cpp source files
1. Create source file
In the src directory in the function pack folder, click catkin_ws/test_package/src, create two. CPP files, server.cpp and client.cpp, as the server and client respectively.
#include "ros/ros.h" #include "test_package/test_srv.h" // Contains the created SRV file //Sum the three variables and send the calculation results to other nodes bool add(test_package::test_srv::Request &req, test_package::test_srv::Response &res){ res.sum = req.num1 + req.num2 + req.num3; ROS_INFO("request: num1=%ld, num2=%ld, num3=%ld", (int)req.num1, (int)req.num2, (int)req.num3); ROS_INFO("sending back response: [%ld]", (int)res.sum); return true; } int main(int argc, char **argv){ ros::init(argc, argv, "add_3_ints_server"); ros::NodeHandle n; //Create the server side of the service "add_3_ints" and broadcast it in ROS ros::ServiceServer service = n.advertiseService("add_3_ints", add); ROS_INFO("Ready to add 3 ints!"); ros::spin(); return 0; }
#include "ros/ros.h" #include "test_package/test_srv.h" #include <cstdlib> int main(int argc, char **argv){ ros::init(argc, argv, "add_3_ints_client"); if(argc != 4){ ROS_INFO("usage: add_3_ints_client num1 num2 num3"); return 1; } ros::NodeHandle n; //Create a client with the name "add_3_ints" ros::ServiceClient client = n.serviceClient<test_package::test_srv>("add_3_ints"); //Create an instance of the srv file and add the data value to be sent test_package::test_srv srv; srv.request.num1 = atoll(argv[1]); srv.request.num2 = atoll(argv[2]); srv.request.num3 = atoll(argv[3]); //Call the service and send data. If the call is successful, the server will return true; otherwise, it will return false if(client.call(srv)){ ROS_INFO("Sum: %ld", (long int)srv.response.sum); } else{ ROS_ERROR("Failed to call service add_3_ints"); return 1; } return 0; }
2. Edit CMakeLists.txt
add_executable(server src/server.cpp) add_executable(client src/client.cpp) add_dependencies(server test_package_generate_messages_cpp) add_dependencies(client test_package_generate_messages_cpp) target_link_libraries(server ${catkin_LIBRARIES}) target_link_libraries(client ${catkin_LIBRARIES})
5.4 test procedure
Back to catkin_ws workspace, compile.
cd ~/dev/catkin_ws catkin_make
After compiling, open a terminal and run roscore, then open two new terminal windows and run the following code respectively
rosrun test_package server
rosrun test_package client 6 4 2
It can be seen that the server and client have realized message communication and completed the sum calculation of three numbers.
6, Configuration of startup file
Previously, we have realized the creation and use of nodes, but each node needs to open different command line windows for execution. If there are more nodes, it will be very troublesome to start nodes.
Through the startup file, we can start multiple nodes in the command line window. We only need to run the file with the suffix. launch to start multiple nodes.
6.1 creating a. launch file
First, create a folder called launch in the function package, and create the test.launch file in it.
roscd test_package mkdir launch cd launch vim test.launch
Enter the following in the test.launch file:
<?xml version="1.0"?> <launch> <node name="talker" pkg="test_package" type="talker" /> <node name="listener" pkg="test_package" type="listener" /> </launch>
6.2 startup node
The startup file written above can start the talker and listener nodes of the previous experiment. The startup commands are as follows:
roslaunch test_package test.launch
The system will output the following information, indicating that the startup is successful.
Use the rosnode list to list the active nodes. You can see that we have successfully started the talker and listener nodes.
If you want to see the information passed by two nodes, you can use rqt_console
7, Use of dynamic parameters
Generally, when writing a node, we can only initialize the variables in the node with data. If we want to change the values of these variables, we can use the subject, service or parameter server, but this method cannot be updated dynamically online. If the listener does not actively query, we cannot know whether the parameters are updated. Sometimes we need to dynamically update parameters online, so we need to use dynamic parameters.
7.1 creating a profile
First, create a new folder named CFG in the function package, and create a test.cfg file in it.
roscd test_package mkdir cfg cd cfg vim test.cfg
Add the following code in test.cfg:
# Initialize ROS and import parameter generator #!/usr/bin/env python PACKAGE = "test_package" from dynamic_reconfigure.parameter_generator_catkin import * # Initialize the parameter generator. We can add parameters through gen gen = ParameterGenerator() # Add different parameter types and set default values, descriptions, value ranges, etc # gen.add(name, type, level, description, default, min, max) gen.add("double_param", double_t, 0, "A double parameter", .1, 0, 1) gen.add("str_param", str_t, 0, "A string parameter", "test_default_string") gen.add("int_param", int_t, 0, "An Integer parameter", 1, 0, 100) gen.add("bool_param", bool_t, 0, "A Boolean parameter", True) size_enum = gen.enum([gen.const("Low", int_t, 0, "Low is 0"), gen.const("Medium", int_t, 1, "Medium is 1"), gen.const("High", int_t, 2, "High is 2"), gen.const("Exlarge", int_t, 3, "Exlarge is 3")], "Select from the list") gen.add("size", int_t, 0, "Select from the list", 1, 0, 3, edit_method=size_enum) # Generate the necessary files and exit the program exit(gen.generate(PACKAGE, "test_package", "test_"))
Since test.cfg is an executable file executed by ROS, we need to change the file permissions:
chmod a+x test.cfg
7.2 modify CMakeLists.txt to add the compilation of the configuration file
Open CMakeLists.txt and find_package, add dynamic at the end_ The reconfigure is as follows:
find_package(catkin REQUIRED COMPONENTS roscpp std_msgs message_generation dynamic_reconfigure )
Find generate_dynamic_reconfigure_options, uncomment and change the internal configuration file to the newly created configuration file.
## Generate dynamic reconfigure parameters in the 'cfg' folder generate_dynamic_reconfigure_options( cfg/test.cfg )
7.3 creating nodes
Next, you need to create a new node with dynamic configuration support.
Create a new file in the src folder as follows:
roscd test_package vim src/dynamic_param.cpp
Write the following code in the file:
#include <ros/ros.h> #include <dynamic_reconfigure/server.h> #include <test_package/test_Config.h> //The callback function will output the new value of the parameter, and the parameter name must be the same as the test.cfg configuration file void callback(test_package::test_Config &config, uint32_t level){ ROS_INFO("Reconfigure Request: %d %f %s %s %d", config.int_param, config.double_param, config.str_param.c_str(), config.bool_param?"True":"False", config.size); } int main(int argc, char **argv){ ros::init(argc, argv, "test_dynamic_reconfigure"); //initialize server dynamic_reconfigure::Server<test_package::test_Config> server; //Send a callback function to the server. When the server gets a reconfiguration request, it will call the callback function dynamic_reconfigure::Server<test_package::test_Config>::CallbackType f; f = boost::bind(&callback, _1, _2); server.setCallback(f); ros::spin(); return 0; }
7.4 modify CMakeLists.txt to add node compilation
add_executable(dynamic_param src/dynamic_param.cpp) add_dependencies(dynamic_param test_package_gencfg) target_link_libraries(dynamic_param ${catkin_LIBRARIES})
7.5 operation configuration
Open three terminal command line windows and run the following commands respectively:
roscore rosrun test_package dynamic_param rosrun rqt_reconfigure rqt_reconfigure
When the execution is complete, you will see an rqt_reconfigure window, in which you can dynamically configure node parameters, and you can see the changes of command line printing parameters when adjusting parameters.