设置重置处理程序
目标: 使用重置处理程序扩展机器人模拟,以便在按下 Webots 的重置按钮时重新启动节点。
教程级别: 高级
时间: 10 分钟
背景
在本教程中,您将学习如何使用 Webots 在机器人模拟中实现重置处理程序。 Webots 重置按钮将世界恢复到初始状态并重新启动控制器。 它很方便,因为它可以快速重置模拟,但在 ROS 2 的上下文中,机器人控制器不会再次启动,从而导致模拟停止。 重置处理程序允许您在按下 Webots 中的重置按钮时重新启动特定节点或执行其他操作。 这对于需要重置模拟状态或重新启动特定组件而无需完全重新启动整个 ROS 系统的场景非常有用。
先决条件
在继续本教程之前,请确保您已完成以下内容:
了解初学者 教程 中涵盖的 ROS 2 节点和主题。
了解 Webots 和 ROS 2 及其接口包。
熟悉 设置机器人模拟(基础)。
简单情况的重置处理程序(仅限控制器)
在包的启动文件中,添加 respawn
参数。
def generate_launch_description():
robot_driver = WebotsController(
robot_name='my_robot',
parameters=[
{'robot_description': robot_description_path}
],
# Every time one resets the simulation the controller is automatically respawned
respawn=True
)
# Starts Webots
webots = WebotsLauncher(world=PathJoinSubstitution([package_dir, 'worlds', world]))
return LaunchDescription([
webots,
robot_driver
])
重置时,Webots 会终止所有驱动程序节点。
因此,要在重置后重新启动它们,您应该将驱动程序节点的 respawn
属性设置为 True
。
这将确保驱动程序节点在重置后启动并运行。
多个节点的重置处理程序(无需关闭)
如果您有一些其他节点必须与驱动程序节点一起启动(例如 ros2_control
节点),那么您可以使用 OnProcessExit
事件处理程序:
def get_ros2_control_spawners(*args):
# Declare here all nodes that must be restarted at simulation reset
ros_control_node = Node(
package='controller_manager',
executable='spawner',
arguments=['diffdrive_controller']
)
return [
ros_control_node
]
def generate_launch_description():
robot_driver = WebotsController(
robot_name='my_robot',
parameters=[
{'robot_description': robot_description_path}
],
# Every time one resets the simulation the controller is automatically respawned
respawn=True
)
# Starts Webots
webots = WebotsLauncher(world=PathJoinSubstitution([package_dir, 'worlds', world]))
# Declare the reset handler that respawns nodes when robot_driver exits
reset_handler = launch.actions.RegisterEventHandler(
event_handler=launch.event_handlers.OnProcessExit(
target_action=robot_driver,
on_exit=get_ros2_control_spawners,
)
)
return LaunchDescription([
webots,
robot_driver,
reset_handler
] + get_ros2_control_spawners())
无法在“ros2_control”节点上使用“respawn”属性,因为生成器在启动时退出,而不是在模拟重置时退出。 相反,我们应该在函数中声明一个节点列表(例如“get_ros2_control_spawners”)。 执行启动文件时,此列表中的节点与其他节点一起启动。 使用“reset_handler”,该函数也被声明为在“robot_driver”节点退出时启动的操作,这对应于在 Webots 界面中重置模拟的时刻。 “robot_driver”节点仍将“respawn”属性设置为“True”,以便它与“ros2_control”节点一起重新启动。
需要关闭节点的重置处理程序
使用当前的 ROS 2 启动 API,无法在启动文件中进行重置,因为在启动文件中需要在重新启动之前关闭节点(例如“Nav2”或“RViz”)。 原因是,目前,ROS 2 不允许从启动文件中关闭特定节点。 有一个解决方案,但它需要在按下重置按钮后手动重新启动节点。
Webots 需要在特定的启动文件中启动,而无需其他节点。
def generate_launch_description():
# Starts Webots
webots = WebotsLauncher(world=PathJoinSubstitution([package_dir, 'worlds', world]))
return LaunchDescription([
webots
])
必须从另一个进程启动第二个启动文件。 此启动文件包含所有其他节点,包括机器人控制器/插件、Navigation2 节点、RViz、状态发布者等。
def generate_launch_description():
robot_driver = WebotsController(
robot_name='my_robot',
parameters=[
{'robot_description': robot_description_path}
]
)
ros_control_node = Node(
package='controller_manager',
executable='spawner',
arguments=['diffdrive_controller']
)
nav2_node = IncludeLaunchDescription(
PythonLaunchDescriptionSource(os.path.join(
get_package_share_directory('nav2_bringup'), 'launch', 'bringup_launch.py')),
launch_arguments=[
('map', nav2_map),
('params_file', nav2_params),
],
)
rviz = Node(
package='rviz2',
executable='rviz2',
output='screen'
)
# Declare the handler that shuts all nodes down when robot_driver exits
shutdown_handler = launch.actions.RegisterEventHandler(
event_handler=launch.event_handlers.OnProcessExit(
target_action=robot_driver,
on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],
)
)
return LaunchDescription([
robot_driver,
ros_control_node,
nav2_node,
rviz,
shutdown_handler
])
第二个启动文件包含一个处理程序,当驱动程序节点退出时(模拟重置时就是这种情况),该处理程序会触发关闭事件。 按下重置按钮后,必须从命令行手动重新启动此第二个启动文件。
摘要
在本教程中,您学习了如何使用 Webots 在机器人模拟中实现重置处理程序。 重置处理程序允许您在按下 Webots 中的重置按钮时重新启动特定节点或执行其他操作。 您根据模拟的复杂性和节点的要求探索了不同的方法。