launch存在的意义就是,能够不再手动一个一个去启动Node,而可以通过配置一个LaunchDescription。让程序自动把这个里面所有的Node都拉起来。
我按着教程自己做了一边,碰到几个问题,记录一下,以免再犯。
先看下我的*.launch.py
from launch import LaunchDescription # launch
from launch_ros.actions import Node
def generate_launch_description():
ld = [Node(
package = "aaaaa",
executable = "222"
),
Node(
package = "aaaaa",
executable = "333"
)]
return LaunchDescription(ld)
1、首先要注意的是函数名:
一定要叫generate_launch_description()。我一开始拼错了。。。执行colcon build是可以通过,但是一旦运行ros2 launch xxx就会报错。
2、再就是这个函数要返回一个LaunchDescription的实例。参数是一个列表,列表里的元素就是你希望拉起来的节点。我这里只是简单的拉起来两个节点,也没配置参数啥的。
3、注意 executable 参数,这个地方,写的是每个包里,console_scripts 的名字,而不是 py文件名或者节点名字。参看我aaaaa包的setup.py内的描述。我之前写成了talker/listener,就一直不对。
from setuptools import setup
package_name = 'aaaaa'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='udeer',
maintainer_email='zhuofei@udeer.ai',
description='TODO: Package description',
license='TODO: License declaration',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'111 = aaaaa.zzz:main',
'222 = aaaaa.talker:main',
'333 = aaaaa.listener:main',
'444addclient = aaaaa.adder_Client:main',
'555addserver = aaaaa.adder_Server:main',
'666para = aaaaa.paramlearn:main',
],
}
)
4、这个launch包的setup.py,需要在data_files后面加东西。加一个元组(),第一个元素是在install中生成的目录,第二个元素是在src中的.py文件,如下:
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
(os.path.join('share', package_name, 'launch'), glob(os.path.join(package_name, '*.launch.py'))),
],
如我这段代码,就是把src/bbbbb/bbbbb/talk.launch.py,生成到install/bbbbb/share/bbbbb/launch下。
5、然后在执行launch之前,要确保已经source了install下的setup.up或者local_setup.sh,前者对所有的terminal都有效,后者只对当前的terminal有效。