diff --git a/README.md b/README.md index 6e6159b4..a5e46bd9 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,6 @@ Launch arguments are largely common to both simulation and physical robot. Howev | 🤖 | 🖥️ | Argument | Description
***Type:*** `Default` | | --- | --- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| ❌ | ✅ | `add_wheel_joints` | Flag enabling joint_state_publisher to publish information about the wheel position. Should be false when there is a controller that sends this information.
***bool:*** `False` | | ❌ | ✅ | `add_world_transform` | Adds a world frame that connects the tf trees of individual robots (useful when running multiple robots).
***bool:*** `False` | | ✅ | ✅ | `animations_config_path` | Path to a YAML file with a description of led configuration. This file includes definition of robot panels, virtual segments and default animations.
***string:*** [`{robot_model}_animations.yaml`](./husarion_ugv_lights/config) | | ❌ | ✅ | `battery_config_path` | Path to the Ignition LinearBatteryPlugin configuration file. This configuration is intended for use in simulations only.
***string:*** `None` | @@ -108,6 +107,8 @@ Launch arguments are largely common to both simulation and physical robot. Howev | ✅ | ✅ | `safety_bt_project_path` | Path to BehaviorTree project file, responsible for safety and shutdown management.
***string:*** [`SafetyBT.btproj`](./husarion_ugv_manager/behavior_trees/SafetyBT.btproj) | | ✅ | ✅ | `shutdown_hosts_config_path` | Path to file with list of hosts to request shutdown.
***string:*** [`shutdown_hosts.yaml`](./husarion_ugv_manager/config/shutdown_hosts.yaml) | | ✅ | ✅ | `use_ekf` | Enable or disable EKF.
***bool:*** `True` | +| ❌ | ✅ | `use_joint_state_publisher` | Flag enabling joint_state_publisher to publish information about the wheel position. Should be false when there is a controller that sends this information.
***bool:*** `False` | +| ❌ | ✅ | `use_joint_state_publisher_gui` | Flag enabling joint_state_publisher_gui to publish information about the wheel position. Should be false when there is a controller that sends this information.
***bool:*** `False` | | ❌ | ✅ | `use_rviz` | Run RViz simultaneously.
***bool:*** `True` | | ✅ | ✅ | `use_sim` | Whether simulation is used.
***bool:*** `False` | | ✅ | ✅ | `user_led_animations_path` | Path to a YAML file with a description of the user-defined animations.
***string:*** `''` | diff --git a/husarion_ugv_description/CONFIGURATION.md b/husarion_ugv_description/CONFIGURATION.md new file mode 100644 index 00000000..c1c7e8b0 --- /dev/null +++ b/husarion_ugv_description/CONFIGURATION.md @@ -0,0 +1,69 @@ +# husarion_ugv_description + +## URDF - Robot Model Configuration + +### Configure Components + +Create `components.yaml` file with the desired components. Here's a sample configuration: + +```yaml +components: + - type: MAN02 + parent_link: cover_link + xyz: 0.2 -0.2 0.0 + rpy: 0.0 0.0 0.0 + device_namespace: ur5 +``` + +In this example: + - `type`: MAN02: Specifies the component type. + - `parent_link`: cover_link: Defines the parent link to attach the component. + - `xyz`: 0.2 -0.2 0.0: Sets the position of the component. + - `rpy`: 0.0 0.0 0.0: Sets the rotation of the component. + - `device_namespace`: ur5: Sets the device namespace. + +### Visualize Robot Model Configuration + +To use the `ros2 launch` command to launch the `visualize_fake_robot.launch.py` file with a specified robot model and components configuration path, follow these steps: + +1. Open a terminal. +2. Source build workspace. +3. Execute the following command: + +```bash +ros2 launch husarion_ugv_description visualize_fake_robot.launch.py robot_model:=lynx use_joint_state_publisher:=true components_config_path:=$(pwd)/components.yaml +``` + +If you want to move the wheels or move the manipulator you can run the launch file with `joint_state_publisher_gui`: + +```bash +ros2 launch husarion_ugv_description visualize_fake_robot.launch.py robot_model:=lynx use_joint_state_publisher_gui:=true components_config_path:=$(pwd)/components.yaml +``` + +### Overwrite Robot Model Configuration + +To change the configuration let's add another manipulator to `components.yaml`: + +```yaml +components: + - type: MAN02 + parent_link: cover_link + xyz: 0.2 -0.2 0.0 + rpy: 0.0 0.0 0.0 + device_namespace: left_ur5 + - type: MAN02 + parent_link: cover_link + xyz: 0.2 0.2 0.0 + rpy: 0.0 0.0 0.0 + device_namespace: right_ur5 +``` + +To use the `ros2 launch` command to launch the `overwrite_robot_description.launch.py` file with the appropriate arguments to overwrite the robot model, follow these steps: + +1. Open a terminal. +2. Source workspace. +3. Execute the following command: + +```bash +ros2 launch husarion_ugv_description overwrite_robot_description.launch.py robot_model:=lynx components_config_path:=$(pwd)/components.yaml +``` diff --git a/husarion_ugv_description/launch/load_urdf.launch.py b/husarion_ugv_description/launch/load_urdf.launch.py index 9347553f..c4acc0c4 100644 --- a/husarion_ugv_description/launch/load_urdf.launch.py +++ b/husarion_ugv_description/launch/load_urdf.launch.py @@ -19,7 +19,6 @@ from launch import LaunchDescription from launch.actions import DeclareLaunchArgument -from launch.conditions import IfCondition from launch.substitutions import ( Command, EnvironmentVariable, @@ -33,15 +32,6 @@ def generate_launch_description(): - add_wheel_joints = LaunchConfiguration("add_wheel_joints") - declared_add_wheel_joints_arg = DeclareLaunchArgument( - "add_wheel_joints", - default_value="True", - description="Flag enabling joint_state_publisher to publish information about the wheel " - "position. Should be false when there is a controller that sends this information.", - choices=["True", "true", "False", "false"], - ) - battery_config_path = LaunchConfiguration("battery_config_path") declare_battery_config_path_arg = DeclareLaunchArgument( "battery_config_path", @@ -183,16 +173,7 @@ def generate_launch_description(): emulate_tty=True, ) - joint_state_publisher_node = Node( - package="joint_state_publisher", - executable="joint_state_publisher", - namespace=namespace, - emulate_tty=True, - condition=IfCondition(add_wheel_joints), - ) - actions = [ - declared_add_wheel_joints_arg, declare_battery_config_path_arg, declare_components_config_path_arg, declare_robot_model_arg, # robot_model is used by wheel_type @@ -203,7 +184,6 @@ def generate_launch_description(): declare_wheel_config_path_arg, SetParameter(name="use_sim_time", value=use_sim), robot_state_pub_node, - joint_state_publisher_node, # do not publish, when use_sim is true ] return LaunchDescription(actions) diff --git a/husarion_ugv_description/launch/visualize_fake_robot.launch.py b/husarion_ugv_description/launch/visualize_fake_robot.launch.py new file mode 100644 index 00000000..236eb897 --- /dev/null +++ b/husarion_ugv_description/launch/visualize_fake_robot.launch.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 + +# Copyright 2020 ros2_control Development Team +# Copyright 2024 Husarion sp. z o.o. +# +# 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. + +import os + +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription +from launch.conditions import IfCondition +from launch.launch_description_sources import PythonLaunchDescriptionSource +from launch.substitutions import ( + EnvironmentVariable, + LaunchConfiguration, + PathJoinSubstitution, + PythonExpression, +) +from launch_ros.actions import Node +from launch_ros.substitutions import FindPackageShare + + +def generate_launch_description(): + components_config_path = LaunchConfiguration("components_config_path") + declare_components_config_path_arg = DeclareLaunchArgument( + "components_config_path", + default_value=PathJoinSubstitution( + [FindPackageShare("husarion_ugv_description"), "config", "components.yaml"] + ), + description=( + "Additional components configuration file. Components described in this file " + "are dynamically included in Panther's urdf." + "Panther options are described here " + "https://husarion.com/manuals/panther/panther-options/" + ), + ) + + namespace = LaunchConfiguration("namespace") + declare_namespace_arg = DeclareLaunchArgument( + "namespace", + default_value=EnvironmentVariable("ROBOT_NAMESPACE", default_value=""), + description="Add namespace to all launched nodes.", + ) + + robot_model = LaunchConfiguration("robot_model") + robot_model_dict = {"LNX": "lynx", "PTH": "panther"} + robot_model_env = os.environ.get("ROBOT_MODEL", default="PTH") + declare_robot_model_arg = DeclareLaunchArgument( + "robot_model", + default_value=robot_model_dict[robot_model_env], + description="Specify robot model.", + choices=["lynx", "panther"], + ) + + rviz_config = LaunchConfiguration("rviz_config") + declare_rviz_config_arg = DeclareLaunchArgument( + "rviz_config", + default_value=PathJoinSubstitution( + [FindPackageShare("husarion_ugv_description"), "rviz", "robot_model.rviz"] + ), + description="RViz configuration file.", + ) + + use_joint_state_publisher = LaunchConfiguration("use_joint_state_publisher") + declare_use_joint_state_publisher_arg = DeclareLaunchArgument( + "use_joint_state_publisher", + default_value="False", + description="Flag enabling joint_state_publisher to publish information about joints positions. Should be false when there is a controller that sends this information.", + choices=["True", "true", "False", "false"], + ) + + use_joint_state_publisher_gui = LaunchConfiguration("use_joint_state_publisher_gui") + declare_use_joint_state_publisher_gui_arg = DeclareLaunchArgument( + "use_joint_state_publisher_gui", + default_value="False", + description="Flag enabling joint_state_publisher_gui to publish information about joints positions. Should be false when there is a controller that sends this information.", + choices=["True", "true", "False", "false"], + ) + + wheel_type = LaunchConfiguration("wheel_type") + default_wheel_type = {"lynx": "WH05", "panther": "WH01"} + declare_wheel_type_arg = DeclareLaunchArgument( + "wheel_type", + default_value=PythonExpression([f"{default_wheel_type}['", robot_model, "']"]), + description=( + "Specify the wheel type. If the selected wheel type is not 'custom', " + "the 'wheel_config_path' and 'controller_config_path' arguments will be " + "automatically adjusted and can be omitted." + ), + choices=["WH01", "WH02", "WH04", "WH05", "custom"], + ) + + load_urdf = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [FindPackageShare("husarion_ugv_description"), "/launch/load_urdf.launch.py"] + ), + launch_arguments={ + "components_config_path": components_config_path, + "namespace": namespace, + "robot_model": robot_model, + "wheel_type": wheel_type, + }.items(), + ) + + rviz = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + [FindPackageShare("husarion_ugv_description"), "/launch/rviz.launch.py"] + ), + launch_arguments={"namespace": namespace, "rviz_config": rviz_config}.items(), + ) + + joint_state_publisher_node = Node( + package="joint_state_publisher", + executable="joint_state_publisher", + namespace=namespace, + emulate_tty=True, + condition=IfCondition(use_joint_state_publisher), + ) + + joint_state_publisher_gui_node = Node( + package="joint_state_publisher_gui", + executable="joint_state_publisher_gui", + namespace=namespace, + emulate_tty=True, + condition=IfCondition(use_joint_state_publisher_gui), + ) + + actions = [ + declare_components_config_path_arg, + declare_namespace_arg, + declare_robot_model_arg, + declare_rviz_config_arg, + declare_use_joint_state_publisher_arg, + declare_use_joint_state_publisher_gui_arg, + declare_wheel_type_arg, + load_urdf, + rviz, + joint_state_publisher_node, + joint_state_publisher_gui_node, + ] + + return LaunchDescription(actions) diff --git a/husarion_ugv_description/package.xml b/husarion_ugv_description/package.xml index 5712cdfd..481d035d 100644 --- a/husarion_ugv_description/package.xml +++ b/husarion_ugv_description/package.xml @@ -20,6 +20,7 @@ ament_cmake joint_state_publisher + joint_state_publisher_gui launch launch_ros nav2_common diff --git a/husarion_ugv_description/rviz/robot_model.rviz b/husarion_ugv_description/rviz/robot_model.rviz new file mode 100644 index 00000000..73166d19 --- /dev/null +++ b/husarion_ugv_description/rviz/robot_model.rviz @@ -0,0 +1,233 @@ +Panels: + - Class: rviz_common/Displays + Help Height: 85 + Name: Displays + Property Tree Widget: + Expanded: + - /Status1 + Splitter Ratio: 0.5 + Tree Height: 692 + - Class: rviz_common/Selection + Name: Selection + - Class: rviz_common/Tool Properties + Expanded: + - /2D Goal Pose1 + - /Publish Point1 + Name: Tool Properties + Splitter Ratio: 0.5886790156364441 + - Class: rviz_common/Views + Expanded: + - /Current View1 + Name: Views + Splitter Ratio: 0.5 + - Class: rviz_common/Time + Experimental: false + Name: Time + SyncMode: 0 + SyncSource: "" +Visualization Manager: + Class: "" + Displays: + - Class: rviz_common/Group + Displays: + - Alpha: 0.5 + Cell Size: 1 + Class: rviz_default_plugins/Grid + Color: 160; 160; 164 + Enabled: true + Line Style: + Line Width: 0.029999999329447746 + Value: Lines + Name: Grid + Normal Cell Count: 0 + Offset: + X: 0 + Y: 0 + Z: 0 + Plane: XY + Plane Cell Count: 10 + Reference Frame: + Value: true + Enabled: true + Name: Map + - Class: rviz_common/Group + Displays: + - Alpha: 1 + Class: rviz_default_plugins/RobotModel + Collision Enabled: false + Description File: "" + Description Source: Topic + Description Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: robot_description + Enabled: true + Links: + All Links Enabled: true + Expand Joint Details: false + Expand Link Details: false + Expand Tree: false + Link Tree Style: Links in Alphabetic Order + base_link: + Alpha: 1 + Show Axes: false + Show Trail: false + body_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + cover_link: + Alpha: 1 + Show Axes: false + Show Trail: false + fl_wheel_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + fr_wheel_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + front_bumper_link: + Alpha: 1 + Show Axes: false + Show Trail: false + imu_link: + Alpha: 1 + Show Axes: false + Show Trail: false + lights_channel_1_link: + Alpha: 1 + Show Axes: false + Show Trail: false + lights_channel_2_link: + Alpha: 1 + Show Axes: false + Show Trail: false + rear_bumper_link: + Alpha: 1 + Show Axes: false + Show Trail: false + rl_wheel_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + rr_wheel_link: + Alpha: 1 + Show Axes: false + Show Trail: false + Value: true + Mass Properties: + Inertia: false + Mass: false + Name: RobotModel + TF Prefix: "" + Update Interval: 0 + Value: true + Visual Enabled: true + - Class: rviz_default_plugins/TF + Enabled: false + Frame Timeout: 15 + Frames: + All Enabled: true + Marker Scale: 1 + Name: TF + Show Arrows: true + Show Axes: true + Show Names: false + Tree: + {} + Update Interval: 0 + Value: false + Enabled: true + Name: Robot + Enabled: true + Global Options: + Background Color: 48; 48; 48 + Fixed Frame: base_link + Frame Rate: 30 + Name: root + Tools: + - Class: rviz_default_plugins/Interact + Hide Inactive Objects: true + - Class: rviz_default_plugins/MoveCamera + - Class: rviz_default_plugins/Select + - Class: rviz_default_plugins/FocusCamera + - Class: rviz_default_plugins/Measure + Line color: 128; 128; 0 + - Class: rviz_default_plugins/SetInitialPose + Covariance x: 0.25 + Covariance y: 0.25 + Covariance yaw: 0.06853891909122467 + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: initialpose + - Class: rviz_default_plugins/SetGoal + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: goal_pose + - Class: rviz_default_plugins/PublishPoint + Single click: true + Topic: + Depth: 5 + Durability Policy: Volatile + History Policy: Keep Last + Reliability Policy: Reliable + Value: clicked_point + Transformation: + Current: + Class: rviz_default_plugins/TF + Value: true + Views: + Current: + Class: rviz_default_plugins/Orbit + Distance: 2.1199140548706055 + Enable Stereo Rendering: + Stereo Eye Separation: 0.05999999865889549 + Stereo Focal Distance: 1 + Swap Stereo Eyes: false + Value: false + Focal Point: + X: 0.13748444616794586 + Y: 0.210101917386055 + Z: 0.22006787359714508 + Focal Shape Fixed Size: false + Focal Shape Size: 0.05000000074505806 + Invert Z Axis: false + Name: Current View + Near Clip Distance: 0.009999999776482582 + Pitch: 0.49539831280708313 + Target Frame: + Value: Orbit (rviz) + Yaw: 0.8653994202613831 + Saved: ~ +Window Geometry: + Displays: + collapsed: false + Height: 1009 + Hide Left Dock: false + Hide Right Dock: true + QMainWindow State: 000000ff00000000fd00000004000000000000015a0000034afc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000006b00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c00610079007301000000440000034a000000eb00fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f0000035afc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d0000035a000000b900fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e100000197000000030000073a0000003efc0100000002fb0000000800540069006d006501000000000000073a000002d200fffffffb0000000800540069006d00650100000000000004500000000000000000000005d90000034a00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 + Selection: + collapsed: false + Time: + collapsed: false + Tool Properties: + collapsed: false + Views: + collapsed: true + Width: 1850 + X: 70 + Y: 34 diff --git a/husarion_ugv_gazebo/launch/simulate_robot.launch.py b/husarion_ugv_gazebo/launch/simulate_robot.launch.py index 9fd37809..f21e0148 100644 --- a/husarion_ugv_gazebo/launch/simulate_robot.launch.py +++ b/husarion_ugv_gazebo/launch/simulate_robot.launch.py @@ -106,7 +106,6 @@ def generate_launch_description(): ) ), launch_arguments={ - "add_wheel_joints": "False", "namespace": namespace, "robot_model": robot_model, }.items(), diff --git a/husarion_ugv_gazebo/launch/spawn_robot.launch.py b/husarion_ugv_gazebo/launch/spawn_robot.launch.py index 77527036..2c0480d3 100644 --- a/husarion_ugv_gazebo/launch/spawn_robot.launch.py +++ b/husarion_ugv_gazebo/launch/spawn_robot.launch.py @@ -88,7 +88,6 @@ def generate_launch_description(): ) ), launch_arguments={ - "add_wheel_joints": LaunchConfiguration("add_wheel_joints", default="True"), "namespace": namespace, "robot_model": robot_model, "use_sim": "True",