ROS2学习日志:CV开发之关联Gazebo/Webots/ROS2

1.关于模拟器

         (1)安装位置:分别安装在/usr/bin/gazebo和usr/local/bin/webots,其中gazebo由/usr/bin/gzclient(负责前端界面显示与交互)和/usr/bin/gzserver(负责后端数据管理与通信)组成。

         (2)启动说明:启动命令分别是gazebo [options] [worldfile]和webots [options] [worldfile],详细参数选项可通过gazebo -h或webots -h查看。当世界文件为空时,gazebo启动空模拟器,webots启动空模拟器或上次启动的世界文件。

2.关于控制器

         (1)如何设置:在模型文件或世界文件中指定控制器,gazebo在xml中添加<plugin>...</plugin>来指定和配置控制器,webots在wbt文件中由controller和controllerArgs来指定和配置控制器。

         (2)如何编码:参见官方样例。需要说明的是,gazebo的控制器被编译成的是动态库文件,webots的控制器被编译成的是可执行文件。

3.ROS控制器

         (1)关联ROS:将仿真器与外界的交互通过ROS的订阅发布机制来实现,从而摆脱复杂的API编程,扮演此中间角色的可形象的称之为ROS控制器或ROS驱动。

         (2)启动脚本:分别是gazebo.launch.py和robot_launch.py,其中gazebo.launch.py由gzclient.launch.py和gzserver.launch.py组成。

4.直接启动与脚本启动的关系

         (1)核心关系:脚本启动也是调用直接启动,只是将直接启动的参数形式重向为脚本的参数形式,使得启动操作更方便,然而本质上直接启动也能完成脚本启动的所有功能,只是稍显麻烦而已。

         (2)gazebo.launch.py对直接启动的重点扩展:启动时默认init:=true和factory:=true,这将加载位于/opt/ros/foxy/lib/中libgazebo_ros_init.so和libgazebo_ros_factory.so(这两个文件的作用是...),相当于设置了参数-s /opt/ros/foxy/lib/libgazebo_ros_init.so -s /opt/ros/foxy/lib/libgazebo_ros_factory.so的直接启动(注意这两个文件也可以放到模型文件中加载而无需手动加载)。

         (3)robot_launch.py对直接启动的重点扩展:启动时默认executable=webots_node,这将加载位于/opt/ros/foxy/lib/webots_ros2_core中webots_node(这是所有WebotsROS控制器的基类且它加载了所有内置传感器的驱动),相当于wbt文件中设置controller为/opt/ros/foxy/lib/webots_ros2_core/webots_node后的直接启动(注意webots要使用外部控制器必须将wbt文件中的controller设置为<extern>)。

         (4)gazebo.launch.py对比robot_launch.py:Gazebo需要加载单独加载libgazebo_ros_init.so和libgazebo_ros_factory.so及每个传感器的驱动,Webots只能加载一个驱动且只是webots_node或webots_node子类,但webots_node已完成了所有内置传感器驱动的加载。

         另外,脚本启动可能还包含附加启动其它程序,如机器人状态发布器,然而这些操作都是可以手动操作的。

         总结而言,脚本启动一次完成了直接启动和相关附加程序的启动,但这些启动都可以手动一步一步操作。

5.直接启动与脚本启动的样例

         Gazebo脚本启动不能指定控制器(只能在模型文件中指定),但直接启动可以,脚本启动可设置是否启动ROS基本功能。

         (1)无ROS控制器的Gazebo模型:/usr/share/gazebo-11/world包含很多模型,其中everything.world攘括了所有模型。

    加载环境:source /opt/ros/foxy/setup.bash  && source /usr/share/gazebo/setup.sh

    直接启动且模型无ROS控制器-->能使无任何ROS功能:gazebo --verbose /usr/share/gazebo-11/worlds/everything.world

    直接启动且模型无ROS控制器-->能使有基础ROS功能:gazebo --verbose -s /opt/ros/foxy/lib/libgazebo_ros_init.so -s /opt/ros/foxy/lib/libgazebo_ros_factory.so /usr/share/gazebo-11/worlds/everything.world

    脚本启动且模型无ROS控制器-->能使有基础ROS功能:ros2 launch gazebo_ros gazebo.launch.py verbose:=true world:=/usr/share/gazebo-11/worlds/everything.world

    脚本启动且模型无ROS控制器-->能使无基础ROS功能:ros2 launch gazebo_ros gazebo.launch.py verbose:=true world:=/usr/share/gazebo-11/worlds/everything.world init:=false factory:=false

         (2)有ROS控制器的Gazebo模型:/opt/ros/foxy/share/gazebo_plugins/worlds包含很多模型,下以gazebo_ros_video_demo.world模型作为测试。

    加载环境:source /opt/ros/foxy/setup.bash && source /usr/share/gazebo/setup.sh

    直接启动且模型有ROS控制器-->能使无基础但有DIYROS功能:gazebo --verbose /opt/ros/foxy/share/gazebo_plugins/worlds/gazebo_ros_video_demo.world

    直接启动且模型有ROS控制器-->能使有基础且有DIYROS功能:gazebo --verbose -s /opt/ros/foxy/lib/libgazebo_ros_init.so -s /opt/ros/foxy/lib/libgazebo_ros_factory.so /opt/ros/foxy/share/gazebo_plugins/worlds/gazebo_ros_video_demo.world

    脚本启动且模型有ROS控制器-->能使有基础且有DIYROS功能:ros2 launch gazebo_ros gazebo.launch.py verbose:=true /opt/ros/foxy/share/gazebo_plugins/worlds/gazebo_ros_video_demo.world

    脚本启动且模型有ROS控制器-->能使无基础且有DIYROS功能:ros2 launch gazebo_ros gazebo.launch.py verbose:=true /opt/ros/foxy/share/gazebo_plugins/worlds/gazebo_ros_video_demo.world init:=false factory:=false

         Webots直接启动不能指定DIY控制器(只能在模型文件中指定),但脚本启动可以,脚本启动必须将controller设置<extern>。

         (1)无ROS控制器的Webots模型:/usr/local/webots/projects包含很多模型且大多附带控制器,以下测试需要提前将测试模型的controller设为<extern>。

    加载环境:source /opt/ros/foxy/setup.bash

    直接启动且模型无ROS控制器-->能使无任何ROS功能:webots --mode=realtime /usr/local/webots/projects/robots/dji/mavic/worlds/mavic_2_pro.wbt

    直接启动且模型无ROS控制器-->能使有基础ROS功能:正在尝试

    脚本启动且模型无ROS控制器-->能使有基础ROS功能:ros2 launch webots_ros2_core robot_launch.py world:=/usr/local/webots/projects/robots/dji/mavic/worlds/mavic_2_pro.wbt

    脚本启动且模型无ROS控制器-->能使无基础ROS功能:无法做到,因为要么使用默认的webots_ros2_core->webots_node要么指定一个ROS控制器,否则无法启动。

         (2)有ROS控制器的Webots模型:/opt/ros/foxy/share包含几个典型的模型且都带ROS控制器,由于使用外部控制器(ROS控制器是外部控制器),所以这些模型的controller都已设为<extern>。

    加载环境:source /opt/ros/foxy/setup.bash

    直接启动且模型有ROS控制器-->能使无基础且无DIYROS功能:webots --mode=realtime /opt/ros/foxy/share/webots_ros2_epuck/worlds/epuck_world.wbt

    直接启动且模型有ROS控制器-->能使有基础且无DIYROS功能:正在尝试将controller设置为webots_node

    直接启动且模型有ROS控制器-->能使有基础且有DIYROS功能:正在尝试将controller设置为xxxxxx_robot_controller

    脚本启动且模型有ROS控制器-->能使有基础且有DIYROS功能:ros2 launch webots_ros2_core robot_launch.py world:=/opt/ros/foxy/share/webots_ros2_epuck/worlds/epuck_world.wbt package:=webots_ros2_epuck executable:=driver

   速控:ros2 topic pub /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 0.1, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}"

    脚本启动且模型有ROS控制器-->能使有基础且无DIYROS功能:ros2 launch webots_ros2_core robot_launch.py world:=/opt/ros/foxy/share/webots_ros2_epuck/worlds/epuck_world.wbt

    直接启动且模型有ROS控制器-->能使无基础且无DIYROS功能:无法做到,因为要么使用默认的webots_ros2_core->webots_node要么指定一个ROS控制器,否则无法启动。

6.Gazebo间接脚本与Webots直接脚本样例

         Webots脚本样例在WebotsROS2官网上有很多可供参考,其中最通用的是webots_ros2_core包中的robot_launch.py,其它样例都是其缩减版的扩展或直接调用它后的扩展,以下是robot_launch.py的精简版(调用之前先source /opt/ros/foxy/setup.bash):

         Gazebo脚本样例可参见turtlebot3_bringup包和nav2_bringup包中的启动脚本,其中最通用的是gazebo_ros包中的gzserver.launch.py和gzclient.launch.py及这两者的合并版gazebo.launch.py,通常是直接调用gazebo.launch.py后再扩展。

         需要说明是Python启动脚本的参数是可传递的且可覆盖的,即gazebo.launch.py参数包含gzserver.launch.py和gzclient.launch.py的参数,若内层脚本参数与外层脚本参数重名,则内层参数被覆盖,以下是调用gazebo.launch.py的启动脚本样例(调用之前先source /opt/ros/foxy/setup.bash && source /usr/share/gazebo/setup.sh):

import os, sys, shutil, argparse
from ament_index_python.packages import (get_package_prefix, get_packages_with_prefixes, get_package_share_directory)
import launch
from launch import (Action, LaunchDescription)#InheritFrom LaunchDescriptionEntity
from launch.actions import (TimerAction, ExecuteProcess, DeclareLaunchArgument, IncludeLaunchDescription)
from launch.conditions import IfCondition
from launch.substitutions import LaunchConfiguration
from launch.events import TimerEvent
from launch.event_handlers import OnProcessExit
from launch.launch_description_sources import PythonLaunchDescriptionSource
import launch_ros
from launch_ros.actions import Node
from launch_ros.descriptions import ComposableNode
def create_argument(args, varname, default, description = 'no description'):
    cfg = LaunchConfiguration(varname, default = default)
    args.append(DeclareLaunchArgument(varname, default_value = default, description=description))
    return cfg
def handler_for_shutdown_launch_when_action_exit(action):
    return launch.actions.RegisterEventHandler(
        event_handler=launch.event_handlers.OnProcessExit(target_action=action,
            on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())]))

def generate_launch_description():
    """
    This script for taking out some usual arguments from gzclient.launch.py and gzserver.launch.py but hiden by gazebo.launch.py

    """
    user_arguments = []

    #1.RobotSimulator
    world = create_argument(user_arguments, 'world',  get_package_share_directory('gazebo_plugins') + '/worlds/gazebo_ros_video_demo.world')
    gui = create_argument(user_arguments, 'gui', 'true')
    init = create_argument(user_arguments, 'init', 'true')
    factory = create_argument(user_arguments, 'factory', 'true')
    verbose = create_argument(user_arguments, 'verbose', 'true')
    robot_simulator = IncludeLaunchDescription(
        PythonLaunchDescriptionSource([get_package_share_directory('gazebo_ros'), '/launch/gazebo.launch.py']),
        launch_arguments =
        {
            'world': world,
            'gui': gui,
            'init': init,
            'factory': factory,
            'verbose': verbose,
            'client_required': 'true',
            'server_required': 'true',
        }.items())

    #2.SimulatorClock
    use_sim_time = create_argument(user_arguments, 'use_sim_time', 'true')
    clock_simulator = ExecuteProcess(cmd=['ros2', 'param', 'set', '/gazebo', 'use_sim_time', use_sim_time], output='screen')

    #3.EntitySpawner
    entity_name = create_argument(user_arguments, 'entity_name', 'ambulance', 'diretory name coming from /root/.gazebo/models and downloaded from https://github.com/osrf/gazebo_models or http://models.gazebosim.org/')
    entity_x = create_argument(user_arguments, 'entity_x', '-10')
    entity_y = create_argument(user_arguments, 'entity_y', '10')
    entity_z = create_argument(user_arguments, 'entity_z', '0')
    entity_spawner = Node(package='gazebo_ros',
                        executable='spawn_entity.py',
                        arguments=['-entity', entity_name, '-database', entity_name, '-x', entity_x, '-y', entity_y, '-z', entity_z],
                        output='screen')

    #4.LaunchAllEntities
    return LaunchDescription(user_arguments + [
        robot_simulator,
        clock_simulator,
        entity_spawner])
View Code

 

原文地址:https://www.cnblogs.com/dzyBK/p/14497589.html