ROS series: Chapter 4 (6)

Article directory

4. ROS operation management

This chapter is mainly to solve the multi-level deep ROS system, associating different function packages, starting a large number of ROS nodes, function packages, nodes, topics, parameter duplication, and communication problems between nodes on different hosts;

  • Master the usage syntax of meta-function packages;
  • Master the usage syntax of launch files;
  • Understand what ROS workspace coverage is and what security risks exist;
  • Master the processing method when the node name is duplicated;
  • Master the handling method when the topic name is duplicated;
  • Master the processing method when the parameter name is duplicated;
  • It can realize ROS distributed communication.

1. ROS meta function package

Metapackage is a Linux file management system concept. It is a virtual package in ROS, which has no substantive content, but it depends on other software packages. In this way, other packages can be combined.

effect:

The meta-function package depends on some other function packages in ROS, and other dependencies will be installed when installing this package;

Implementation process:

  1. Right-click src and select Create Catkin Package;
  2. Enter the name of the function package plumbing_my, add a function package that does not depend on the function package dependency, and add the dependency package in package.xml after pressing Enter:

<exec_depend>plumbing_pub_sub</exec_depend>
<exec_depend>plumbing_server_client</exec_depend>
<exec_depend>plumbing_param_server</exec_depend>

​ Add meta feature package request:

<export>
 <!-- Other tools can request additional information be placed here -->
 <metapackage/>
</export>
  1. Modify CMakeLists.txt, the content is as follows:

    cmake_minimum_required(VERSION 3.0.2)
    project(demo)
    find_package(catkin REQUIRED)
    catkin_metapackage()
    

    Note: The last line in the CMakeLists.txt cannot have a newline, and there are only four lines of code, and the second line is the name of the function package.

    Just compile and run;

2. ROS node runs and manages launch files

The launch file is a file in XML format, which can start multiple local and remote nodes, and can also set parameters in the parameter server;
function:

Simplify the configuration and startup of nodes and improve the startup efficiency of ROS programs

Use:
Take the little turtle as an example:

  1. Create a new launch file
    Add a launch directory under the function package, create a new xxxx.launch file under the directory, and edit the launch file:
<launch>
    <node pkg="turtlesim" type="turtlesim_node"     name="myTurtle" output="screen" />
    <node pkg="turtlesim" type="turtle_teleop_key"  name="myTurtleContro" output="screen" />
</launch>
  1. call launch file
roslaunch 包名 xxx.launch

**Note: ** When the roslaunch command executes the launch file, it will automatically determine whether there is roscore, and if not, call roscore; ctrl+shift+~ to quickly start the terminal

2.1 launch file—launch tag

The tag is the root tag of all launch files and acts as a container for other tags

Attributes:

deprecated = "Deprecated Declaration"

effect:

Inform the user that the current launch file is deprecated and will not run

Subset labels:

All other tags are children of launch

Code example:

<launch deprecated = "当前版本已经过时,请停止使用!">
    <node pkg="turtlesim" type="turtlesim_node"     name="myTurtle" output="screen" />
    <node pkg="turtlesim" type="turtle_teleop_key"  name="myTurtleContro" output="screen" />
</launch>

2.2 launch file—node label

The label is used to specify the ROS node, which is the most common label. It should be noted that: the roslaunch command cannot guarantee to start the node in the order of declaration of the node (the start of the node is multi-process)

Attributes:

Attributes Function
pkg="package name" the package the node belongs to
type=“nodeType” Node type (executable with the same name)
name=“nodeName” NodeName (the name of the node in the ROS network topology)
args="xxx xxx xxx" (optional) Pass parameters to node
machine="machine name" Start the node on the specified machine
respawn="true|false" (optional) Whether to automatically restart if the node exits
respawn_delay="N" (optional) If respawn is true, start the node after a delay of N seconds
required="true|false" (optional) Whether the node must, if true, then if the node exits, the entire roslaunch will be killed
ns="xxx" (optional) Start the node in the specified namespace xxx
clear_params="true|false" (optional) Before starting, delete all parameters of the private space of the node
output="log|screen" (optional) Log sending target, can be set to log log file, or screen screen, the default is log

Subset labels:

  • env environment variable settings
  • remap remaps node names
  • rosparam parameter setting
  • param parameter setting

Code example:

<?xml version="1.0"?>
<launch>
<!-- <launch deprecated="此文件已经过时,不建议使用!"> -->

    <!-- 启动的节点 -->
    <!-- respawn="true" 节点关闭后自动重启 -->
    <!-- respawn_delay="10" 在respawn设置为true后可以通过delay延时自动启动节点  -->
    <!-- required="true"  节点退出后关闭整个roslaunch -->
    <!-- 当上述三个在一行时,可能会出现错误提示The traceback for the exception was written to the log file -->
    <!-- ns="hello"可以在指定命名空间启动节点  避免重名问题 -->
    <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen" />

    <!-- 键盘控制节点 -->
    <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>


</launch>

2.3launch file—include tag

Attributes:

  • file="$(find package name)/xxx/xxx.launch"

    file paths to include

  • ns="xxx" (optional)

    Import files in the specified namespace

effect:

Used to import launch files in other xml formats into the current file

Subset labels:

  • env environment variable settings
  • arg to pass arguments to the included file

Code example:

<launch>
    <!-- 包含文件路径   $(find 功能包名)/xxx/yyy.launch   -->
    <include file="$(find launch01_basic)/launch/start_turtle.launch"/>
</launch>

2.4launch file—remap label

Attributes:

  • file="$(find package name)/xxx/xxx.launch"

    file paths to include

  • ns="xxx" (optional)

    Import files in the specified namespace

effect:

for topic renaming

Subset labels:

  • none

Code example:

<?xml version="1.0"?>
<launch>
<!-- <launch deprecated="此文件已经过时,不建议使用!"> -->

    <!-- 启动的节点 -->
    <!-- respawn="true" 节点关闭后自动重启 -->
    <!-- respawn_delay="10" 在respawn设置为true后可以通过delay延时自动启动节点  -->
    <!-- required="true"  节点退出后关闭整个roslaunch -->
    <!-- 当上述三个在一起时,会出现错误提示The traceback for the exception was written to the log file -->
    <!-- ns="hello"可以在指定命名空间启动节点  避免重名问题 -->
    <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen" >
        <remap from="/turtle1/cmd_vel" to="/cmd_vel"/>
    </node>
    <!-- 键盘控制节点 -->
    <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>   
</launch>

Code implementation function:

The topic name sent by the ros built-in keyboard control node is /cmd_vel, and the turtle gui subscribes to /turtle1/cmd_vel. Because the topic names are inconsistent, it is not possible to directly use the keyboard control node to control the turtle gui, so the node node that generates the turtle gui needs to be The label redefines the topic name, that is, /turtle1/cmd_vel is changed to /cmd_vel"; you can use rostopic list to view the current topic communication list.

Use rqt_graph to get the current topic communication more clearly

2.5launch file—param tag

Attributes:

  • name="namespace/parameter name"

    The parameter name, which can contain a namespace

  • value="xxx" (optional)

    Define the parameter value, if omitted here, you must specify an external file as the parameter source

  • type="str|int|double|bool|yaml" (optional)

    Specify the parameter type, if not specified, roslaunch will try to determine the parameter type, the rules are as follows:

    • If the number containing '.' is not parsed as a floating point type, otherwise it is an integer type
    • "true" and "false" are bool values ​​(case insensitive)
    • else is a string

effect:

Applied to setting parameters on the parameter server, the parameter source can be defined with value in the tag, or loaded from an external file. When it is in the node tag, it is equivalent to a private namespace

Subset labels:

  • none

Code example:

<?xml version="1.0"?>
<launch>
<!-- <launch deprecated="此文件已经过时,不建议使用!"> -->

    <!-- 启动的节点 -->
    <!-- respawn="true" 节点关闭后自动重启 -->
    <!-- respawn_delay="10" 在respawn设置为true后可以通过delay延时自动启动节点  -->
    <!-- required="true"  节点退出后关闭整个roslaunch -->
    <!-- 当上述三个在一起时,会出现错误提示The traceback for the exception was written to the log file -->
    <!-- ns="hello"可以在指定命名空间启动节点  避免重名问题 -->
    <!-- param标签 使用:向参数服务器设置参数 -->
    <!-- param标签格式1 会在参数前私有命名,node节点名称 -->
    <param name="param_A"  type="int" value="100"/>
    <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen" >
        <remap from="/turtle1/cmd_vel" to="/cmd_vel"/>
        <!-- param标签格式2 launch目录下,node标签外 -->
        <param name="param_B" type="double" value="3.14"/>
    </node>
    <!-- 键盘控制节点 -->
    <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>   
</launch>

Code implementation function:

Set the parameters in the param parameter, you can view it in the rosparam list, and get the parameters through rosparam get /xxx

2.6launch file—rosparam tag

Attributes:

  • command="load | dump | delete" (optional, default load)

    Load, export or delete parameters

  • file=“$(find xxxxx)/xxx/yyy…”

    yaml file to load or export to

  • param="parameter name"

  • ns="namespace" (optional)

effect:

Import parameters from yaml files, or export parameters to yaml files, and can also be used to delete parameters. If defined under the node tag, it will be considered private

Subset labels:

  • none

Code example:

start_turtle.launch

<?xml version="1.0"?>
<launch>
    <!-- <launch deprecated="此文件已经过时,不建议使用!"> -->

    <!-- 启动的节点 -->
    <!-- respawn="true" 节点关闭后自动重启 -->
    <!-- respawn_delay="10" 在respawn设置为true后可以通过delay延时自动启动节点  -->
    <!-- required="true"  节点退出后关闭整个roslaunch -->
    <!-- 当上述三个在一起时,会出现错误提示The traceback for the exception was written to the log file -->
    <!-- ns="hello"可以在指定命名空间启动节点  避免重名问题 -->
    <!-- param标签 使用:向参数服务器设置参数 -->
    <!-- param标签格式1 launch目录下,node标签外 -->
    <param name="param_A" type="int" value="100"/>
    <!-- rosparam 使用:操作参数服务器数据 -->
    <!-- rosparam格式1: launch 下,node 外 -->
    <!-- 加载参数 -->
    <rosparam command="load" file="$(find launch01_basic)/launch/params.yaml"/>

    <!-- 导出参数 -->
    <!-- <rosparam command="dump" file="$(find launch01_basic)/launch/params_out.yaml"/> -->

    
    <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen">
        <remap from="/turtle1/cmd_vel" to="/cmd_vel"/>
        <!-- param标签格式2 node标签内  会在参数前私有命名,node节点名称-->
        <param name="param_B" type="double" value="3.14"/>
        <!--rosparam格式2: node 内 -->
        <rosparam command="load" file="$(find launch01_basic)/launch/params.yaml"/>

    </node>
    <!-- 键盘控制节点 -->
    <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>
</launch>

dump.launch

<?xml version="1.0"?>
<launch>
    <rosparam command="dump" file="$(find launch01_basic)/launch/params_out.yaml"/>
    <!-- 删除参数 -->
    <rosparam command="delete" param="bg_B"/> 
</launch>

Code implementation function:

Use the rosparam command to set the parameters in the param parameter, you can view it in the rosparam list, and get the parameters through rosparam get /xxx

Notice:

1. When setting the three primary colors in the yaml file, a space must be added after the colon, otherwise an error will be reported

2. rosparam has priority, and rosparam will be run first, so if the export data is not the target parameter, you can set another launch file to export the yaml file

2.7launch file—group label (group)

Attributes:

  • ns="namespace" (optional)

  • clear_params="true|false" (optional)

    Before starting, whether to delete all parameters of the group namespace (use with caution...this function is dangerous)

effect:

Nodes can be grouped, with the ns attribute, allowing nodes to belong to a namespace

Subset labels:

  • tags other than the launch tag

Code example:

turtles.launch

<?xml version="1.0"?>
<launch>

    <!-- 同时启动两队乌龟GUI以及键盘控制节点 -->
    <group ns="first">
        <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen"/>
        <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>
    </group>
    <group ns="second">
        <node name="my_turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen"/>
        <node name="my_key" pkg="turtlesim" type="turtle_teleop_key" output="screen"/>
    </group>
</launch>

Code implementation function:

After grouping, although the two GUIs have the same name, it will not happen that the one started later will stop the previous program

2.8launch file—arg label

Attributes:

  • name="parameter name"

  • default="default value" (optional)

  • value="value" (optional)

    Cannot coexist with default

  • doc="description"

    Parameter Description

effect:

Used for dynamic parameter passing, similar to function parameters, which can enhance the flexibility of launch files

Subset labels:

  • none

Code example:

turtles.launch

<?xml version="1.0"?>
<launch>

    <!-- 演示arg的使用,需要设置多个参数,参数使用的是同一个值(小车长度) -->
    <!-- <param name="A" value="0.5"/>
    <param name="B" value="0.5"/>
    <param name="C" value="0.5"/> -->

    <arg name="car_length" default="0.55"/>
    
    <param name="A" value="$(arg car_length)"/>
    <param name="B" value="$(arg car_length)"/>
    <param name="C" value="$(arg car_length)"/>
</launch>

Code implementation function:

Similar to declaring a global variable and assigning a value, you can directly change the value of the variable later, saving you the effort of line-by-line modification

Dynamic parameter passing function:

roslaunch launch01_basic arg.launch car_length:=0.6

3. ROS workspace coverage problem

Try to avoid the problem of ROS workspace coverage

**Problem description: **In different workspaces, there may be cases where the function package has the same name. At this time, if the function package with this name is called, the wrong path function package may be called, and confusion may occur when calling;

Reason analysis : ROS will parse the hidden folder .bashrc file and generate the ROS package path. The path information will arrange the path priority according to the order of the workspace configured in .bashrc, that is, the last configuration has the highest priority, and the higher the priority The lower the value, the current path priority can be viewed through the echo command. The higher priority in the front will be used first when the program is called. The sample code is as follows:

echo $ROS_PACKAGE_PATH 

**Conclusion:** When the function package has the same name, there will be a call priority, that is, the last configuration will be executed first, and you can view it through ROS_PACKAGE_PATH

BUG description:

When multiple workspaces are sourced in the .bashrc file, it may happen that only two workspaces are included in the ROS PACKAGE PATH, you can delete the build and devel directories of the custom workspace, re-catkin_make, and then reload. bashrc file, problem solved

4. Duplicate ROS node name

When you need to start a node with the same name or start the same node multiple times, you should pay attention to the problem of duplication of ROS node names

**Concept:**Namespace is to add a prefix to the name, and name remapping is to alias the name. Both of these strategies can solve the node duplicate name problem, and there are many ways to implement the two strategies:

  • rosrun command
  • launch file
  • Encoding implementation

The above three methods can avoid duplicate node names through namespace or name remapping. This section will demonstrate the use of the three one by one. The requirements to be realized by the three are similar.

4.1rosrun setting namespace and remapping

4.1.1rosrun set namespace

Syntax: rosrun package name node name __ns:= new name

Code example:

rosrun turtlesim turtlesim_node __ns:=ergouzi
rosrun turtlesim turtlesim_node __ns:=dagouzi

Both nodes are up and running;

4.1.2 rosrun name remapping

Syntax: rosrun package name node name __name:= new name

Code example:

rosrun turtlesim  turtlesim_node __name:=daqiang
rosrun turtlesim  turtlesim_node __name:=xiaoqiang

Both nodes are up and running;

4.1.3 rosrun namespace and name remapping superimposed use

语法: rosrun 包名 节点名 __ns:=新名称 __name:=新名称

Code example:

rosrun turtlesim  turtlesim_node __ns:=ergouzi __name:=daqiang 
rosrun turtlesim  turtlesim_node __ns:=dagouzi __name:=xiaoqiang

Both nodes are up and running;

甚至可以直接用  rosrun turtlesim  turtlesim_node /turtlesim_node:=daqiang  即/节点名称:=新名称

4.2 Launch file setting namespace and remapping

When using the syntax of the launch file, there are two attributes in the node tag: name and ns, which are used to implement name remapping and namespace settings respectively. It is also relatively simple to set up namespaces and name remapping using launch files.

launch file:

<?xml version="1.0"?>
<launch>
    <node name="turtlesim" pkg="turtlesim" type="turtlesim_node" output="screen"/>
    <!-- 名称重映射 -->
    <node name="t1" pkg="turtlesim" type="turtlesim_node" output="screen"/>
    <!-- 命名空间 -->
    <node name="turtlesim" ns="ergouzi" pkg="turtlesim" type="turtlesim_node" output="screen"/> 
    <!-- 命名空间 + 名称重映射 -->
    <node name="t2" ns="dagouzi" pkg="turtlesim" type="turtlesim_node" output="screen"/> 
</launch>

In the node tag in the launch file, the name attribute must exist, and the ns namespace is optional;

operation result:

rosnode list
/dagouzi/t2
/ergouzi/turtlesim
/rosout
/t1
/turtlesim

It can also be seen from here that the node label call is not executed strictly in the order of programming; it may be in the reverse order of calling;

4.3 Encoding settings namespace and remapping

If you customize the node implementation, you can more flexibly implement setting namespaces and name remapping;

4.3.1 C++ Implementation: Remapping

4.3.1.1 Name alias setting

Core code:ros::init(argc,argv,"zhangsan",ros::init_options::AnonymousName);

4.3.1.2 Execution

A timestamp is appended to the name.

4.3.2 C++ Implementation: Namespaces

4.3.2.1 Namespace Settings

core code

  std::map<std::string, std::string> map;
  map["__ns"] = "xxxx";
  ros::init(map,"wangqiang");
Copy
4.3.2.2 Execution effect

The node name sets the namespace.

5. ROS topic name setting

In ROS, the topic name may have the same name. When the subscribed message has the same name, there may be a problem when the subscriber receives an unnecessary message, which will cause the node to run abnormally; or you want the two to not communicate The nodes communicate on the topic, so it is necessary to modify the topic to be the same.

According to different prefixes, there are three types: global, relative, and private.

  • Global (the parameter name directly refers to the ROS system, which is at the same level as the node namespace)
  • Relative (the parameter name refers to the namespace of the node, which is at the same level as the node name)
  • private (the parameter name refers to the node name and is a child of the node name)

Name remapping is to alias the name and add a prefix to the name. This implementation is more complicated than node renaming. It not only uses the namespace as the prefix, but also uses the node name as the prefix. There are several ways to implement the two strategies:

  • rosrun command
  • launch file
  • Encoding implementation

This section will demonstrate the use of the three one by one, and the requirements to be realized by the three are similar.

case:

Use the ros-noetic-teleop-twist-keyboard function package to control the turtle display GUI

5.1 rosrun set topic remapping

**Syntax: **rosrun name remapping syntax: rorun package name node name topic name: = new topic name

5.1.1 Solution 1: Modify the keyboard control node to publish the topic name

Set the topic of the teleop_twist_keyboard node to/turtle1/cmd_vel

Start the keyboard control node:rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/turtle1/cmd_vel

Start the tortoise display node:rosrun turtlesim turtlesim_node

The two can achieve normal communication

5.1.2 Solution 2: Modify the subscription topic name of the turtle GUI node

Set the topic of the turtle display node to/cmd_vel

Start the keyboard control node:rosrun teleop_twist_keyboard teleop_twist_keyboard.py

Start the tortoise display node:rosrun turtlesim turtlesim_node /turtle1/cmd_vel:=/cmd_vel

The two can achieve normal communication

5.2 launch file setting topic remapping

** Syntax: ** Use remap tag

<node pkg="xxx" type="xxx" name="xxx">
    <remap from="原话题" to="新话题" />
</node>
5.2.1 Solution 1: Set the topic of the teleop_twist_keyboard node to/turtle1/cmd_vel
<?xml version="1.0"?>
<!-- 执行键盘功能包直接控制小乌龟 -->
<launch>
    <!-- 将乌龟的话题设置与键盘控制一致 -->
    <node name="my_turtle" pkg="turtlesim" type="turtlesim_node" >
       
    </node>

    <!-- 将乌龟的话题设置与键盘控制一致 -->
    <node name="key" pkg="teleop_twist_keyboard" type="teleop_twist_keyboard.py">
        <remap from="/cmd_vel" to="/turtle1/cmd_vel"/>
    </node>
</launch>

The two can achieve normal communication

5.2.2 Solution 2: Set the topic of the turtle display node to/cmd_vel
<?xml version="1.0"?>
<!-- 执行键盘功能包直接控制小乌龟 -->
<launch>
    <!-- 将乌龟的话题设置与键盘控制一致 -->
    <node name="my_turtle" pkg="turtlesim" type="turtlesim_node" >
        <remap from="/turtle1/cmd_vel" to="/cmd_vel"/>   
    </node>
    <node name="key" pkg="teleop_twist_keyboard" type="teleop_twist_keyboard.py"/>
    <!-- 将乌龟的话题设置与键盘控制一致 -->

</launch>

The two can achieve normal communication

5.3 Code setting topic name

The name of the topic has a certain relationship with the namespace of the node and the name of the node. The topic name can be roughly divided into three types:

  • Global (topics refer to the ROS system, which is at the same level as the node namespace)
  • Relative (the topic refers to the namespace of the node, which is at the same level as the node name)
  • Private (topic refers to the node name, which is a child of the node name)

[External link image transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the image and upload it directly (img-2SKGiOC6-1667583256847) (C:\Users\Haotian\AppData\Roaming\Typora\typora-user-images \1667384023357.png)]

Coding to demonstrate the specific relationship:

process:

5.3.1 Global Name C++ Implementation

**Format:** /The name starting with, has nothing to do with the node name

For example: /xxx/yyy/zzz

Example 1:ros::Publisher pub = nh.advertise("/chatter",1000);

Result 1:/chatter

Example 2:ros::Publisher pub = nh.advertise("/chatter/money",1000);

Result 2:/chatter/money

Code example:

#include "ros/ros.h"
#include "std_msgs/String.h"
/**
 * @brief 需求:演示不同类型的话题名称设置
 *             设置话题名称以及命名空间
 *  
 *
 */
int main(int argc, char *argv[])
{
    
    

    ros::init(argc, argv, "hello");
    ros::NodeHandle nh;
    //核心:设置不同类型的话题
    // 1.全局 --- 话题名称需要以 / 开头(也可以设置自己的命名空间),此时话题名称与节点(命名空间以及名称)没有任何关系
    // ros::Publisher pub = nh.advertise<std_msgs::String>("/chatter",1000);
    ros::Publisher pub = nh.advertise<std_msgs::String>("/yyy/chatter", 1000);

    // 2.相对

    // 3.私有

    while (ros::ok())
    {
    
    
        

    }
    return 0;
}

5.3.2 Relative name C++ implementation

**Format:** Non- /beginning names, refer to the namespace (level with the node name) to determine the topic name

Example 1:ros::Publisher pub = nh.advertise("chatter",1000);

Result 1:xxx/chatter

Example 2:ros::Publisher pub = nh.advertise("chatter/money",1000);

Result 2:xxx/chatter/money

Code example:

#include "ros/ros.h"
#include "std_msgs/String.h"
/**
 * @brief 需求:演示不同类型的话题名称设置
 *             设置话题名称以及命名空间
 *  
 *
 */
int main(int argc, char *argv[])
{
    
    

    ros::init(argc, argv, "hello");
    ros::NodeHandle nh;
    //核心:设置不同类型的话题
    // 1.全局 --- 话题名称需要以 / 开头(也可以设置自己的命名空间),此时话题名称与节点(命名空间以及名称)没有任何关系
    // ros::Publisher pub = nh.advertise<std_msgs::String>("/chatter",1000);
    // ros::Publisher pub = nh.advertise<std_msgs::String>("/yyy/chatter", 1000);

    // 2.相对 --- 非 / 开头    相对的会把话题后缀到命名空间后方,与命名空间同级
    // ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",1000);
    ros::Publisher pub = nh.advertise<std_msgs::String>("yyy/chatter", 1000);

    // 3.私有

    while (ros::ok())
    {
    
    
        

    }
    

    return 0;
}

5.3.3 Private Names C++

**Format:** ~Names beginning with

Example 1:

ros::NodeHandle nh("~");
ros::Publisher pub = nh.advertise("chatter",1000);

Result 1:/xxx/hello/chatter

Example 2:

ros::NodeHandle nh("~");
ros::Publisher pub = nh.advertise("chatter/money",1000);

Result 2:/xxx/hello/chatter/money

PS: When using ~, and the topic name sometimes /starts with , then the topic name is absolute

Example 3:

ros::NodeHandle nh("~");
ros::Publisher pub = nh.advertise("/chatter/money",1000);

Result 3:/chatter/money

Code example:

#include "ros/ros.h"
#include "std_msgs/String.h"
/**
 * @brief 需求:演示不同类型的话题名称设置
 *             设置话题名称以及命名空间
 *  
 *
 */
int main(int argc, char *argv[])
{
    
    

    ros::init(argc, argv, "hello");
    // ros::NodeHandle nh;
    //核心:设置不同类型的话题
    // 1.全局 --- 话题名称需要以 / 开头(也可以设置自己的命名空间),此时话题名称与节点(命名空间以及名称)没有任何关系
    // ros::Publisher pub = nh.advertise<std_msgs::String>("/chatter",1000);
    // ros::Publisher pub = nh.advertise<std_msgs::String>("/yyy/chatter", 1000);

    // 2.相对 --- 非 / 开头    相对的会把话题后缀到命名空间后方,与命名空间同级
    // ros::Publisher pub = nh.advertise<std_msgs::String>("chatter",1000);
    // ros::Publisher pub = nh.advertise<std_msgs::String>("yyy/chatter", 1000);

    // 3.私有--- 需要创建特定句柄 NodeHandle  nh(~);
    ros::NodeHandle nh("~");
    // ros::Publisher pub = nh.advertise<std_msgs::String>("chatter", 1000);
    // ros::Publisher pub = nh.advertise<std_msgs::String>("yyy/chatter", 1000);

    //注意:如果私有的NH创建的话题以 / 开通(全局话题) 生成的话题就是全局话题而非私有话题
    //全局话题优先级更高
    ros::Publisher pub = nh.advertise<std_msgs::String>("/yyy/chatter", 1000);//私有句柄 话题名称变全局名称时 变成全局话题,因为全局话题优先级最高

    while (ros::ok())
    {
    
    
        

    }
    

    return 0;
}

6. ROS topic name setting


In ROS, the node name topic name may have the same name, and the parameter name may also have the same name. However, there is no name remapping operation for parameter duplication. In order to avoid duplication, the method of adding a prefix to the parameter is used, which is similar to the global, relative, and private methods of the topic name in the previous section;

  • Global (the parameter name directly refers to the ROS system, which is at the same level as the node namespace)
  • Relative (the parameter name refers to the namespace of the node, which is at the same level as the node name)
  • private (the parameter name refers to the node name and is a child of the node name)

There are also three ways to set parameters:

  • rosrun command
  • launch file
  • Encoding implementation

6.1 rosrun setting parameters

When rosrun starts the node, you can set parameters:

**Syntax:**rosrun function package package name node name_parameter name:=parameter value

1. Setting parameters

rosrun turtlesim turtlesim_node _radius:=3.56

2. run

rosparam listView node information and display the results:

/rosdistro
/roslaunch/uris/host_wht_vpc__35637
/rosversion
/run_id
/turtlesim/background_b
/turtlesim/background_g
/turtlesim/background_r
/turtlesim/radius

The results show that the parameter A prefixes the node name, which means that the rosrun execution setting parameter name uses the private mode

6.2 launch setting parameters

The method of setting parameters through the launch file has been introduced before, and parameters can be set outside the node label or through param or rosparam in the node label. Parameters set outside the node tag are global, refer to / , parameters set inside the node tag are private, refer to /namespace/nodename.

1. Setting parameters

Take the param tag as an example to set parameters

<!-- 设置参数 -->
<launch>
    <!-- 格式1:全局 -->
    <param name="radius" value="0.2"/>
    <node name="my_turtle" pkg="turtlesim" type="turtlesim_node" ns="xxx">
        <!-- 格式2:私有 -->
        <param name="radius" value="0.08"/>
    </node>
</launch>

2. run

rosparam listView node information and display the results:

/radius
/rosdistro
/roslaunch/uris/host_wht_vpc__45767
/rosversion
/run_id
/xxx/my_turtle/background_b
/xxx/my_turtle/background_g
/xxx/my_turtle/background_r
/xxx/my_turtle/radius

The running results are consistent with expectations.

6.3 Encoding setting parameters

The encoding method can be set more conveniently: global, relative and private parameters.

6.3.1 ros::param setting parameters

The calling API for setting parameters is ros::param::set. In this function, parameter 1 is passed in the parameter name, and parameter 2 is the value of the parameter passed in. When setting the parameter name in parameter 1, if it starts with /, it is a global parameter. If it starts with ~, then it is a private parameter, if it does not start with either / or ~, then it is a relative parameter.

Code example:

#include <ros/ros.h>

int main(int argc, char* argv[])
{
    
    
    ros::init(argc, argv, "hello");
    ros::NodeHandle nh;
    /*
         使用ros::param来设置参数
    */
    //全局,和命名空间以及节点名称无关
    ros::param::set("/radiusA", 100);
    //相对,参考命名空间
    ros::param::set("radiusB", 100);  
    //私有,参考命名空间与节点名称
    ros::param::set("~radiusC", 100); 

    return 0;
}

When running, assume that the set namespace is xxx, the node name is yyy, use rosparam list to view:

/radiusA
/rosdistro
/roslaunch/uris/host_wht_vpc__46715
/rosversion
/run_id
/xxx/hello/radiusC
/xxx/radiusB

6.3.2 ros::NodeHandle setting parameters

When setting parameters, you first need to create a NodeHandle object, and then call the setParam function of the object. The parameter 1 of this function is the parameter name, and the parameter 2 is the parameter value to be set. If the parameter name starts with /, then it is a global parameter. If the parameter name If it does not start with /, then whether the parameter is a relative parameter or a private parameter is related to the NodeHandle object. If the NodeHandle object is created when the default no-argument construction is called, then the parameter is a relative parameter. If the NodeHandle object is created using: ros::NodeHandle nh("~"), then this parameter is a private parameter. Code example:

#include <ros/ros.h>

int main(int argc, char* argv[])
{
    
    
    ros::init(argc, argv, "hello");
    ros::NodeHandle nh;
    /*
         使用ros::param来设置参数
    */
    //全局,和命名空间以及节点名称无关
    ros::param::set("/radiusA", 100);
    //相对,参考命名空间
    ros::param::set("radiusB", 100);  
    //私有,参考命名空间与节点名称
    ros::param::set("~radiusC", 100);
    /*
         使用NodeHandle来设置参数
    */
    //全局,和命名空间以及节点名称无关
    nh.setParam("/radius_nh_A", 100);
    //相对,参考命名空间
    nh.setParam("radius_nh_B", 100);
    //私有,参考命名空间与节点名称
    ros::NodeHandle nh_private("~");
    nh_private.setParam("radius_nh_C", 100); 
    return 0;
}

When running, assume that the set namespace is xxx, the node name is yyy, use rosparam list to view:

/radiusA
/radius_nh_A
/rosdistro
/roslaunch/uris/host_wht_vpc__36311
/rosversion
/run_id
/yyy/hello/radiusC
/yyy/hello/radius_nh_C
/yyy/radiusB
/yyy/radius_nh_B

**Note:** If the parameters are abnormal, you can refresh the roscore once, and then re-run the rosparam list to refresh the display;

7. ROS distributed communication


ROS is a distributed computing environment. A running ROS system can consist of multiple nodes distributed across multiple computers. Depending on how the system is configured, any node may need to communicate with any other node at any time.

Therefore, ROS has certain requirements for network configuration:

  • There must be full bi-directional connectivity between all machines on all ports.
  • Each computer must announce itself by a name that all other computers can resolve.

accomplish

1. Prepare

First, ensure that different computers are in the same network. It is best to set fixed IPs separately. If it is a virtual machine, you need to change the network adapter to bridge mode;

2. Configuration file modification

Modify the /etc/hosts files of different computers respectively, and add the IP address and computer name of the other party to the file:

Host side:

从机的IP    从机计算机名

Slave side:

主机的IP    主机计算机名

After setting, you can use the ping command to test whether the network communication is normal.

IP address view name: ifconfig

Check the computer name: hostname

3. Configure host IP

Configure the IP address of the host

Add ~/.bashrc

export ROS_MASTER_URI=http://主机IP:11311
export ROS_HOSTNAME=主机IP

4. Configure slave IP

Configure the IP address of the slave machine, there can be multiple slave machines, and each set the following settings:

Add ~/.bashrc

export ROS_MASTER_URI=http://主机IP:11311
export ROS_HOSTNAME=从机IP

4. Configure slave IP

Configure the IP address of the slave machine, there can be multiple slave machines, and each set the following settings:

Add ~/.bashrc

export ROS_MASTER_URI=http://主机IP:11311
export ROS_HOSTNAME=从机IP

test

1. The host starts roscore (required)

2. The host starts the subscription node, and the slave starts the publishing node to test whether the communication is normal

3. Reverse test, the master starts the publishing node, the slave starts the subscription node, and tests whether the communication is normal

Guess you like

Origin blog.csdn.net/TianHW103/article/details/127699152