From 8f530b550f08401cf3196bb6a17c6b759dda8796 Mon Sep 17 00:00:00 2001 From: Roni Kreinin Date: Mon, 13 Mar 2023 16:38:50 -0400 Subject: [PATCH 01/14] Added namespace support Updated GUI to have namespace input Update OAKD frames --- README.md | 2 +- .../config/turtlebot4_node.yaml | 123 ++++----- .../gui/lite/gui.config | 1 + .../gui/standard/gui.config | 1 + .../launch/ignition.launch.py | 242 ++---------------- .../launch/ros_ign_bridge.launch.py | 190 +++++--------- .../launch/turtlebot4_ignition.launch.py | 79 ++++++ .../launch/turtlebot4_nodes.launch.py | 3 +- .../launch/turtlebot4_spawn.launch.py | 214 ++++++++++++++++ .../Turtlebot4Hmi/Turtlebot4Hmi.cc | 72 +++++- .../Turtlebot4Hmi/Turtlebot4Hmi.hh | 47 +++- .../Turtlebot4Hmi/Turtlebot4Hmi.qml | 75 ++++-- turtlebot4_ignition_toolbox/src/hmi_node.cpp | 10 +- 13 files changed, 610 insertions(+), 449 deletions(-) create mode 100644 turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py create mode 100644 turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py diff --git a/README.md b/README.md index 2cae399..d972c08 100644 --- a/README.md +++ b/README.md @@ -10,5 +10,5 @@ sudo apt-get update && sudo apt-get install wget sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" > /etc/apt/sources.list.d/gazebo-stable.list' wget http://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add - sudo apt-get update -sudo apt-get install ignition-edifice ros-galactic-turtlebot4-simulator ros-galactic-irobot-create-nodes +sudo apt-get install ignition-fortress ros-humble-turtlebot4-simulator ``` diff --git a/turtlebot4_ignition_bringup/config/turtlebot4_node.yaml b/turtlebot4_ignition_bringup/config/turtlebot4_node.yaml index 6fadb80..348f8ea 100644 --- a/turtlebot4_ignition_bringup/config/turtlebot4_node.yaml +++ b/turtlebot4_ignition_bringup/config/turtlebot4_node.yaml @@ -1,62 +1,63 @@ -turtlebot4_node: - ros__parameters: - wifi: - interface: "wlan0" - - # Supported Functions: - # Dock - # Undock - # Wall Follow Left - # Wall Follow Right - # Power - # EStop - - # Menu Functions: - # Scroll Up - # Scroll Down - # Back - # Select - # Help - +/**: + turtlebot4_node: + ros__parameters: + wifi: + interface: "wlan0" + + # Supported Functions: + # Dock + # Undock + # Wall Follow Left + # Wall Follow Right + # Power + # EStop + + # Menu Functions: + # Scroll Up + # Scroll Down + # Back + # Select + # Help + + # Buttons: + # create3_1 + # create3_power + # create3_2 + # hmi_1 + # hmi_2 + # hmi_3 + # hmi_4 + + # Format: + # button: ["SHORT_PRESS_FUNC", "LONG_PRESS_FUNC", "LONG_PRESS_DURATION_MS"] + + buttons: + create3_1: ["Dock", "Wall Follow Left", "2000"] + create3_power: ["EStop", "Power", "3000"] + create3_2: ["Undock", "Wall Follow Right", "2000"] + + hmi_1: ["Select"] + hmi_2: ["Back"] + hmi_3: ["Scroll Up"] + hmi_4: ["Scroll Down"] + + # Menu entry must match a function + menu: + entries: ["Dock", "Undock", "EStop", "Wall Follow Left", "Wall Follow Right", "Power", "Help"] + + # Controller button functions # Buttons: - # create3_1 - # create3_power - # create3_2 - # hmi_1 - # hmi_2 - # hmi_3 - # hmi_4 - - # Format: - # button: ["SHORT_PRESS_FUNC", "LONG_PRESS_FUNC", "LONG_PRESS_DURATION_MS"] - - buttons: - create3_1: ["Dock", "Wall Follow Left", "2000"] - create3_power: ["EStop", "Power", "3000"] - create3_2: ["Undock", "Wall Follow Right", "2000"] - - hmi_1: ["Select"] - hmi_2: ["Back"] - hmi_3: ["Scroll Up"] - hmi_4: ["Scroll Down"] - - # Menu entry must match a function - menu: - entries: ["Dock", "Undock", "EStop", "Wall Follow Left", "Wall Follow Right", "Power", "Help"] - - # Controller button functions - # Buttons: - # a b x y - # up down left right - # l1 l2 l3 r1 r2 r3 - # share options home - - controller: - b: ["EStop"] - a: ["Select"] - x: ["Back"] - up: ["Scroll Up"] - down: ["Scroll Down"] - l2: ["Wall Follow Left"] - r2: ["Wall Follow Right"] - home: ["Dock", "Undock", "3000"] + # a b x y + # up down left right + # l1 l2 l3 r1 r2 r3 + # share options home + + controller: + b: ["EStop"] + a: ["Select"] + x: ["Back"] + up: ["Scroll Up"] + down: ["Scroll Down"] + l2: ["Wall Follow Left"] + r2: ["Wall Follow Right"] + home: ["Dock", "Undock", "3000"] diff --git a/turtlebot4_ignition_bringup/gui/lite/gui.config b/turtlebot4_ignition_bringup/gui/lite/gui.config index 615cecf..3f512c9 100644 --- a/turtlebot4_ignition_bringup/gui/lite/gui.config +++ b/turtlebot4_ignition_bringup/gui/lite/gui.config @@ -103,6 +103,7 @@ + /cmd_vel true docked diff --git a/turtlebot4_ignition_bringup/gui/standard/gui.config b/turtlebot4_ignition_bringup/gui/standard/gui.config index d618952..d3c30d8 100644 --- a/turtlebot4_ignition_bringup/gui/standard/gui.config +++ b/turtlebot4_ignition_bringup/gui/standard/gui.config @@ -103,6 +103,7 @@ + /cmd_vel true docked diff --git a/turtlebot4_ignition_bringup/launch/ignition.launch.py b/turtlebot4_ignition_bringup/launch/ignition.launch.py index 3e645aa..02bd6b5 100644 --- a/turtlebot4_ignition_bringup/launch/ignition.launch.py +++ b/turtlebot4_ignition_bringup/launch/ignition.launch.py @@ -1,4 +1,4 @@ -# Copyright 2021 Clearpath Robotics, Inc. +# Copyright 2023 Clearpath Robotics, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,60 +15,25 @@ # @author Roni Kreinin (rkreinin@clearpathrobotics.com) import os + from pathlib import Path from ament_index_python.packages import get_package_share_directory -from launch import LaunchContext, LaunchDescription, SomeSubstitutionsType, Substitution +from launch import LaunchDescription from launch.actions import DeclareLaunchArgument from launch.actions import IncludeLaunchDescription, SetEnvironmentVariable -from launch.conditions import IfCondition, LaunchConfigurationEquals from launch.launch_description_sources import PythonLaunchDescriptionSource from launch.substitutions import LaunchConfiguration, PathJoinSubstitution - from launch_ros.actions import Node -class OffsetParser(Substitution): - def __init__( - self, - number: SomeSubstitutionsType, - offset: float, - ) -> None: - self.__number = number - self.__offset = offset - - def perform( - self, - context: LaunchContext = None, - ) -> str: - number = float(self.__number.perform(context)) - return f'{number + self.__offset}' - - ARGUMENTS = [ - DeclareLaunchArgument('rviz', default_value='false', - choices=['true', 'false'], - description='Start rviz.'), - DeclareLaunchArgument('sync', default_value='true', - choices=['true', 'false'], - description='Whether to run a SLAM'), - DeclareLaunchArgument('localization', default_value='off', - choices=['off', 'localization', 'slam'], - description='Whether to run localization'), - DeclareLaunchArgument('nav2', default_value='false', - choices=['true', 'false'], - description='Run nav2'), DeclareLaunchArgument('use_sim_time', default_value='true', choices=['true', 'false'], description='use_sim_time'), DeclareLaunchArgument('world', default_value='depot', description='Ignition World'), - DeclareLaunchArgument('model', default_value='standard', - choices=['standard', 'lite'], - description='Turtlebot4 Model'), - DeclareLaunchArgument('robot_name', default_value='turtlebot4', - description='Robot name') ] @@ -81,20 +46,12 @@ def generate_launch_description(): 'turtlebot4_ignition_gui_plugins') pkg_turtlebot4_description = get_package_share_directory( 'turtlebot4_description') - pkg_turtlebot4_navigation = get_package_share_directory( - 'turtlebot4_navigation') - pkg_turtlebot4_viz = get_package_share_directory( - 'turtlebot4_viz') - - pkg_irobot_create_common_bringup = get_package_share_directory( - 'irobot_create_common_bringup') pkg_irobot_create_description = get_package_share_directory( 'irobot_create_description') pkg_irobot_create_ignition_bringup = get_package_share_directory( 'irobot_create_ignition_bringup') pkg_irobot_create_ignition_plugins = get_package_share_directory( 'irobot_create_ignition_plugins') - pkg_ros_ign_gazebo = get_package_share_directory( 'ros_ign_gazebo') @@ -116,192 +73,35 @@ def generate_launch_description(): # Paths ign_gazebo_launch = PathJoinSubstitution( [pkg_ros_ign_gazebo, 'launch', 'ign_gazebo.launch.py']) - turtlebot4_ros_ign_bridge_launch = PathJoinSubstitution( - [pkg_turtlebot4_ignition_bringup, 'launch', 'ros_ign_bridge.launch.py']) - rviz_launch = PathJoinSubstitution( - [pkg_turtlebot4_viz, 'launch', 'view_robot.launch.py']) - nav2_launch = PathJoinSubstitution( - [pkg_turtlebot4_navigation, 'launch', 'nav2.launch.py']) - slam_launch = PathJoinSubstitution( - [pkg_turtlebot4_navigation, 'launch', 'slam.launch.py']) - localization_launch = PathJoinSubstitution( - [pkg_turtlebot4_navigation, 'launch', 'localization.launch.py']) - node_launch = PathJoinSubstitution( - [pkg_turtlebot4_ignition_bringup, 'launch', 'turtlebot4_nodes.launch.py']) - create3_nodes_launch = PathJoinSubstitution( - [pkg_irobot_create_common_bringup, 'launch', 'create3_nodes.launch.py']) - create3_ignition_nodes_launch = PathJoinSubstitution( - [pkg_irobot_create_ignition_bringup, 'launch', 'create3_ignition_nodes.launch.py']) - robot_description_launch = PathJoinSubstitution( - [pkg_turtlebot4_description, 'launch', 'robot_description.launch.py']) - dock_description_launch = PathJoinSubstitution( - [pkg_irobot_create_common_bringup, 'launch', 'dock_description.launch.py']) - - # Parameters - param_file_cmd = DeclareLaunchArgument( - 'param_file', - default_value=PathJoinSubstitution( - [pkg_turtlebot4_ignition_bringup, 'config', 'turtlebot4_node.yaml']), - description='Turtlebot4 Robot param file') - - declare_map_yaml_cmd = DeclareLaunchArgument( - 'map', - default_value=PathJoinSubstitution( - [pkg_turtlebot4_navigation, 'maps', 'depot.yaml']), - description='Full path to map yaml file to load') - - # Launch configurations - x, y, z = LaunchConfiguration('x'), LaunchConfiguration('y'), LaunchConfiguration('z') - yaw = LaunchConfiguration('yaw') - turtlebot4_node_yaml_file = LaunchConfiguration('param_file') # Ignition gazebo ignition_gazebo = IncludeLaunchDescription( PythonLaunchDescriptionSource([ign_gazebo_launch]), launch_arguments=[ - ('ign_args', [ - LaunchConfiguration('world'), '.sdf', - ' -v 4', - ' --gui-config ', PathJoinSubstitution( - [pkg_turtlebot4_ignition_bringup, - 'gui', - LaunchConfiguration('model'), - 'gui.config'])]) + ('ign_args', [LaunchConfiguration('world'), + '.sdf', + ' -v 4', + ' --gui-config ', + PathJoinSubstitution( + [pkg_turtlebot4_ignition_bringup, + 'gui', + LaunchConfiguration('model'), + 'gui.config'])]) ] ) - # Robot description - robot_description = IncludeLaunchDescription( - PythonLaunchDescriptionSource([robot_description_launch]), - launch_arguments=[('model', LaunchConfiguration('model')), - ('use_sim_time', LaunchConfiguration('use_sim_time'))] - ) - - # Dock description - x_dock = OffsetParser(x, 0.157) - yaw_dock = OffsetParser(yaw, 3.1416) - dock_description = IncludeLaunchDescription( - PythonLaunchDescriptionSource([dock_description_launch]), - launch_arguments={'gazebo': 'ignition'}.items() - ) - - # Spawn Turtlebot4 - spawn_robot = Node( - package='ros_ign_gazebo', - executable='create', - arguments=[ - '-name', LaunchConfiguration('robot_name'), - '-x', x, - '-y', y, - '-z', z, - '-Y', yaw, - '-topic', 'robot_description'], - output='screen') - - # Spawn dock - spawn_dock = Node( - package='ros_ign_gazebo', - executable='create', - arguments=[ - '-name', 'standard_dock', - '-x', x_dock, - '-y', y, - '-z', z, - '-Y', yaw_dock, - '-topic', 'standard_dock_description'], - output='screen') - - # ROS Ign bridge - turtlebot4_ros_ign_bridge = IncludeLaunchDescription( - PythonLaunchDescriptionSource([turtlebot4_ros_ign_bridge_launch]), - launch_arguments=[('model', LaunchConfiguration('model'))] - ) - - # Rviz2 - rviz2 = IncludeLaunchDescription( - PythonLaunchDescriptionSource([rviz_launch]), - condition=IfCondition(LaunchConfiguration('rviz')), - ) - - # Navigation - nav2 = IncludeLaunchDescription( - PythonLaunchDescriptionSource([nav2_launch]), - condition=IfCondition(LaunchConfiguration('nav2')) - ) - - slam = IncludeLaunchDescription( - PythonLaunchDescriptionSource([slam_launch]), - launch_arguments=[('sync', LaunchConfiguration('sync'))], - condition=LaunchConfigurationEquals('localization', 'slam') - ) - - localization = IncludeLaunchDescription( - PythonLaunchDescriptionSource([localization_launch]), - launch_arguments=[('map', LaunchConfiguration('map'))], - condition=LaunchConfigurationEquals('localization', 'localization') - ) - - # TurtleBot 4 nodes - - turtlebot4_node = IncludeLaunchDescription( - PythonLaunchDescriptionSource([node_launch]), - launch_arguments=[('model', LaunchConfiguration('model')), - ('param_file', turtlebot4_node_yaml_file)] - ) - - # Create3 nodes - create3_nodes = IncludeLaunchDescription( - PythonLaunchDescriptionSource([create3_nodes_launch]) - ) - - create3_ignition_nodes = IncludeLaunchDescription( - PythonLaunchDescriptionSource([create3_ignition_nodes_launch]), - launch_arguments=[('robot_name', LaunchConfiguration('robot_name'))] - ) - - # RPLIDAR static transforms - rplidar_stf = Node( - name='rplidar_stf', - package='tf2_ros', - executable='static_transform_publisher', - output='screen', - arguments=[ - '0', '0', '0', '0', '0.0', '0.0', - 'rplidar_link', [LaunchConfiguration('robot_name'), '/rplidar_link/rplidar']] - ) - - # OAKD static transforms - oakd_stf = Node( - name='camera_stf', - package='tf2_ros', - executable='static_transform_publisher', - output='screen', - arguments=[ - '0', '0', '0', '0', '0', '0', - 'oakd_rgb_camera_optical_frame', - [LaunchConfiguration('robot_name'), '/oakd_rgb_camera_frame/rgbd_camera'] - ] - ) + # Clock bridge + clock_bridge = Node(package='ros_gz_bridge', executable='parameter_bridge', + name='clock_bridge', + output='screen', + arguments=[ + '/clock' + '@rosgraph_msgs/msg/Clock' + '[ignition.msgs.Clock' + ]) - # Define LaunchDescription variable + # Create launch description and add actions ld = LaunchDescription(ARGUMENTS) ld.add_action(ign_resource_path) ld.add_action(ign_gui_plugin_path) - ld.add_action(param_file_cmd) - ld.add_action(declare_map_yaml_cmd) ld.add_action(ignition_gazebo) - ld.add_action(turtlebot4_ros_ign_bridge) - ld.add_action(rviz2) - ld.add_action(robot_description) - ld.add_action(dock_description) - ld.add_action(spawn_robot) - ld.add_action(spawn_dock) - ld.add_action(create3_nodes) - ld.add_action(create3_ignition_nodes) - ld.add_action(turtlebot4_node) - ld.add_action(nav2) - ld.add_action(slam) - ld.add_action(localization) - ld.add_action(rplidar_stf) - ld.add_action(oakd_stf) + ld.add_action(clock_bridge) return ld diff --git a/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py b/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py index c988e41..d043957 100644 --- a/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py +++ b/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py @@ -1,4 +1,4 @@ -# Copyright 2021 Clearpath Robotics, Inc. +# Copyright 2023 Clearpath Robotics, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -31,6 +31,8 @@ description='Use sim time'), DeclareLaunchArgument('robot_name', default_value='turtlebot4', description='Robot name'), + DeclareLaunchArgument('namespace', default_value=LaunchConfiguration('robot_name'), + description='Robot namespace'), DeclareLaunchArgument('world', default_value='depot', description='World name'), DeclareLaunchArgument('model', default_value='standard', @@ -50,210 +52,159 @@ def generate_launch_description(): 'user2' ] - namespace = LaunchConfiguration('robot_name') + robot_name = LaunchConfiguration('robot_name') + namespace = LaunchConfiguration('namespace') + world = LaunchConfiguration('world') use_sim_time = LaunchConfiguration('use_sim_time') pkg_irobot_create_ignition_bringup = get_package_share_directory( 'irobot_create_ignition_bringup') - create3_ros_ign_bridge_launch = PathJoinSubstitution( + create3_ros_gz_bridge_launch = PathJoinSubstitution( [pkg_irobot_create_ignition_bringup, 'launch', 'create3_ros_ignition_bridge.launch.py']) create3_bridge = IncludeLaunchDescription( - PythonLaunchDescriptionSource([create3_ros_ign_bridge_launch]), + PythonLaunchDescriptionSource([create3_ros_gz_bridge_launch]), launch_arguments=[ - ('robot_name', LaunchConfiguration('robot_name')), - ('world', LaunchConfiguration('world')) + ('robot_name', robot_name), + ('namespace', namespace), + ('world', world) ] ) # lidar bridge lidar_bridge = Node( - package='ros_ign_bridge', + package='ros_gz_bridge', executable='parameter_bridge', - namespace=namespace, name='lidar_bridge', output='screen', parameters=[{ 'use_sim_time': use_sim_time }], arguments=[ - ['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), + ['/world/', world, + '/model/', robot_name, '/link/rplidar_link/sensor/rplidar/scan' + '@sensor_msgs/msg/LaserScan[ignition.msgs.LaserScan'] ], remappings=[ - (['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), + (['/world/', world, + '/model/', robot_name, '/link/rplidar_link/sensor/rplidar/scan'], - '/scan') + 'scan') ]) # Display message bridge hmi_display_msg_bridge = Node( - package='ros_ign_bridge', + package='ros_gz_bridge', executable='parameter_bridge', - namespace=namespace, name='hmi_display_msg_bridge', output='screen', parameters=[{'use_sim_time': use_sim_time}], arguments=[ - ['/model/', LaunchConfiguration('robot_name'), '/hmi/display/raw' + + [namespace, '/hmi/display/raw' + '@std_msgs/msg/String' + ']ignition.msgs.StringMsg'], - ['/model/', LaunchConfiguration('robot_name'), '/hmi/display/selected' + + [namespace, '/hmi/display/selected' + '@std_msgs/msg/Int32' + ']ignition.msgs.Int32'] ], remappings=[ - (['/model/', LaunchConfiguration('robot_name'), '/hmi/display/raw'], - '/hmi/display/_raw'), - (['/model/', LaunchConfiguration('robot_name'), '/hmi/display/selected'], - '/hmi/display/_selected') + ([namespace, '/hmi/display/raw'], + 'hmi/display/_raw'), + ([namespace, '/hmi/display/selected'], + 'hmi/display/_selected') ], condition=LaunchConfigurationEquals('model', 'standard')) # Buttons message bridge hmi_buttons_msg_bridge = Node( - package='ros_ign_bridge', + package='ros_gz_bridge', executable='parameter_bridge', - namespace=namespace, name='hmi_buttons_msg_bridge', output='screen', parameters=[{'use_sim_time': use_sim_time}], arguments=[ - ['/model/', LaunchConfiguration('robot_name'), '/hmi/buttons' + + [namespace, '/hmi/buttons' + '@std_msgs/msg/Int32' + '[ignition.msgs.Int32'] ], remappings=[ - (['/model/', LaunchConfiguration('robot_name'), '/hmi/buttons'], - '/hmi/buttons/_set') + ([namespace, '/hmi/buttons'], + 'hmi/buttons/_set') ], condition=LaunchConfigurationEquals('model', 'standard')) # Buttons message bridge hmi_led_msg_bridge = Node( - package='ros_ign_bridge', + package='ros_gz_bridge', executable='parameter_bridge', - namespace=namespace, name='hmi_led_msg_bridge', output='screen', parameters=[{'use_sim_time': use_sim_time}], arguments=[ - ['/model/', LaunchConfiguration('robot_name'), '/hmi/led/' + led + + [namespace, '/hmi/led/' + led + '@std_msgs/msg/Int32' + ']ignition.msgs.Int32'] for led in leds ], remappings=[ - (['/model/', LaunchConfiguration('robot_name'), '/hmi/led/' + led], - '/hmi/led/_' + led) for led in leds + ([namespace, '/hmi/led/' + led], + 'hmi/led/_' + led) for led in leds ], condition=LaunchConfigurationEquals('model', 'standard')) # Camera sensor bridge - oakd_pro_camera_bridge = Node( - package='ros_ign_bridge', + oakd_camera_bridge = Node( + package='ros_gz_bridge', executable='parameter_bridge', - namespace=namespace, name='camera_bridge', output='screen', parameters=[{'use_sim_time': use_sim_time}], arguments=[ - ['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_pro_rgb_camera_frame/sensor/rgbd_camera/image' + - '@sensor_msgs/msg/Image' + - '[ignition.msgs.Image'], - ['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_pro_rgb_camera_frame/sensor/rgbd_camera/depth_image' + - '@sensor_msgs/msg/Image' + - '[ignition.msgs.Image'], - ['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_pro_rgb_camera_frame/sensor/rgbd_camera/points' + - '@sensor_msgs/msg/PointCloud2' + - '[ignition.msgs.PointCloudPacked'], - ['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_pro_rgb_camera_frame/sensor/rgbd_camera/camera_info' + - '@sensor_msgs/msg/CameraInfo' + - '[ignition.msgs.CameraInfo'], - ], - remappings=[ - (['/world/', LaunchConfiguration('world'), - '/model/', - LaunchConfiguration('robot_name'), - '/link/oakd_pro_rgb_camera_frame/sensor/rgbd_camera/image'], - '/color/image'), - (['/world/', LaunchConfiguration('world'), - '/model/', - LaunchConfiguration('robot_name'), - '/link/oakd_pro_rgb_camera_frame/sensor/rgbd_camera/depth_image'], - '/stereo/depth'), - (['/world/', LaunchConfiguration('world'), - '/model/', - LaunchConfiguration('robot_name'), - '/link/oakd_pro_rgb_camera_frame/sensor/rgbd_camera/points'], - '/stereo/depth/points'), - (['/world/', LaunchConfiguration('world'), - '/model/', - LaunchConfiguration('robot_name'), - '/link/oakd_pro_rgb_camera_frame/sensor/rgbd_camera/camera_info'], - '/color/camera_info') - ], - condition=LaunchConfigurationEquals('model', 'standard')) - - oakd_lite_camera_bridge = Node( - package='ros_ign_bridge', - executable='parameter_bridge', - namespace=namespace, - name='camera_bridge', - output='screen', - parameters=[{'use_sim_time': use_sim_time}], - arguments=[ - ['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_lite_rgb_camera_frame/sensor/rgbd_camera/image' + + ['/world/', world, + '/model/', robot_name, + '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/image' + '@sensor_msgs/msg/Image' + '[ignition.msgs.Image'], - ['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_lite_rgb_camera_frame/sensor/rgbd_camera/depth_image' + + ['/world/', world, + '/model/', robot_name, + '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/depth_image' + '@sensor_msgs/msg/Image' + '[ignition.msgs.Image'], - ['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_lite_rgb_camera_frame/sensor/rgbd_camera/points' + + ['/world/', world, + '/model/', robot_name, + '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/points' + '@sensor_msgs/msg/PointCloud2' + '[ignition.msgs.PointCloudPacked'], - ['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_lite_rgb_camera_frame/sensor/rgbd_camera/camera_info' + + ['/world/', world, + '/model/', robot_name, + '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/camera_info' + '@sensor_msgs/msg/CameraInfo' + '[ignition.msgs.CameraInfo'], - ], + ], remappings=[ - (['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_lite_rgb_camera_frame/sensor/rgbd_camera/image'], - '/color/image'), - (['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_lite_rgb_camera_frame/sensor/rgbd_camera/depth_image'], - '/stereo/depth'), - (['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_lite_rgb_camera_frame/sensor/rgbd_camera/points'], - '/stereo/depth/points'), - (['/world/', LaunchConfiguration('world'), - '/model/', LaunchConfiguration('robot_name'), - '/link/oakd_lite_rgb_camera_frame/sensor/rgbd_camera/camera_info'], - '/color/camera_info') - ], - condition=LaunchConfigurationEquals('model', 'lite')) + (['/world/', world, + '/model/', + robot_name, + '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/image'], + 'oakd/rgb/preview/image_raw'), + (['/world/', world, + '/model/', + robot_name, + '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/depth_image'], + 'oakd/rgb/preview/depth'), + (['/world/', world, + '/model/', + robot_name, + '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/points'], + 'oakd/rgb/preview/depth/points'), + (['/world/', world, + '/model/', + robot_name, + '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/camera_info'], + 'oakd/rgb/preview/camera_info') + ] + ) # Define LaunchDescription variable ld = LaunchDescription(ARGUMENTS) @@ -262,6 +213,5 @@ def generate_launch_description(): ld.add_action(hmi_buttons_msg_bridge) ld.add_action(hmi_led_msg_bridge) ld.add_action(lidar_bridge) - ld.add_action(oakd_pro_camera_bridge) - ld.add_action(oakd_lite_camera_bridge) + ld.add_action(oakd_camera_bridge) return ld diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py new file mode 100644 index 0000000..7ebedea --- /dev/null +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py @@ -0,0 +1,79 @@ +# Copyright 2023 Clearpath Robotics, 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. +# +# @author Roni Kreinin (rkreinin@clearpathrobotics.com) + +from ament_index_python.packages import get_package_share_directory + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument +from launch.actions import IncludeLaunchDescription +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution + + +ARGUMENTS = [ + DeclareLaunchArgument('robot_name', default_value='turtlebot4', + description='Robot name'), + DeclareLaunchArgument('namespace', default_value='', + description='Robot namespace'), + DeclareLaunchArgument('rviz', default_value='true', + choices=['true', 'false'], description='Start rviz.'), + DeclareLaunchArgument('world', default_value='depot', + description='Ignition World'), + DeclareLaunchArgument('model', default_value='standard', + choices=['standard', 'lite'], + description='Turtlebot4 Model'), +] + +for pose_element in ['x', 'y', 'z', 'yaw']: + ARGUMENTS.append(DeclareLaunchArgument(pose_element, default_value='0.0', + description=f'{pose_element} component of the robot pose.')) + + +def generate_launch_description(): + # Directories + pkg_turtlebot4_ignition_bringup = get_package_share_directory( + 'turtlebot4_ignition_bringup') + + # Paths + ignition_launch = PathJoinSubstitution( + [pkg_turtlebot4_ignition_bringup, 'launch', 'ignition.launch.py']) + robot_spawn_launch = PathJoinSubstitution( + [pkg_turtlebot4_ignition_bringup, 'launch', 'turtlebot4_spawn.launch.py']) + + ignition = IncludeLaunchDescription( + PythonLaunchDescriptionSource([ignition_launch]), + launch_arguments=[ + ('world', LaunchConfiguration('world')) + ] + ) + + robot_spawn = IncludeLaunchDescription( + PythonLaunchDescriptionSource([robot_spawn_launch]), + launch_arguments=[ + ('robot_name', LaunchConfiguration('robot_name')), + ('namespace', LaunchConfiguration('namespace')), + ('rviz', LaunchConfiguration('rviz')), + ('x', LaunchConfiguration('x')), + ('y', LaunchConfiguration('y')), + ('z', LaunchConfiguration('z')), + ('yaw', LaunchConfiguration('yaw'))] + ) + + # Create launch description and add actions + ld = LaunchDescription(ARGUMENTS) + ld.add_action(ignition) + ld.add_action(robot_spawn) + return ld diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_nodes.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_nodes.launch.py index a3757c7..2d7b89e 100644 --- a/turtlebot4_ignition_bringup/launch/turtlebot4_nodes.launch.py +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_nodes.launch.py @@ -1,4 +1,4 @@ -# Copyright 2021 Clearpath Robotics, Inc. +# Copyright 2023 Clearpath Robotics, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ # @author Roni Kreinin (rkreinin@clearpathrobotics.com) from ament_index_python.packages import get_package_share_directory + from launch import LaunchDescription from launch.actions import DeclareLaunchArgument from launch.conditions import LaunchConfigurationEquals diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py new file mode 100644 index 0000000..21ad45a --- /dev/null +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py @@ -0,0 +1,214 @@ +# Copyright 2023 Clearpath Robotics, 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. +# +# @author Roni Kreinin (rkreinin@clearpathrobotics.com) + + +from ament_index_python.packages import get_package_share_directory + +from irobot_create_common_bringup.offset import OffsetParser, RotationalOffsetX, RotationalOffsetY + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, GroupAction, IncludeLaunchDescription +from launch.conditions import IfCondition +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import LaunchConfiguration, PathJoinSubstitution + +from launch_ros.actions import Node, PushRosNamespace + + +ARGUMENTS = [ + DeclareLaunchArgument('rviz', default_value='true', + choices=['true', 'false'], + description='Start rviz.'), + DeclareLaunchArgument('use_sim_time', default_value='true', + choices=['true', 'false'], + description='use_sim_time'), + DeclareLaunchArgument('model', default_value='standard', + choices=['standard', 'lite'], + description='Turtlebot4 Model'), + DeclareLaunchArgument('robot_name', default_value='turtlebot4', + description='Robot name'), + DeclareLaunchArgument('namespace', default_value=LaunchConfiguration('robot_name'), + description='Robot namespace') +] + + +def generate_launch_description(): + + # Directories + pkg_turtlebot4_ignition_bringup = get_package_share_directory( + 'turtlebot4_ignition_bringup') + pkg_turtlebot4_description = get_package_share_directory( + 'turtlebot4_description') + pkg_turtlebot4_viz = get_package_share_directory( + 'turtlebot4_viz') + pkg_irobot_create_common_bringup = get_package_share_directory( + 'irobot_create_common_bringup') + pkg_irobot_create_ignition_bringup = get_package_share_directory( + 'irobot_create_ignition_bringup') + + # Paths + turtlebot4_ros_ign_bridge_launch = PathJoinSubstitution( + [pkg_turtlebot4_ignition_bringup, 'launch', 'ros_ign_bridge.launch.py']) + rviz_launch = PathJoinSubstitution( + [pkg_turtlebot4_viz, 'launch', 'view_model.launch.py']) + turtlebot4_node_launch = PathJoinSubstitution( + [pkg_turtlebot4_ignition_bringup, 'launch', 'turtlebot4_nodes.launch.py']) + create3_nodes_launch = PathJoinSubstitution( + [pkg_irobot_create_common_bringup, 'launch', 'create3_nodes.launch.py']) + create3_ignition_nodes_launch = PathJoinSubstitution( + [pkg_irobot_create_ignition_bringup, 'launch', 'create3_ignition_nodes.launch.py']) + robot_description_launch = PathJoinSubstitution( + [pkg_turtlebot4_description, 'launch', 'robot_description.launch.py']) + dock_description_launch = PathJoinSubstitution( + [pkg_irobot_create_common_bringup, 'launch', 'dock_description.launch.py']) + + # Parameters + param_file_cmd = DeclareLaunchArgument( + 'param_file', + default_value=PathJoinSubstitution( + [pkg_turtlebot4_ignition_bringup, 'config', 'turtlebot4_node.yaml']), + description='Turtlebot4 Robot param file') + + # Launch configurations + namespace = LaunchConfiguration('namespace') + x, y, z = LaunchConfiguration('x'), LaunchConfiguration('y'), LaunchConfiguration('z') + yaw = LaunchConfiguration('yaw') + turtlebot4_node_yaml_file = LaunchConfiguration('param_file') + + # Calculate dock offset due to yaw rotation + dock_offset_x = RotationalOffsetX(0.157, yaw) + dock_offset_y = RotationalOffsetY(0.157, yaw) + # Spawn dock at robot position + rotational offset + x_dock = OffsetParser(x, dock_offset_x) + y_dock = OffsetParser(y, dock_offset_y) + # Rotate dock towards robot + yaw_dock = OffsetParser(yaw, 3.1416) + + spawn_robot_group_action = GroupAction([ + PushRosNamespace(namespace), + + # Robot description + IncludeLaunchDescription( + PythonLaunchDescriptionSource([robot_description_launch]), + launch_arguments=[('model', LaunchConfiguration('model')), + ('use_sim_time', LaunchConfiguration('use_sim_time')), + ('robot_name', LaunchConfiguration('robot_name'))] + ), + + # Dock description + IncludeLaunchDescription( + PythonLaunchDescriptionSource([dock_description_launch]), + # The robot starts docked + launch_arguments={'gazebo': 'ignition'}.items(), + ), + + # Spawn TurtleBot 4 + Node( + package='ros_ign_gazebo', + executable='create', + arguments=['-name', LaunchConfiguration('robot_name'), + '-x', x, + '-y', y, + '-z', z, + '-Y', yaw, + '-topic', 'robot_description'], + output='screen' + ), + + # Spawn Dock + Node( + package='ros_ign_gazebo', + executable='create', + arguments=['-name', [LaunchConfiguration('robot_name'), '/standard_dock'], + '-x', x_dock, + '-y', y_dock, + '-z', z, + '-Y', yaw_dock, + '-topic', 'standard_dock_description'], + output='screen', + ), + + # ROS IGN bridge + IncludeLaunchDescription( + PythonLaunchDescriptionSource([turtlebot4_ros_ign_bridge_launch]), + launch_arguments=[('model', LaunchConfiguration('model'))] + ), + + # TurtleBot 4 nodes + IncludeLaunchDescription( + PythonLaunchDescriptionSource([turtlebot4_node_launch]), + launch_arguments=[('model', LaunchConfiguration('model')), + ('param_file', turtlebot4_node_yaml_file)] + ), + + # Create 3 nodes + IncludeLaunchDescription( + PythonLaunchDescriptionSource([create3_nodes_launch]) + ), + + # Create 3 Ignition nodes + IncludeLaunchDescription( + PythonLaunchDescriptionSource([create3_ignition_nodes_launch]) + ), + + # RPLIDAR static transforms + Node( + name='rplidar_stf', + package='tf2_ros', + executable='static_transform_publisher', + output='screen', + arguments=[ + '0', '0', '0', '0', '0', '0.0', + 'rplidar_link', [LaunchConfiguration('robot_name'), '/rplidar_link/rplidar']], + remappings=[ + ('/tf', 'tf'), + ('/tf_static', 'tf_static'), + ] + ), + + # OAKD static transform + # Required for pointcloud. See https://github.com/gazebosim/gz-sensors/issues/239 + Node( + name='camera_stf', + package='tf2_ros', + executable='static_transform_publisher', + output='screen', + arguments=[ + '0', '0', '0', + '1.5707', '-1.5707' ,'0', + 'oakd_rgb_camera_optical_frame', + [LaunchConfiguration('robot_name'), '/oakd_rgb_camera_frame/rgbd_camera'] + ], + remappings=[ + ('/tf', 'tf'), + ('/tf_static', 'tf_static'), + ] + ) + ]) + + # RViz + rviz = IncludeLaunchDescription( + PythonLaunchDescriptionSource([rviz_launch]), + launch_arguments=[('namespace', namespace)], + condition=IfCondition(LaunchConfiguration('rviz')), + ) + + # Define LaunchDescription variable + ld = LaunchDescription(ARGUMENTS) + ld.add_action(param_file_cmd) + ld.add_action(spawn_robot_group_action) + ld.add_action(rviz) + return ld diff --git a/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.cc b/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.cc index 058ce0e..7ff1c3f 100644 --- a/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.cc +++ b/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.cc @@ -33,11 +33,25 @@ Turtlebot4Hmi::Turtlebot4Hmi() : Plugin() { App()->Engine()->rootContext()->setContextProperty("DisplayListView", &this->display_list_); + CreatePublishers(); + CreateSubscribers(); +} + +Turtlebot4Hmi::~Turtlebot4Hmi() +{ +} + +void Turtlebot4Hmi::CreatePublishers() +{ this->hmi_button_pub_ = ignition::transport::Node::Publisher(); this->hmi_button_pub_ = this->node_.Advertise < ignition::msgs::Int32 > (this->hmi_button_topic_); this->create3_button_pub_ = ignition::transport::Node::Publisher(); this->create3_button_pub_ = this->node_.Advertise < ignition::msgs::Int32 > ( this->create3_button_topic_); +} + +void Turtlebot4Hmi::CreateSubscribers() +{ this->node_.Subscribe(this->display_topic_, &Turtlebot4Hmi::OnRawMessage, this); this->node_.Subscribe(this->display_selected_topic_, &Turtlebot4Hmi::OnSelectedMessage, this); this->node_.Subscribe(this->power_led_topic_, &Turtlebot4Hmi::OnPowerLedMessage, this); @@ -49,8 +63,23 @@ Turtlebot4Hmi::Turtlebot4Hmi() this->node_.Subscribe(this->user2_led_topic_, &Turtlebot4Hmi::OnUser2LedMessage, this); } -Turtlebot4Hmi::~Turtlebot4Hmi() +void Turtlebot4Hmi::RemovePublishers() { + this->node_.UnadvertiseSrv(this->hmi_button_topic_); + this->node_.UnadvertiseSrv(this->create3_button_topic_); +} + +void Turtlebot4Hmi::RemoveSubscribers() +{ + this->node_.Unsubscribe(this->display_topic_); + this->node_.Unsubscribe(this->display_selected_topic_); + this->node_.Unsubscribe(this->power_led_topic_); + this->node_.Unsubscribe(this->motors_led_topic_); + this->node_.Unsubscribe(this->comms_led_topic_); + this->node_.Unsubscribe(this->wifi_led_topic_); + this->node_.Unsubscribe(this->battery_led_topic_); + this->node_.Unsubscribe(this->user1_led_topic_); + this->node_.Unsubscribe(this->user2_led_topic_); } void Turtlebot4Hmi::LoadConfig(const tinyxml2::XMLElement * _pluginElem) @@ -63,11 +92,52 @@ void Turtlebot4Hmi::LoadConfig(const tinyxml2::XMLElement * _pluginElem) this->title = "Turtlebot4 HMI"; } + auto namespaceElem = _pluginElem->FirstChildElement("namespace"); + if (nullptr != namespaceElem && nullptr != namespaceElem->GetText()) + { + this->SetNamespace(namespaceElem->GetText()); + } + this->connect( this, SIGNAL(AddMsg(QString)), this, SLOT(OnAddMsg(QString)), Qt::QueuedConnection); } +QString Turtlebot4Hmi::Namespace() const +{ + return QString::fromStdString(this->namespace_); +} + +void Turtlebot4Hmi::SetNamespace(const QString &_name) +{ + this->namespace_ = _name.toStdString(); + + ignmsg << "A new robot namespace has been entered: '" << + this->namespace_ << " ' " <create3_button_topic_ = this->namespace_ + "/create3_buttons"; + this->hmi_button_topic_ = this->namespace_ + "/hmi/buttons"; + this->display_topic_ = this->namespace_ + "/hmi/display/raw"; + this->display_selected_topic_ = this->namespace_ + "/hmi/display/selected"; + this->power_led_topic_ = this->namespace_ + "/hmi/led/power"; + this->motors_led_topic_ = this->namespace_ + "/hmi/led/motors"; + this->comms_led_topic_ = this->namespace_ + "/hmi/led/comms"; + this->wifi_led_topic_ = this->namespace_ + "/hmi/led/wifi"; + this->battery_led_topic_ = this->namespace_ + "/hmi/led/battery"; + this->user1_led_topic_ = this->namespace_ + "/hmi/led/user1"; + this->user2_led_topic_ = this->namespace_ + "/hmi/led/user2"; + + // Recreate publishers and subscribers with new topics. + CreatePublishers(); + CreateSubscribers(); + this->NamespaceChanged(); +} + void Turtlebot4Hmi::OnHmiButton(const int button) { ignition::msgs::Int32 button_msg; diff --git a/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.hh b/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.hh index 690b5d2..b89efb7 100644 --- a/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.hh +++ b/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.hh @@ -36,6 +36,14 @@ class Turtlebot4Hmi : public Plugin { Q_OBJECT + // \brief Namespace + Q_PROPERTY( + QString name + READ Namespace + WRITE SetNamespace + NOTIFY NamespaceChanged + ) + public: /// \brief Constructor Turtlebot4Hmi(); @@ -44,6 +52,16 @@ public: /// \brief Called by Ignition GUI when plugin is instantiated. /// \param[in] _pluginElem XML configuration for this plugin. void LoadConfig(const tinyxml2::XMLElement * _pluginElem) override; + // \brief Get the robot namespace as a string, for example + /// '/robot1' + /// \return Namespace + Q_INVOKABLE QString Namespace() const; + +public slots: + /// \brief Callback in Qt thread when the robot namespace changes. + /// \param[in] _name variable to indicate the robot namespace to + /// publish the Button commands. + void SetNamespace(const QString &_name); protected slots: /// \brief Callback trigged when the button is pressed. @@ -59,6 +77,8 @@ signals: void setBatteryState(const bool state, const QString color); void setUser1State(const bool state, const QString color); void setUser2State(const bool state, const QString color); + /// \brief Notify that robot namespace has changed + void NamespaceChanged(); /// \brief Subscriber callbacks private: @@ -71,6 +91,10 @@ private: void OnBatteryLedMessage(const ignition::msgs::Int32 & msg); void OnUser1LedMessage(const ignition::msgs::Int32 & msg); void OnUser2LedMessage(const ignition::msgs::Int32 & msg); + void CreatePublishers(); + void CreateSubscribers(); + void RemovePublishers(); + void RemoveSubscribers(); signals: void AddMsg(QString msg); @@ -83,17 +107,18 @@ private: ignition::transport::Node::Publisher hmi_button_pub_; ignition::transport::Node::Publisher create3_button_pub_; - std::string hmi_button_topic_ = "/model/turtlebot4/hmi/buttons"; - std::string create3_button_topic_ = "/create3/buttons"; - std::string display_topic_ = "/model/turtlebot4/hmi/display/raw"; - std::string display_selected_topic_ = "/model/turtlebot4/hmi/display/selected"; - std::string power_led_topic_ = "/model/turtlebot4/hmi/led/power"; - std::string motors_led_topic_ = "/model/turtlebot4/hmi/led/motors"; - std::string comms_led_topic_ = "/model/turtlebot4/hmi/led/comms"; - std::string wifi_led_topic_ = "/model/turtlebot4/hmi/led/wifi"; - std::string battery_led_topic_ = "/model/turtlebot4/hmi/led/battery"; - std::string user1_led_topic_ = "/model/turtlebot4/hmi/led/user1"; - std::string user2_led_topic_ = "/model/turtlebot4/hmi/led/user2"; + std::string namespace_ = ""; + std::string hmi_button_topic_ = "/hmi/buttons"; + std::string create3_button_topic_ = "/create3_buttons"; + std::string display_topic_ = "/hmi/display/raw"; + std::string display_selected_topic_ = "/hmi/display/selected"; + std::string power_led_topic_ = "/hmi/led/power"; + std::string motors_led_topic_ = "/hmi/led/motors"; + std::string comms_led_topic_ = "/hmi/led/comms"; + std::string wifi_led_topic_ = "/hmi/led/wifi"; + std::string battery_led_topic_ = "/hmi/led/battery"; + std::string user1_led_topic_ = "/hmi/led/user1"; + std::string user2_led_topic_ = "/hmi/led/user2"; QStringListModel display_list_; diff --git a/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.qml b/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.qml index 220d19f..f511ec6 100644 --- a/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.qml +++ b/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.qml @@ -31,7 +31,7 @@ Rectangle anchors.fill: parent focus: true Layout.minimumWidth: 400 - Layout.minimumHeight: 525 + Layout.minimumHeight: 575 Connections { target: Turtlebot4Hmi @@ -74,26 +74,55 @@ Rectangle Rectangle { - id: create3ButtonsRectangle + id: namespaceRectangle border.color: "black" border.width: 2 anchors.top: widgetRectangle.top anchors.left: widgetRectangle.left focus: true - height: 125 + height: 75 width: 400 - - // Buttons + // Robot namespace input Label { - id: create3ButtonsLabel - text: "Create3" - font.pixelSize: 22 - anchors.top: create3ButtonsRectangle.top + id: namespaceLabel + text: "Namespace:" + Layout.fillWidth: true + Layout.margins: 10 + anchors.top: namespaceRectangle.top anchors.topMargin: 10 - anchors.left: parent.left + anchors.left: namespaceRectangle.left + anchors.leftMargin: 10 + } + + TextField { + id: nameField + width: 175 + Layout.fillWidth: true + Layout.margins: 10 + text: Turtlebot4Hmi.namespace + placeholderText: qsTr("Robot namespace") + anchors.top: namespaceLabel.bottom + anchors.topMargin: 5 + anchors.left: namespaceRectangle.left anchors.leftMargin: 10 + onEditingFinished: { + Turtlebot4Hmi.SetNamespace(text) + } } + } + + Rectangle + { + id: create3ButtonsRectangle + border.color: "black" + border.width: 2 + anchors.top: namespaceRectangle.bottom + anchors.left: namespaceRectangle.left + focus: true + height: 125 + width: 400 + // Buttons ToolButton { id: create3Button1 anchors.verticalCenter: create3ButtonPower.verticalCenter @@ -115,8 +144,8 @@ Rectangle ToolButton { id: create3ButtonPower - anchors.top: create3ButtonsLabel.bottom - anchors.topMargin: 0 + anchors.bottom: create3ButtonsRectangle.bottom + anchors.bottomMargin: 15 anchors.horizontalCenter: create3ButtonsRectangle.horizontalCenter checkable: true checked: true @@ -156,7 +185,7 @@ Rectangle Rectangle { id: hmiRectangle - height: 350 + height: 325 width: 400 color: "transparent" border.color: "black" @@ -164,19 +193,9 @@ Rectangle anchors.top: create3ButtonsRectangle.bottom anchors.left: create3ButtonsRectangle.left - Label { - id: hmiLabel - text: "Turtlebot4 HMI" - font.pixelSize: 22 - anchors.top: hmiRectangle.top - anchors.topMargin: 10 - anchors.left: hmiRectangle.left - anchors.leftMargin: 10 - } - StatusIndicator { id: ledPower - anchors.top: hmiLabel.bottom + anchors.top: hmiRectangle.top anchors.topMargin: 10 anchors.right: ledMotors.left anchors.rightMargin: 35 @@ -195,7 +214,7 @@ Rectangle StatusIndicator { id: ledMotors - anchors.top: hmiLabel.bottom + anchors.top: hmiRectangle.top anchors.topMargin: 10 anchors.right: ledComms.left anchors.rightMargin: 35 @@ -214,7 +233,7 @@ Rectangle StatusIndicator { id: ledComms - anchors.top: hmiLabel.bottom + anchors.top: hmiRectangle.top anchors.topMargin: 10 anchors.horizontalCenter: hmiRectangle.horizontalCenter color: "green" @@ -232,7 +251,7 @@ Rectangle StatusIndicator { id: ledWifi - anchors.top: hmiLabel.bottom + anchors.top: hmiRectangle.top anchors.topMargin: 10 anchors.left: ledComms.right anchors.leftMargin: 35 @@ -251,7 +270,7 @@ Rectangle StatusIndicator { id: ledBattery - anchors.top: hmiLabel.bottom + anchors.top: hmiRectangle.top anchors.topMargin: 10 anchors.left: ledWifi.right anchors.leftMargin: 35 diff --git a/turtlebot4_ignition_toolbox/src/hmi_node.cpp b/turtlebot4_ignition_toolbox/src/hmi_node.cpp index 077d11e..a707a76 100644 --- a/turtlebot4_ignition_toolbox/src/hmi_node.cpp +++ b/turtlebot4_ignition_toolbox/src/hmi_node.cpp @@ -28,25 +28,25 @@ Hmi::Hmi() : rclcpp::Node("hmi_node") { display_subscriber_ = create_subscription( - "/hmi/display", + "hmi/display", rclcpp::SensorDataQoS(), std::bind(&Hmi::display_subscriber_callback, this, std::placeholders::_1)); button_subscriber_ = create_subscription( - "/hmi/buttons/_set", + "hmi/buttons/_set", rclcpp::QoS(rclcpp::KeepLast(10)), std::bind(&Hmi::button_subscriber_callback, this, std::placeholders::_1)); button_publisher_ = create_publisher( - "/hmi/buttons", + "hmi/buttons", rclcpp::SensorDataQoS()); display_raw_publisher_ = create_publisher( - "/hmi/display/_raw", + "hmi/display/_raw", rclcpp::QoS(rclcpp::KeepLast(10))); display_selected_publisher_ = create_publisher( - "/hmi/display/_selected", + "hmi/display/_selected", rclcpp::QoS(rclcpp::KeepLast(10))); } From e9945bdde53c5c3cfdbb6676a78ed2444eeca6f5 Mon Sep 17 00:00:00 2001 From: Roni Kreinin Date: Mon, 13 Mar 2023 17:59:10 -0400 Subject: [PATCH 02/14] Added missing launch configurations --- .../launch/turtlebot4_spawn.launch.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py index 21ad45a..ffddef1 100644 --- a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py @@ -1,4 +1,4 @@ -# Copyright 2023 Clearpath Robotics, Inc. +# Copyright 2021 Clearpath Robotics, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -44,6 +44,10 @@ description='Robot namespace') ] +for pose_element in ['x', 'y', 'z', 'yaw']: + ARGUMENTS.append(DeclareLaunchArgument(pose_element, default_value='0.0', + description=f'{pose_element} component of the robot pose.')) + def generate_launch_description(): @@ -84,6 +88,7 @@ def generate_launch_description(): # Launch configurations namespace = LaunchConfiguration('namespace') + use_sim_time = LaunchConfiguration('use_sim_time') x, y, z = LaunchConfiguration('x'), LaunchConfiguration('y'), LaunchConfiguration('z') yaw = LaunchConfiguration('yaw') turtlebot4_node_yaml_file = LaunchConfiguration('param_file') @@ -202,7 +207,9 @@ def generate_launch_description(): # RViz rviz = IncludeLaunchDescription( PythonLaunchDescriptionSource([rviz_launch]), - launch_arguments=[('namespace', namespace)], + launch_arguments=[ + ('namespace', namespace), + ('use_sim_time', use_sim_time)], condition=IfCondition(LaunchConfiguration('rviz')), ) From b6901b1c204b67647209e23f053d51000a56a8f8 Mon Sep 17 00:00:00 2001 From: Roni Kreinin Date: Wed, 15 Mar 2023 17:25:52 -0400 Subject: [PATCH 03/14] Namespace the default robot name 'turtlebot4' rather than using unique robot name and namespace --- .../launch/ros_ign_bridge.launch.py | 30 ++++++++-------- .../launch/turtlebot4_ignition.launch.py | 3 -- .../launch/turtlebot4_spawn.launch.py | 36 ++++++++++++------- turtlebot4_ignition_bringup/worlds/depot.sdf | 2 +- 4 files changed, 40 insertions(+), 31 deletions(-) diff --git a/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py b/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py index d043957..702d326 100644 --- a/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py +++ b/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py @@ -30,8 +30,10 @@ choices=['true', 'false'], description='Use sim time'), DeclareLaunchArgument('robot_name', default_value='turtlebot4', - description='Robot name'), - DeclareLaunchArgument('namespace', default_value=LaunchConfiguration('robot_name'), + description='Ignition model name'), + DeclareLaunchArgument('dock_name', default_value='standard_dock', + description='Ignition model name'), + DeclareLaunchArgument('namespace', default_value='', description='Robot namespace'), DeclareLaunchArgument('world', default_value='depot', description='World name'), @@ -42,6 +44,12 @@ def generate_launch_description(): + use_sim_time = LaunchConfiguration('use_sim_time') + robot_name = LaunchConfiguration('robot_name') + dock_name = LaunchConfiguration('dock_name') + namespace = LaunchConfiguration('namespace') + world = LaunchConfiguration('world') + leds = [ 'power', 'motors', @@ -52,11 +60,6 @@ def generate_launch_description(): 'user2' ] - robot_name = LaunchConfiguration('robot_name') - namespace = LaunchConfiguration('namespace') - world = LaunchConfiguration('world') - use_sim_time = LaunchConfiguration('use_sim_time') - pkg_irobot_create_ignition_bringup = get_package_share_directory( 'irobot_create_ignition_bringup') @@ -67,6 +70,7 @@ def generate_launch_description(): PythonLaunchDescriptionSource([create3_ros_gz_bridge_launch]), launch_arguments=[ ('robot_name', robot_name), + ('dock_name', dock_name), ('namespace', namespace), ('world', world) ] @@ -184,23 +188,19 @@ def generate_launch_description(): ], remappings=[ (['/world/', world, - '/model/', - robot_name, + '/model/', robot_name, '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/image'], 'oakd/rgb/preview/image_raw'), (['/world/', world, - '/model/', - robot_name, + '/model/', robot_name, '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/depth_image'], 'oakd/rgb/preview/depth'), (['/world/', world, - '/model/', - robot_name, + '/model/', robot_name, '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/points'], 'oakd/rgb/preview/depth/points'), (['/world/', world, - '/model/', - robot_name, + '/model/', robot_name, '/link/oakd_rgb_camera_frame/sensor/rgbd_camera/camera_info'], 'oakd/rgb/preview/camera_info') ] diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py index 7ebedea..e6cfb68 100644 --- a/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py @@ -24,8 +24,6 @@ ARGUMENTS = [ - DeclareLaunchArgument('robot_name', default_value='turtlebot4', - description='Robot name'), DeclareLaunchArgument('namespace', default_value='', description='Robot namespace'), DeclareLaunchArgument('rviz', default_value='true', @@ -63,7 +61,6 @@ def generate_launch_description(): robot_spawn = IncludeLaunchDescription( PythonLaunchDescriptionSource([robot_spawn_launch]), launch_arguments=[ - ('robot_name', LaunchConfiguration('robot_name')), ('namespace', LaunchConfiguration('namespace')), ('rviz', LaunchConfiguration('rviz')), ('x', LaunchConfiguration('x')), diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py index ffddef1..ae5b68e 100644 --- a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py @@ -18,6 +18,7 @@ from ament_index_python.packages import get_package_share_directory from irobot_create_common_bringup.offset import OffsetParser, RotationalOffsetX, RotationalOffsetY +from irobot_create_common_bringup.namespace import GetNamespacedName from launch import LaunchDescription from launch.actions import DeclareLaunchArgument, GroupAction, IncludeLaunchDescription @@ -38,9 +39,7 @@ DeclareLaunchArgument('model', default_value='standard', choices=['standard', 'lite'], description='Turtlebot4 Model'), - DeclareLaunchArgument('robot_name', default_value='turtlebot4', - description='Robot name'), - DeclareLaunchArgument('namespace', default_value=LaunchConfiguration('robot_name'), + DeclareLaunchArgument('namespace', default_value='', description='Robot namespace') ] @@ -93,6 +92,9 @@ def generate_launch_description(): yaw = LaunchConfiguration('yaw') turtlebot4_node_yaml_file = LaunchConfiguration('param_file') + robot_name = GetNamespacedName(namespace, 'turtlebot4') + dock_name = GetNamespacedName(namespace, 'standard_dock') + # Calculate dock offset due to yaw rotation dock_offset_x = RotationalOffsetX(0.157, yaw) dock_offset_y = RotationalOffsetY(0.157, yaw) @@ -109,8 +111,7 @@ def generate_launch_description(): IncludeLaunchDescription( PythonLaunchDescriptionSource([robot_description_launch]), launch_arguments=[('model', LaunchConfiguration('model')), - ('use_sim_time', LaunchConfiguration('use_sim_time')), - ('robot_name', LaunchConfiguration('robot_name'))] + ('use_sim_time', LaunchConfiguration('use_sim_time'))] ), # Dock description @@ -124,7 +125,7 @@ def generate_launch_description(): Node( package='ros_ign_gazebo', executable='create', - arguments=['-name', LaunchConfiguration('robot_name'), + arguments=['-name', robot_name, '-x', x, '-y', y, '-z', z, @@ -137,7 +138,7 @@ def generate_launch_description(): Node( package='ros_ign_gazebo', executable='create', - arguments=['-name', [LaunchConfiguration('robot_name'), '/standard_dock'], + arguments=['-name', dock_name, '-x', x_dock, '-y', y_dock, '-z', z, @@ -149,7 +150,11 @@ def generate_launch_description(): # ROS IGN bridge IncludeLaunchDescription( PythonLaunchDescriptionSource([turtlebot4_ros_ign_bridge_launch]), - launch_arguments=[('model', LaunchConfiguration('model'))] + launch_arguments=[ + ('model', LaunchConfiguration('model')), + ('robot_name', robot_name), + ('dock_name', dock_name), + ('namespace', namespace)] ), # TurtleBot 4 nodes @@ -161,12 +166,19 @@ def generate_launch_description(): # Create 3 nodes IncludeLaunchDescription( - PythonLaunchDescriptionSource([create3_nodes_launch]) + PythonLaunchDescriptionSource([create3_nodes_launch]), + launch_arguments=[ + ('namespace', namespace) + ] ), # Create 3 Ignition nodes IncludeLaunchDescription( - PythonLaunchDescriptionSource([create3_ignition_nodes_launch]) + PythonLaunchDescriptionSource([create3_ignition_nodes_launch]), + launch_arguments=[ + ('robot_name', robot_name), + ('dock_name', dock_name), + ] ), # RPLIDAR static transforms @@ -177,7 +189,7 @@ def generate_launch_description(): output='screen', arguments=[ '0', '0', '0', '0', '0', '0.0', - 'rplidar_link', [LaunchConfiguration('robot_name'), '/rplidar_link/rplidar']], + 'rplidar_link', [robot_name, '/rplidar_link/rplidar']], remappings=[ ('/tf', 'tf'), ('/tf_static', 'tf_static'), @@ -195,7 +207,7 @@ def generate_launch_description(): '0', '0', '0', '1.5707', '-1.5707' ,'0', 'oakd_rgb_camera_optical_frame', - [LaunchConfiguration('robot_name'), '/oakd_rgb_camera_frame/rgbd_camera'] + [robot_name, '/oakd_rgb_camera_frame/rgbd_camera'] ], remappings=[ ('/tf', 'tf'), diff --git a/turtlebot4_ignition_bringup/worlds/depot.sdf b/turtlebot4_ignition_bringup/worlds/depot.sdf index e117533..110a4bf 100644 --- a/turtlebot4_ignition_bringup/worlds/depot.sdf +++ b/turtlebot4_ignition_bringup/worlds/depot.sdf @@ -5,7 +5,7 @@ false - 0.002 + 0.01 1.0 From 629a8c7ce01b9363af95e0e7c373c30e2a72c729 Mon Sep 17 00:00:00 2001 From: Hilary Luo Date: Thu, 6 Apr 2023 11:44:06 -0400 Subject: [PATCH 04/14] Fixed world name and set max step size for better performance --- turtlebot4_ignition_bringup/worlds/maze.sdf | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/turtlebot4_ignition_bringup/worlds/maze.sdf b/turtlebot4_ignition_bringup/worlds/maze.sdf index aa0f4bd..1916a4e 100644 --- a/turtlebot4_ignition_bringup/worlds/maze.sdf +++ b/turtlebot4_ignition_bringup/worlds/maze.sdf @@ -1,7 +1,8 @@ + - + - 0.001 + 0.003 1 1000 From c0311841f3e1e6b7b11d57ba0b07dab94a2bacad Mon Sep 17 00:00:00 2001 From: Hilary Luo Date: Thu, 6 Apr 2023 11:46:16 -0400 Subject: [PATCH 05/14] Fixed model spawning in wall, improved visuals and made locations less ambiguous for slam --- turtlebot4_ignition_bringup/worlds/maze.sdf | 299 ++++++++++++++++---- 1 file changed, 238 insertions(+), 61 deletions(-) diff --git a/turtlebot4_ignition_bringup/worlds/maze.sdf b/turtlebot4_ignition_bringup/worlds/maze.sdf index 1916a4e..00950da 100644 --- a/turtlebot4_ignition_bringup/worlds/maze.sdf +++ b/turtlebot4_ignition_bringup/worlds/maze.sdf @@ -92,6 +92,11 @@ 0.01 20 2 + + 0.1 0.1 0.1 1 + 0 0.01 0.05 1 + 0 0.01 0.05 1 + @@ -110,6 +115,11 @@ 0.01 20 2 + + 0.1 0.1 0.1 1 + 0 0.01 0.05 1 + 0 0.01 0.05 1 + @@ -128,6 +138,11 @@ 20 0.01 2 + + 0.1 0.1 0.1 1 + 0 0.01 0.05 1 + 0 0.01 0.05 1 + @@ -139,6 +154,11 @@ 20 0.01 2 + + 0.1 0.1 0.1 1 + 0 0.01 0.05 1 + 0 0.01 0.05 1 + @@ -146,6 +166,11 @@ 20 0.01 2 + + 0.1 0.1 0.1 1 + 0 0.01 0.05 1 + 0 0.01 0.05 1 + @@ -169,6 +194,11 @@ 1 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -188,6 +218,11 @@ 3 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -207,6 +242,11 @@ 1 6 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -226,6 +266,11 @@ 1 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -245,6 +290,11 @@ 2 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -264,6 +314,11 @@ 2 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -283,6 +338,11 @@ 1 3 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -302,6 +362,11 @@ 1 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -321,6 +386,11 @@ 2 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -340,6 +410,11 @@ 5 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -359,25 +434,34 @@ 4 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - - 0 5 0 0 0 0 + 0 5.5 0 0 0 0 true - 2 10 1 + 2 9 1 - 2 10 1 + 2 9 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -397,6 +481,11 @@ 2 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -416,6 +505,11 @@ 1 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -435,6 +529,11 @@ 1 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -454,6 +553,11 @@ 3 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -473,6 +577,11 @@ 3 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -492,6 +601,11 @@ 3 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -511,6 +625,11 @@ 3 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -530,6 +649,11 @@ 3 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -549,6 +673,11 @@ 1 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -568,6 +697,11 @@ 1 3 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -587,6 +721,11 @@ 6 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + @@ -606,11 +745,16 @@ 1 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 1.5 3.5 0 0 0 0 + 1.5 5.5 0 0 0 0 true @@ -625,49 +769,64 @@ 1 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 2.5 4.5 0 0 0 0 + 2.5 6 0 0 0 0 true - 1 1 1 + 1 2 1 - 1 1 1 + 1 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 3.5 5.5 0 0 0 0 + 3.5 7.5 0 0 0 0 true - 1 1 1 + 1 3 1 - 1 1 1 + 1 3 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 4.5 6.5 0 0 0 0 + 4.5 8.5 0 0 0 0 true @@ -682,30 +841,40 @@ 1 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 5.5 7.5 0 0 0 0 + 5.5 9 0 0 0 0 true - 1 1 1 + 1 2 1 - 1 1 1 + 1 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 6.5 8.5 0 0 0 0 + 6.5 9.5 0 0 0 0 true @@ -720,149 +889,157 @@ 1 1 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 7.5 9.5 0 0 0 0 + 4.5 3 0 0 0 0 true - 1 1 1 + 1 2 1 - 1 1 1 + 1 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 4.5 2.5 0 0 0 0 + 5.5 4 0 0 0 0 true - 1 1 1 + 1 2 1 - 1 1 1 + 1 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 5.5 3.5 0 0 0 0 + 6.5 5 0 0 0 0 true - 1 1 1 + 1 2 1 - 1 1 1 + 1 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 6.5 4.5 0 0 0 0 + 7.5 6 0 0 0 0 true - 1 1 1 + 1 2 1 - 1 1 1 + 1 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 7.5 5.5 0 0 0 0 + 8.5 7 0 0 0 0 true - 1 1 1 + 1 2 1 - 1 1 1 + 1 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - 8.5 6.5 0 0 0 0 + 9.5 8 0 0 0 0 true - 1 1 1 + 1 2 1 - 1 1 1 - - - - - - - 9.5 7.5 0 0 0 0 - true - - - - 1 1 1 - - - - - - - 1 1 1 + 1 2 1 + + 0.1 0.1 0.1 1 + 0 0.1 0.2 1 + 0 0.01 0.05 1 + - - - \ No newline at end of file From f304df147667d6529702071e3f475cd062b2c388 Mon Sep 17 00:00:00 2001 From: Hilary Luo Date: Thu, 6 Apr 2023 11:48:27 -0400 Subject: [PATCH 06/14] New world --- .../worlds/warehouse.sdf | 257 ++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 turtlebot4_ignition_bringup/worlds/warehouse.sdf diff --git a/turtlebot4_ignition_bringup/worlds/warehouse.sdf b/turtlebot4_ignition_bringup/worlds/warehouse.sdf new file mode 100644 index 0000000..6a36bb2 --- /dev/null +++ b/turtlebot4_ignition_bringup/worlds/warehouse.sdf @@ -0,0 +1,257 @@ + + + + + 0.003 + 1.0 + + + + + + + + 1 1 1 1 + 0.3 0.7 0.9 1 + 0 + false + + + + 0 + -5 -3 10 0 0 0 + 1 1 1 1 + 1 1 1 1 + 0 0 -1 + + + + true + + + + + 0.0 0.0 1 + 1 1 + + + + + 0 0 0 0 0 0 + + + + + + https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/Warehouse + + warehouse + 0 0 -0.1 0 0 0 + + + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/pallet_box_mobile + + pallet_box_0 + -4 12 0.01 0 0 0 + true + + + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf_big + + shelf_big_0 + -8.5 -13 0 0 -0 0 + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf_big + + shelf_big_1 + 6.5 -13 0 0 -0 0 + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf_big + + shelf_big_2 + -1.5 -13 0 0 -0 0 + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf + + shelf_3 + 13.5 4.5 0 0 -0 0 + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf + + shelf_4 + 10 4.5 0 0 -0 0 + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf + + shelf_5 + 13.5 -21 0 0 -0 0 + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf + + shelf_6 + 13.5 -15 0 0 -0 0 + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf + + shelf_7 + 0.4 -2 0 0 -0 0 + + + + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf_big + + shelf_big_3 + 3.5 9.5 0 0 0 1.57 + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf_big + + shelf_big_4 + -1.3 18.5 0 0 0 1.57 + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf + + shelf_0 + -10 21.5 0 0 -0 1.57 + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf + + shelf_1 + -7 23.6 0 0 -0 1.57 + + + + https://fuel.ignitionrobotics.org/1.0/MovAi/models/shelf + + shelf_2 + -4 21.5 0 0 -0 1.57 + + + + + + + https://fuel.gazebosim.org/1.0/OpenRobotics/models/Jersey Barrier + + barrier_0 + -10.4 14.75 0 0 0 1.57 + + + + https://fuel.gazebosim.org/1.0/OpenRobotics/models/Jersey Barrier + + barrier_1 + -10.4 10.5 0 0 0 1.57 + + + + https://fuel.gazebosim.org/1.0/OpenRobotics/models/Jersey Barrier + + barrier_2 + -10.4 6.5 0 0 0 1.57 + + + + https://fuel.gazebosim.org/1.0/OpenRobotics/models/Jersey Barrier + + barrier_3 + -12.85 4.85 0 0 0 0 + + + + + + + https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/Chair + + chair_0 + 14.3 -5.5 0 0 -0 3 + + + + https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/Chair + + chair_1 + 14.3 -4 0 0 -0 -3 + + + + https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/foldable_chair + + fchair_0 + -11.5 6.4 0 0 -0 -1.8 + + + + https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/foldable_chair + + fchair1 + -14 6.5 0 0 -0 1.9 + + + + + + + https://fuel.ignitionrobotics.org/1.0/OpenRobotics/models/Table + + table0 + -12.7 6.5 0 0 0 0 + + + + + + + https://fuel.gazebosim.org/1.0/OpenRobotics/models/Rescue Randy Sitting + + Person 0 - Sitting + 14.65 -10 0 0 0 -1.57 + + + + + https://fuel.gazebosim.org/1.0/OpenRobotics/models/MaleVisitorOnPhone + + Person 1 - Standing + 1 -1 0 0 0 1.57 + + + + + https://fuel.gazebosim.org/1.0/plateau/models/Casual female + + Person 2 - Walking + -12 15 0 0 0 0 + + + + From 820a1634eabe851594fb57d8a0e478212cac2c4e Mon Sep 17 00:00:00 2001 From: Hilary Luo Date: Thu, 6 Apr 2023 13:32:24 -0400 Subject: [PATCH 07/14] Make warehouse the default world --- turtlebot4_ignition_bringup/launch/ignition.launch.py | 2 +- turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py | 2 +- .../launch/turtlebot4_ignition.launch.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/turtlebot4_ignition_bringup/launch/ignition.launch.py b/turtlebot4_ignition_bringup/launch/ignition.launch.py index 02bd6b5..428db02 100644 --- a/turtlebot4_ignition_bringup/launch/ignition.launch.py +++ b/turtlebot4_ignition_bringup/launch/ignition.launch.py @@ -32,7 +32,7 @@ DeclareLaunchArgument('use_sim_time', default_value='true', choices=['true', 'false'], description='use_sim_time'), - DeclareLaunchArgument('world', default_value='depot', + DeclareLaunchArgument('world', default_value='warehouse', description='Ignition World'), ] diff --git a/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py b/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py index 702d326..a874416 100644 --- a/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py +++ b/turtlebot4_ignition_bringup/launch/ros_ign_bridge.launch.py @@ -35,7 +35,7 @@ description='Ignition model name'), DeclareLaunchArgument('namespace', default_value='', description='Robot namespace'), - DeclareLaunchArgument('world', default_value='depot', + DeclareLaunchArgument('world', default_value='warehouse', description='World name'), DeclareLaunchArgument('model', default_value='standard', choices=['standard', 'lite'], diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py index e6cfb68..2f30fd2 100644 --- a/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py @@ -28,7 +28,7 @@ description='Robot namespace'), DeclareLaunchArgument('rviz', default_value='true', choices=['true', 'false'], description='Start rviz.'), - DeclareLaunchArgument('world', default_value='depot', + DeclareLaunchArgument('world', default_value='warehouse', description='Ignition World'), DeclareLaunchArgument('model', default_value='standard', choices=['standard', 'lite'], From 924761db212efa2e2d8d97ff381e10025140809d Mon Sep 17 00:00:00 2001 From: Hilary Luo Date: Thu, 6 Apr 2023 13:42:18 -0400 Subject: [PATCH 08/14] Add default model type for HMI plugin --- turtlebot4_ignition_bringup/launch/ignition.launch.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/turtlebot4_ignition_bringup/launch/ignition.launch.py b/turtlebot4_ignition_bringup/launch/ignition.launch.py index 428db02..58b3c60 100644 --- a/turtlebot4_ignition_bringup/launch/ignition.launch.py +++ b/turtlebot4_ignition_bringup/launch/ignition.launch.py @@ -34,6 +34,9 @@ description='use_sim_time'), DeclareLaunchArgument('world', default_value='warehouse', description='Ignition World'), + DeclareLaunchArgument('model', default_value='lite', + choices=['standard', 'lite'], + description='Turtlebot4 Model'), ] From 56d8eb33d33d22434dc1281ba17e8713e741cda8 Mon Sep 17 00:00:00 2001 From: Hilary Luo Date: Thu, 6 Apr 2023 14:00:30 -0400 Subject: [PATCH 09/14] Fixing linting errors --- turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py | 2 +- turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py index ae5b68e..0760848 100644 --- a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py @@ -205,7 +205,7 @@ def generate_launch_description(): output='screen', arguments=[ '0', '0', '0', - '1.5707', '-1.5707' ,'0', + '1.5707', '-1.5707', '0', 'oakd_rgb_camera_optical_frame', [robot_name, '/oakd_rgb_camera_frame/rgbd_camera'] ], diff --git a/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.cc b/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.cc index 7ff1c3f..60a6391 100644 --- a/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.cc +++ b/turtlebot4_ignition_gui_plugins/Turtlebot4Hmi/Turtlebot4Hmi.cc @@ -111,7 +111,7 @@ QString Turtlebot4Hmi::Namespace() const void Turtlebot4Hmi::SetNamespace(const QString &_name) { this->namespace_ = _name.toStdString(); - + ignmsg << "A new robot namespace has been entered: '" << this->namespace_ << " ' " < Date: Thu, 6 Apr 2023 14:20:39 -0400 Subject: [PATCH 10/14] Corrected import order --- turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py index 0760848..4afe041 100644 --- a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py @@ -17,8 +17,8 @@ from ament_index_python.packages import get_package_share_directory -from irobot_create_common_bringup.offset import OffsetParser, RotationalOffsetX, RotationalOffsetY from irobot_create_common_bringup.namespace import GetNamespacedName +from irobot_create_common_bringup.offset import OffsetParser, RotationalOffsetX, RotationalOffsetY from launch import LaunchDescription from launch.actions import DeclareLaunchArgument, GroupAction, IncludeLaunchDescription From 95139c9c647db65b705f0254c4587289bc119e08 Mon Sep 17 00:00:00 2001 From: Hilary Luo Date: Thu, 6 Apr 2023 16:03:00 -0400 Subject: [PATCH 11/14] Updated user manual link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d972c08..0d1812e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Turtlebot4 Simulation using Ignition Gazebo. -Visit the [TurtleBot 4 User Manual](https://turtlebot.github.io/turtlebot4-user-manual/software/turtlebot4_packages.html#turtlebot-4-simulator) for details. +Visit the [TurtleBot 4 User Manual](https://turtlebot.github.io/turtlebot4-user-manual/software/turtlebot4_simulator.html) for details. ## Installation ```bash From bf7076969d4ec759db2e512423c10c5cc57b1b40 Mon Sep 17 00:00:00 2001 From: Roni Kreinin Date: Mon, 10 Apr 2023 15:39:24 -0400 Subject: [PATCH 12/14] Added launch args for navigation Do not launch Rviz by default --- .../launch/turtlebot4_ignition.launch.py | 2 +- .../launch/turtlebot4_spawn.launch.py | 58 +++++++++++++++++-- turtlebot4_ignition_bringup/worlds/depot.sdf | 2 +- 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py index 2f30fd2..107a14e 100644 --- a/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_ignition.launch.py @@ -26,7 +26,7 @@ ARGUMENTS = [ DeclareLaunchArgument('namespace', default_value='', description='Robot namespace'), - DeclareLaunchArgument('rviz', default_value='true', + DeclareLaunchArgument('rviz', default_value='false', choices=['true', 'false'], description='Start rviz.'), DeclareLaunchArgument('world', default_value='warehouse', description='Ignition World'), diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py index 4afe041..a678659 100644 --- a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py @@ -30,7 +30,7 @@ ARGUMENTS = [ - DeclareLaunchArgument('rviz', default_value='true', + DeclareLaunchArgument('rviz', default_value='false', choices=['true', 'false'], description='Start rviz.'), DeclareLaunchArgument('use_sim_time', default_value='true', @@ -40,7 +40,16 @@ choices=['standard', 'lite'], description='Turtlebot4 Model'), DeclareLaunchArgument('namespace', default_value='', - description='Robot namespace') + description='Robot namespace'), + DeclareLaunchArgument('localization', default_value='false', + choices=['true', 'false'], + description='Whether to launch localization'), + DeclareLaunchArgument('slam', default_value='false', + choices=['true', 'false'], + description='Whether to launch SLAM'), + DeclareLaunchArgument('nav2', default_value='false', + choices=['true', 'false'], + description='Whether to launch Nav2'), ] for pose_element in ['x', 'y', 'z', 'yaw']: @@ -57,6 +66,8 @@ def generate_launch_description(): 'turtlebot4_description') pkg_turtlebot4_viz = get_package_share_directory( 'turtlebot4_viz') + pkg_turtlebot4_navigation = get_package_share_directory( + 'turtlebot4_navigation') pkg_irobot_create_common_bringup = get_package_share_directory( 'irobot_create_common_bringup') pkg_irobot_create_ignition_bringup = get_package_share_directory( @@ -66,7 +77,7 @@ def generate_launch_description(): turtlebot4_ros_ign_bridge_launch = PathJoinSubstitution( [pkg_turtlebot4_ignition_bringup, 'launch', 'ros_ign_bridge.launch.py']) rviz_launch = PathJoinSubstitution( - [pkg_turtlebot4_viz, 'launch', 'view_model.launch.py']) + [pkg_turtlebot4_viz, 'launch', 'view_robot.launch.py']) turtlebot4_node_launch = PathJoinSubstitution( [pkg_turtlebot4_ignition_bringup, 'launch', 'turtlebot4_nodes.launch.py']) create3_nodes_launch = PathJoinSubstitution( @@ -77,6 +88,12 @@ def generate_launch_description(): [pkg_turtlebot4_description, 'launch', 'robot_description.launch.py']) dock_description_launch = PathJoinSubstitution( [pkg_irobot_create_common_bringup, 'launch', 'dock_description.launch.py']) + localization_launch = PathJoinSubstitution( + [pkg_turtlebot4_navigation, 'launch', 'localization.launch.py']) + slam_launch = PathJoinSubstitution( + [pkg_turtlebot4_navigation, 'launch', 'slam.launch.py']) + nav2_launch = PathJoinSubstitution( + [pkg_turtlebot4_navigation, 'launch', 'nav2.launch.py']) # Parameters param_file_cmd = DeclareLaunchArgument( @@ -91,6 +108,9 @@ def generate_launch_description(): x, y, z = LaunchConfiguration('x'), LaunchConfiguration('y'), LaunchConfiguration('z') yaw = LaunchConfiguration('yaw') turtlebot4_node_yaml_file = LaunchConfiguration('param_file') + localization = LaunchConfiguration('localization') + slam = LaunchConfiguration('slam') + nav2 = LaunchConfiguration('nav2') robot_name = GetNamespacedName(namespace, 'turtlebot4') dock_name = GetNamespacedName(namespace, 'standard_dock') @@ -213,7 +233,37 @@ def generate_launch_description(): ('/tf', 'tf'), ('/tf_static', 'tf_static'), ] - ) + ), + + # Localization + IncludeLaunchDescription( + PythonLaunchDescriptionSource([localization_launch]), + launch_arguments=[ + ('namespace', namespace), + ('use_sim_time', use_sim_time) + ], + condition=IfCondition(localization) + ), + + # SLAM + IncludeLaunchDescription( + PythonLaunchDescriptionSource([slam_launch]), + launch_arguments=[ + ('namespace', namespace), + ('use_sim_time', use_sim_time) + ], + condition=IfCondition(slam) + ), + + # Nav2 + IncludeLaunchDescription( + PythonLaunchDescriptionSource([nav2_launch]), + launch_arguments=[ + ('namespace', namespace), + ('use_sim_time', use_sim_time) + ], + condition=IfCondition(nav2) + ), ]) # RViz diff --git a/turtlebot4_ignition_bringup/worlds/depot.sdf b/turtlebot4_ignition_bringup/worlds/depot.sdf index 110a4bf..af0ce8d 100644 --- a/turtlebot4_ignition_bringup/worlds/depot.sdf +++ b/turtlebot4_ignition_bringup/worlds/depot.sdf @@ -5,7 +5,7 @@ false - 0.01 + 0.003 1.0 From ea287be2223694fe170cdfbb0349606e5eb7c9b4 Mon Sep 17 00:00:00 2001 From: Hilary Luo Date: Mon, 1 May 2023 11:46:35 -0400 Subject: [PATCH 13/14] Spawn robot slightly lower to reduce the drop and rollback, ensuring the robot starts properly docked --- .../launch/turtlebot4_spawn.launch.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py index a678659..3ca036c 100644 --- a/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py +++ b/turtlebot4_ignition_bringup/launch/turtlebot4_spawn.launch.py @@ -121,6 +121,9 @@ def generate_launch_description(): # Spawn dock at robot position + rotational offset x_dock = OffsetParser(x, dock_offset_x) y_dock = OffsetParser(y, dock_offset_y) + # Spawn robot slightly clsoer to the floor to reduce the drop + # Ensures robot remains properly docked after the drop + z_robot = OffsetParser(z, -0.0025) # Rotate dock towards robot yaw_dock = OffsetParser(yaw, 3.1416) @@ -148,7 +151,7 @@ def generate_launch_description(): arguments=['-name', robot_name, '-x', x, '-y', y, - '-z', z, + '-z', z_robot, '-Y', yaw, '-topic', 'robot_description'], output='screen' From accfba66a7d9b7dca158fcab7b931ede100a1cb5 Mon Sep 17 00:00:00 2001 From: Roni Kreinin Date: Mon, 15 May 2023 16:46:20 -0400 Subject: [PATCH 14/14] Removed lighting from warehouse temporarily as it causes the sim to crash when multiple robots are spawned. --- turtlebot4_ignition_bringup/worlds/warehouse.sdf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/turtlebot4_ignition_bringup/worlds/warehouse.sdf b/turtlebot4_ignition_bringup/worlds/warehouse.sdf index 6a36bb2..4acac6d 100644 --- a/turtlebot4_ignition_bringup/worlds/warehouse.sdf +++ b/turtlebot4_ignition_bringup/worlds/warehouse.sdf @@ -9,7 +9,6 @@ - 1 1 1 1 0.3 0.7 0.9 1 @@ -17,13 +16,14 @@ false - + + true