ROS2与Gazebo11入门教程-用ros2 launch启动Gazebo、世界文件和模型
说明:
- 有多种方法可以启动 Gazebo、打开仿真世界、在仿真环境中生成(插入)模型。本节教程将会介绍使用 ROS 2启动Gazebo的方法:使用 ros2 launch命令启动Gazebo以及打开不同的现有世界文件和在仿真世界中生成(插入)不同的现有模型
用ros2 launch打开Gazebo仿真世界
- 命令行工具ros2 launch是启动 ROS 2节点和打开 ROS 2中机器人的标准方法。
- 要启动Gazebo仿真世界,只需运行以下命令即可:
ros2 launch gazebo_ros gazebo.launch.py
- 这样Gazebo GUI应该就会显现出来,但在其场景窗口中没有任何东西(见下图)。
- 要验证是否设置了正确的 ROS 2连接,请用以下命令来查看当前可用的 ROS 2话题:
ros2 topic list -t
- 这样应该可以看见如下所示的话题列表:
/clock [rosgraph_msgs/msg/Clock]
/parameter_events [rcl_interfaces/msg/ParameterEvent]
/performance_metrics [gazebo_msgs/msg/PerformanceMetrics]
/rosout [rcl_interfaces/msg/Log]
- 还可以用以下命令来验证现有的Gazebo服务:
ros2 service list -t
- 这样应该会看见如下所示的服务列表:
/apply_joint_effort [gazebo_msgs/srv/ApplyJointEffort]
/apply_link_wrench [gazebo_msgs/srv/ApplyLinkWrench]
/clear_joint_efforts [gazebo_msgs/srv/JointRequest]
/clear_link_wrenches [gazebo_msgs/srv/LinkRequest]
/delete_entity [gazebo_msgs/srv/DeleteEntity]
/gazebo/describe_parameters [rcl_interfaces/srv/DescribeParameters]
/gazebo/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
/gazebo/get_parameters [rcl_interfaces/srv/GetParameters]
/gazebo/list_parameters [rcl_interfaces/srv/ListParameters]
/gazebo/set_parameters [rcl_interfaces/srv/SetParameters]
/gazebo/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
/get_model_list [gazebo_msgs/srv/GetModelList]
/pause_physics [std_srvs/srv/Empty]
/reset_simulation [std_srvs/srv/Empty]
/reset_world [std_srvs/srv/Empty]
/spawn_entity [gazebo_msgs/srv/SpawnEntity]
/unpause_physics [std_srvs/srv/Empty]
ros2 launch命令的参数
可以将以下参数添加到启动文件中以更改 Gazebo 的行为:
pause参数:若设置为true,则会以仿真暂停状态启动Gazebo;默认为false,这样会以仿真运行状态启动Gazebo;
use_sim_time参数:默认为true,这会告知 ROS 2节点请求时间来获取 Gazebo 发布的仿真时间,并将该仿真时间发布在 ROS 2话题 /clock 上;若设置为false,则不获取和发布仿真时间;
gui参数:默认为true,这样会启动Gazebo的用户界面窗口;若设置为false,则不会打开Gazebo的用户界面;
recording参数:用于设置是否启用Gazebo状态日志记录功能;
debug参数:若设置为true,则会以调试模式启动Gazebo服务器gzserver;默认为false;
verbose参数:若设置为true运行 gzserver 和 gzclient,则会向终端打印错误和警告消息(默认为 false);
server_required参数:若设置为true,当Gazebo 服务器gzserver退出时会终止启动脚本(默认为 false);
gui_required参数:若设置为true,当Gazebo客户端gzclient退出时会终止启动脚本(默认为false)。
ros2 launch命令示例
- 通常这些参数的默认值就是你所需要的,而下面这个设置了参数非默认值的命令只是作为一个示例:
ros2 launch gazebo_ros gazebo.launch.py pause:=true use_sim_time:=false gui:=true recording:=false debug:=true verbose:=true gui_required:=true
用ros2 launch启动其它演示仿真世界
- 除了以空白仿真世界启动Gazebo之外,软件包gazebo_ros中还包含一个生成双摆锤模型实体的演示仿真世界:
ros2 launch gazebo_ros spawn_entity_demo.launch.py
- 请注意,spawn_entity_demo.launch.py中启动了一个简单的关节机制。
- 启动文件spawn_entity_demo.launch.py中包含以下内容:
# Copyright 2019 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Demo for spawn_entity.
Launches Gazebo and spawns a model
"""
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import ThisLaunchFileDir
from launch_ros.actions import Node
def generate_launch_description():
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource([ThisLaunchFileDir(), '/gazebo.launch.py']),
)
# GAZEBO_MODEL_PATH has to be correctly set for Gazebo to be able to find the model
spawn_entity = Node(package='gazebo_ros', node_executable='spawn_entity.py',
arguments=['-entity', 'demo', '-database', 'double_pendulum_with_base'],
output='screen')
return LaunchDescription([
gazebo,
spawn_entity,
])
在这个启动文件中,从 gazebo.launch.py继承了大部分必要的功能。
需要增加的是spawn_entity节点,该节点是gazebo_ros软件包中的一个Python可执行节点,用于向场景中生成插入一个带底座的双摆锤模型。
现在再回过头来看下gazebo.launch.py启动文件的代码内容:
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.actions import IncludeLaunchDescription
from launch.conditions import IfCondition
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration
from launch.substitutions import ThisLaunchFileDir
def generate_launch_description():
return LaunchDescription([
DeclareLaunchArgument('gui', default_value='true',
description='Set to "false" to run headless.'),
DeclareLaunchArgument('server', default_value='true',
description='Set to "false" not to run gzserver.'),
IncludeLaunchDescription(
PythonLaunchDescriptionSource([ThisLaunchFileDir(), '/gzserver.launch.py']),
condition=IfCondition(LaunchConfiguration('server'))
),
IncludeLaunchDescription(
PythonLaunchDescriptionSource([ThisLaunchFileDir(), '/gzclient.launch.py']),
condition=IfCondition(LaunchConfiguration('gui'))
),
])
从这个启动文件的代码内容可以看出,在Gazebo启动描述中,申明了启动参数gui和server,并将这两个参数的默认值均设置为true,即默认同时启动Gazebo服务器和客户端;
同时,为了启动Gazebo服务器和客户端,需要把它们的启动描述源代码Python文件(即相同目录下的 '/gzserver.launch.py'和'/gzclient.launch.py')包含进来。
其中gzserver.launch.py和gzclient.launch.py 启动文件分别用于通过ros2 launch命令来启动Gazebo服务器和客户端,而且可以在启动时设置相关命令行参数。
具体可用的参数及其使用方法,可以通过gzserver –help和gzclient --help帮助命令来了解。
用launch文件生成不同的模型
- 现在继续进行spawn_entity_demo.launch.py文件的检查,现在看下用Node()生成模型实体的代码行:
spawn_entity = Node(package='gazebo_ros', node_executable='spawn_entity.py',
arguments=['-entity', 'demo', '-database', 'double_pendulum_with_base'],
output='screen')
这行代码会调用gazebo_ros软件包中的spawn_entity.py可执行节点程序生成一个实体模型。在本例中,向spawn_tntity.py节点传递了两个参数,即-entity参数(必选参数,用于指定要生成的实体名称),其值为“demo”,以及-database参数(用于指定Gazebo在线模型数据库或者GAZEBO_MODEL_PATH环境变量中各个目录下Gazebo模型的名称),其值为“double_pendulum_with_base”,即生成带底座的双摆锤模型。
实际上,如果不想创建自己的ROS 2软件包来启动Gazebo并生成插入模型,则可以直接利用上面这个示例启动文件spawn_entity_demo.launch.py,通过修改-database参数的值来指定生成插入不同的Gazebo模型。
例如,将上面这行代码稍微修改一下就可以启动Gazebo并生成插入bus模型(如下图所示):
spawn_entity = Node(package='gazebo_ros', node_executable='spawn_entity.py',
arguments=['-entity', 'demo', '-database', 'bus'],
output='screen')
或者将该行代码修改成下面这样来生成插入位于本地~/.gazebo/models目录下自定义的small_warehouse模型(见下图):
spawn_entity = Node(package='gazebo_ros', node_executable='spawn_entity.py',
arguments=['-entity', 'demo', '-database', 'small_warehouse'],
output='screen')
用ros2 launch文件打开不同的仿真世界文件
除了用ros2 launch命令和spawn_entity_demo.launch.py启动文件来启动Gazebo空白仿真世界并生成插入所需的模型外,也可以直接在世界文件中设置要在仿真世界中插入的模型、关节和插件等,这样可以直接用ros2 launch命令启动Gazebo并同时打开不同的仿真世界文件来插入某个或者某些模型。
例如,通过编写下面这样一个简单的Python启动文件,就可以用以下ros2 launch命令启动Gazebo并同时打开underwater.world仿真世界文件:
ros2 launch gazebo_world.launch.py
"""Demo for using ros2 launch command to start a simulation world file.
Launches Gazebo with a specified world file.
"""
import os
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import ThisLaunchFileDir
from launch_ros.actions import Node
from launch.actions import ExecuteProcess
def generate_launch_description():
world_file_name = 'underwater.world'
world = os.path.join('/usr/share/gazebo-11', 'worlds', world_file_name)
gazebo = ExecuteProcess(cmd=['gazebo', '--verbose', world, '-s', 'libgazebo_ros_init.so', '-s', 'libgazebo_ros_factory.so'], output='screen')
return LaunchDescription([
gazebo
])
- 顺利启动后,其效果应该如下图所示:
请注意以下两点:
(1)这里并没有创建自定义软件包,而是直接将这个Python启动文件保存在某个目录下,并从终端中进入到该目录中,然后再执行ros2 launch命令,这样才能找到该启动文件;
(2)若要打开Gazebo自带的其它仿真世界文件,则直接修改上面代码中的world_file_name参数的属性值即可,例如修改成'elevator.world'世界文件,则可以打开具有一部电梯和一个世界插件的仿真世界。
如果要打开其它目录中的世界文件,则需要用相应目录(路径)名替换上面启动文件中代码行world = os.path.join('/usr/share/gazebo-11', 'worlds', world_file_name)中的'/usr/share/gazebo-11'路径。假设要打开~/gazebo_tutorials/worlds目录中的Robonaut2.world文件,需将该行代码修改成world = os.path.join('/home/wangjg/gazebo_tutorials', 'worlds', world_file_name)和将world_file_name改成 'Robonaut2.world'(见下图)。
注意,这里的路径名必须采用绝对路径,而不能用相对路径'~/gazebo_tutorials',否则会提示找不到该是世界文件。
除了上面的--verbose和-s参数外,当然也可以用更多参数来控制Gazebo的启动,例如--pause、--lockstep等参数,这只需要向上面的代码行gazebo = ExecuteProcess(cmd=['gazebo', '--verbose', world, '-s', 'libgazebo_ros_init.so', '-s', 'libgazebo_ros_factory.so'], output='screen') 中cmd=[]中继续添加参数即可,这些参数之间要用逗号分开,而且如果添加的参数需要参数值(arg)的话,其它参数与参数值之间也要用逗号分隔开来,而且除了字符串变量表示的参数之外,这些参数和参数值都要加单引号。
当然,为了构建用户自己的机器人模型和仿真世界,并让机器人模型在仿真世界中具有自定义的行为和控制方式,就需要构建用户自己的软件包,并在软件包中包含worlds、models、launch等目录及相应的world文件、模型和启动文件,以及其它程序和插件,然后就可以使用ros2 launch命令来启动Gazebo并打开用户自定义仿真世界和生成(插入)用户自定义模型。这将是下一节教程的内容。
参考资料:
- (1) Gazebo Tutorial: Using roslaunch to start Gazebo, world files and URDF models
- (2) https://automaticaddison.com/how-to-simulate-a-robot-using-gazebo-and-ros-2/
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号