系列文章目录
木叶飞舞之【机器人ROS2】篇章_第一节、ROS2 humble及cartorgrapher安装
木叶飞舞之【机器人ROS2】篇章_第二节、turtlebot3安装
木叶飞舞之【机器人ROS2】篇章_第三节、给turtlebot3安装realsense深度相机
木叶飞舞之【机器人ROS2】篇章_第四节、ROS2非常简单的传参方式–利用NodeOptions和get_parameter方法
文章目录
- 系列文章目录
- 前言
- 一、launch文件传参的demo
- 1. 编写launch.py文件
- 2. 编写C++代码
- 3. 编写CMakeLists.txt
- 4. 编写package.xml
- 二、yaml文件传参的demo
- 1. 编写launch.py文件
- 2. 编写config.yaml文件
- 3. 编写C++代码
- 4. 同上
前言
很多时候,我们需要给ros节点传参数,参数一般写在launch文件或者yaml文件中,不会写在应用开发代码中,原因主要是编译比较费时。本节提供两种传参方法,一个是launch文件写参数,一个是yaml文件写参数。
一、launch文件传参的demo
- package名:hello_ros
- executable名: demo_pub
- node名: demo_pub
注意,你自己创建包的时候如果没有按照上述名字来写的话,那你记得拷贝代码时改成自己的名称
这个demo中,我们是直接在launch文件中写入了一个rgb_topic
的参数,赋值为’/camera/color/image_raw’
然后通过node节点来读取参数rgb_topic。读取的方法用的是rclcpp::NodeOptions
方法。这个声明参数的方法相较于传统的declare_parameter、get_parameter操作更加简单,大家可以尝试一下。
1. 编写launch.py文件
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
# 方法一、直接在launch文件中写参数
def generate_launch_description():
return LaunchDescription([
Node(
package='hello_ros',
executable='demo_pub',
name='demo_pub',
output='screen',
parameters=[{'rgb_topic':'/camera/color/image_raw'},{'depth_topic':'/camera/depth/image_raw'}]
)
])
2. 编写C++代码
#include <rclcpp/rclcpp.hpp>
#include "std_msgs/msg/string.hpp"
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
// 传参 方法一
rclcpp::NodeOptions nodeOptions;
nodeOptions.automatically_declare_parameters_from_overrides(true);
auto node2 = rclcpp::Node::make_shared("node2", nodeOptions);
std::string rgb_topic;
node2->get_parameter("rgb_topic", rgb_topic);
printf("===> %s \n", rgb_topic.c_str());
// 单线程执行器 灵活管理node节点,非堵塞
rclcpp::executors::SingleThreadedExecutor executor;
executor.add_node(node2);
std::thread([&executor]()
{ executor.spin(); })
.detach();
// rclcpp::spin(node2);
std::cout << "1111111111111" << std::endl;
rclcpp::shutdown();
return 0;
}
代码里用了ros2的单线程执行器SingleThreadedExecutor
,它可以解决传统的spin阻塞问题。假如你用
rclcpp::spin(node2);
那么后续的1111111111111打印就一直不会执行。
3. 编写CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(hello_ros)
# 启用C++14
add_compile_options(-std=c++14)
# 查找ROS2包
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
# 包含头文件目录
include_directories(include
)
# ------------------------------------------------------
# 添加可执行文件
add_executable(demo_pub src/demo_pub.cpp)
# 链接依赖库
ament_target_dependencies(demo_pub
rclcpp
sensor_msgs
cv_bridge
)
# ------------------------------------------------------
# 安装可执行文件
install(TARGETS
demo_pub
DESTINATION lib/${PROJECT_NAME}
)
# 安装其他文件,如参数文件、启动文件等
install(DIRECTORY
launch
config
DESTINATION share/${PROJECT_NAME}
)
# 导出依赖信息
ament_package()
4. 编写package.xml
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>hello_ros</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="yab@todo.todo">yab</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
运行结果跟launch文件里的参数一致。
二、yaml文件传参的demo
代码文件结构跟上个demo的区别就是新增了一个config文件夹和config.yaml文件
1. 编写launch.py文件
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
# 方法二、在yaml文件中写参数,利用launch文件来加载yaml文件
def generate_launch_description():
config_path = os.path.join(
get_package_share_directory('hello_ros'),
'config',
'config.yaml'
)
declare_param_file_cmd=DeclareLaunchArgument(
'param_file',
default_value= config_path
# 'Full path to the ROS2 parameters file'
)
return LaunchDescription([
declare_param_file_cmd,
Node(
package='hello_ros',
executable='demo_pub',
name='demo_pub',
output='screen',
parameters=[LaunchConfiguration('param_file')]
)
])
为了读取yaml文件,所以launch文件中增加了几个配置,分别是DeclareLaunchArgument
、LaunchConfiguration
。
- DeclareLaunchArgument是加载yaml配置文件路径
- LaunchConfiguration是把加载完的yaml文件进行解析
2. 编写config.yaml文件
yaml文件内容结构是 node名称、ros__parameters、自定义的参数名。其中ros__parameters
的下划线是两个下划线组合,千万要注意,不然会报错。(我就是被这个小问题困扰了很久)
特别注意:yaml文件结构一定要完全一样
demo_pub:
ros__parameters:
rgb_topic: "ryan"
3. 编写C++代码
#include <rclcpp/rclcpp.hpp>
#include "std_msgs/msg/string.hpp"
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
// 传参 方法二
rclcpp::NodeOptions nodeOptions;
nodeOptions.automatically_declare_parameters_from_overrides(true);
auto node_parameter=rclcpp::Node::make_shared("demo_pub", nodeOptions);
std::string rgb_topic;
node_parameter->get_parameter("rgb_topic", rgb_topic);
printf("===> %s \n", rgb_topic.c_str());
// 单线程执行器 灵活管理node节点,非堵塞
rclcpp::executors::SingleThreadedExecutor executor;
executor.add_node(node_parameter);
std::thread([&executor]()
{ executor.spin(); })
.detach();
rclcpp::shutdown();
return 0;
}
4. 同上
CMakeLists.txt和package.xml跟上一个demo完全一样,这里就不贴了。
运行结果跟config.yaml中的一样
觉得对您有帮助的,可以点个赞👍支持一下,谢谢各位!
因为淋过雨,所以想为别人撑把伞;因为踩过太多坑,所以想让喜欢机器人的同学们减少试错成本!