ros2 design - 01 - laun file example
ros2 design - 02 - from a launch file
基本格式
返回LaunchDescription, 格式1
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
ld = LaunchDescription()
talker_node = Node(
package="demo_nodes_cpp",
executable="talker",
)
ld.add_action(talker_node)
return ld
返回LaunchDescription, 格式2
并列放在数组内
def generate_launch_description():
return LaunchDescription([
launch.actions.DeclareLaunchArgument(
'node_prefix',
default_value=[launch.substitutions.EnvironmentVariable('USER'), '_'],
description='Prefix for node names'),
launch_ros.actions.Node(
package='demo_nodes_cpp', executable='talker', output='screen',
name=[launch.substitutions.LaunchConfiguration('node_prefix'), 'talker']),
launch_ros.actions.Node(...),
])
topic/service remapping
talker_node = Node(
package="demo_nodes_cpp",
executable="talker",
)
listener_node = Node(
package="demo_nodes_py",
executable="listener",
name="new_name",
parameters=[
{"background_b": 200},
{"background_g": 200},
{"background_r": 200}
],
remappings=[
("chatter", "my_chatter")
]
)
yaml types
- Boolean value
- Integer number
- Float number
- String
- Array of all the 4 previous types
- Array of bytes
load yaml from command line
把路径写全, 或者当前terminal 路径的相对路径
ros2 run ros2_tutorials test_yaml_params --ros-args --params-file ~/ros2_ws/src/ros2_tutorials/config/params.yaml
load yaml from a launch file
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
ld = LaunchDescription()
config = os.path.join(
get_package_share_directory('ros2_tutorials'),
'config',
'params.yaml'
)
node=Node(
package = 'ros2_tutorials',
name = 'your_amazing_node',
executable = 'test_yaml_params',
parameters = [config]
)
ld.add_action(node)
return ld
include child launch file
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.actions import DeclareLaunchArgument
def generate_launch_description():
package_prefix = get_package_share_directory('child_package')
argument_for_child = "lala"
return LaunchDescription([
# Declare the launc parameter
DeclareLaunchArgument(
'argument_for_child',
default_value = argument_for_child,
description = 'Argument for child launch file'),
# include the child launch file
IncludeLaunchDescription(
PythonLaunchDescriptionSource([package_prefix, '/launch/child.launch.py'])
launch_arguments = {'argument_for_child': argument_for_child}.items()
), # 参数非必须
])
launch.substitution
ros2 wiki
使用substitution需要外部替换参数的值,否则会引起错误,或者使用condition保护;
使用substitution功能,需要与DeclareLaunchArgument配合使用
LaunchDescription([
launch.actions.DeclareLaunchArgument(
"my_param",
default_value=[""], # default_value=[], has the same problem
description="optional parameter"
),
launch_ros.actions.Node(
package="my_package",
node_executable="my_node",
arguments=[launch.substitutions.LaunchConfiguration("my_param", condition=launch.conditions.IfCondition(launch.substitutions.LaunchConfiguration("my_param"))]
),
])
RewrittenYaml
重新写入Yaml?
这个python 对象来自nav2_common
继承字launch.Substitution
功能是: Create our own temporary YAML files that include substitutions, 根据参数文件, 以及替换更新的部分参数,生成新的yaml 文件对象;
## 构造函数
def __init__(self,
source_file: launch.SomeSubstitutionsType,
param_rewrites: Dict,
root_key: Optional[launch.SomeSubstitutionsType] = None,
key_rewrites: Optional[Dict] = None,
convert_types = False) -> None:
super().__init__()
"""
Construct the substitution
:param: source_file the original YAML file to modify
:param: param_rewrites mappings to replace
:param: root_key if provided, the contents are placed under this key
:param: key_rewrites keys of mappings to replace
:param: convert_types whether to attempt converting the string to a number or boolean
"""
from launch.utilities import normalize_to_list_of_substitutions # import here to avoid loop
self.__source_file = normalize_to_list_of_substitutions(source_file)
self.__param_rewrites = {}
self.__key_rewrites = {}
self.__convert_types = convert_types
self.__root_key = None
for key in param_rewrites:
self.__param_rewrites[key] = normalize_to_list_of_substitutions(param_rewrites[key])
if key_rewrites is not None:
for key in key_rewrites:
self.__key_rewrites[key] = normalize_to_list_of_substitutions(key_rewrites[key])
if root_key is not None:
self.__root_key = normalize_to_list_of_substitutions(root_key)
source_file: string 类型, 表明yaml的全部路径
param_rewrites: 字典类型, 重新写入参数的键值对, key 为参数名, value 为LaunchConfiguration 变量对象,或者直接具体的值
convert_types: bool 类型,是否支持string 转换到bool ,int, 默认为True
key_rewrites: 字典类型,要替换的关键字 映射, 如果key 名字一样,则可为空, 如果不一样,就得搞关键字的映射了
root_key: Top-level namespace, 一般是名称空间的用法?
RewrittenYaml() 声明的对象很重要; 最后在Node对象中, 赋值给parameters 关键字
dump yaml file from existing params
ros2 param dump /your_amazing_node --print
yaml file example
第一行为node_name:
第二行为_ _ ros_parameters: (推荐缩进 2 或 4 空格)
注意,如果node_name不一致,则加载不会生效; 不会报错
your_amazing_node:
ros__parameters:
bool_value: True
int_number: 5
float_number: 3.14
str_text: "Hello Universe"
bool_array: [True, False, True]
int_array: [10, 11, 12, 13]
float_array: [7.5, 400.4]
str_array: ['Nice', 'more', 'params']
bytes_array: [0x01, 0xF1, 0xA2]
nested_param:
another_int: 7
也可以, 第一行为namespace, 后面行才是node_name
ns1:
your_amazing_node:
ros__parameters:
bool_value: True
...
launch 文件应该也填写namespace 关键字
node=Node(
package = 'ros2_tutorials',
namespace='ns1',
name = 'your_amazing_node',
executable = 'test_yaml_params',
parameters = [config]
)
ros2 代码实例化rclcpp::Node, 或者 rclcpp::LifeCycleNode 的字符串即为node_name, 与yaml 需要一致
其他语法
LaunchConfiguration is local to the launch file and scoped.
DeclareLaunchArgument allows you to expose the argument outside of your launch file. Allowing them to be listed, set, or marked as required when a user launches it from the command line (using ros2 launch) or when including it from another launch file (using IncludeLaunchDescription).
A LaunchConfiguration cannot be required to be set when launching or including and it is not possible to set it when launching from the command line. You can set a LaunchConfiguration before including another launch file, but an argument is better if you want it to be reused.
在launch 文件中, 一般用法是:
先在generate_launch_description() 函数中声明 LaunchConfiguration 变量,
再在LaunchDescription() 函数中,利用DeclareLaunchArgument() 再次声明上一步的变量,同时指明默认值和描述字符串;