2025-03-08 11:45:28 +00:00
|
|
|
import os
|
|
|
|
|
import re
|
|
|
|
|
import subprocess
|
|
|
|
|
|
|
|
|
|
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.conditions import IfCondition
|
|
|
|
|
from launch.conditions import UnlessCondition
|
|
|
|
|
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
|
|
|
|
from launch.substitutions import LaunchConfiguration
|
|
|
|
|
from launch.substitutions import PathJoinSubstitution
|
|
|
|
|
|
|
|
|
|
from launch_ros.actions import Node
|
|
|
|
|
from launch_ros.substitutions import FindPackageShare
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate_launch_description():
|
2025-03-11 04:06:46 +00:00
|
|
|
resources_package = "openarm_description"
|
2025-03-08 11:45:28 +00:00
|
|
|
|
|
|
|
|
# Make path to resources dir without last package_name fragment.
|
2025-03-11 04:06:46 +00:00
|
|
|
path_to_share_dir_clipped = "".join(
|
|
|
|
|
get_package_share_directory(resources_package).rsplit("/" + resources_package, 1)
|
|
|
|
|
)
|
2025-03-08 11:45:28 +00:00
|
|
|
|
|
|
|
|
# Gazebo hint for resources.
|
2025-03-11 04:06:46 +00:00
|
|
|
os.environ["GZ_SIM_RESOURCE_PATH"] = path_to_share_dir_clipped
|
2025-03-08 11:45:28 +00:00
|
|
|
|
|
|
|
|
# Ensure `SDF_PATH` is populated since `sdformat_urdf` uses this rather
|
|
|
|
|
|
|
|
|
|
# than `GZ_SIM_RESOURCE_PATH` to locate resources.
|
|
|
|
|
if "GZ_SIM_RESOURCE_PATH" in os.environ:
|
|
|
|
|
gz_sim_resource_path = os.environ["GZ_SIM_RESOURCE_PATH"]
|
|
|
|
|
|
|
|
|
|
if "SDF_PATH" in os.environ:
|
|
|
|
|
sdf_path = os.environ["SDF_PATH"]
|
|
|
|
|
os.environ["SDF_PATH"] = sdf_path + ":" + gz_sim_resource_path
|
|
|
|
|
else:
|
|
|
|
|
os.environ["SDF_PATH"] = gz_sim_resource_path
|
|
|
|
|
|
2025-03-11 04:06:46 +00:00
|
|
|
use_custom_world = LaunchConfiguration("use_custom_world")
|
|
|
|
|
use_custom_world_launch_arg = DeclareLaunchArgument("use_custom_world", default_value="true")
|
|
|
|
|
gazebo_world = LaunchConfiguration("gazebo_world")
|
|
|
|
|
gazebo_world_launch_arg = DeclareLaunchArgument("gazebo_world", default_value="empty.sdf")
|
2025-03-08 11:45:28 +00:00
|
|
|
|
|
|
|
|
# prepare custom world
|
2025-03-11 04:06:46 +00:00
|
|
|
world = os.getenv("GZ_SIM_WORLD", "empty")
|
|
|
|
|
fly_world_path = resources_package + "/worlds/" + world + ".sdf"
|
2025-03-08 11:45:28 +00:00
|
|
|
gz_version = subprocess.getoutput("gz sim --versions")
|
2025-03-11 04:06:46 +00:00
|
|
|
gz_version_major = re.search(r"^\d{1}", gz_version).group()
|
|
|
|
|
launch_arguments = dict(
|
|
|
|
|
gz_args="-r " + str(fly_world_path) + " --verbose ", gz_version=gz_version_major
|
|
|
|
|
).items()
|
2025-03-08 11:45:28 +00:00
|
|
|
|
|
|
|
|
# Gazebo Sim.
|
|
|
|
|
# by default the custom world is used, otherwise the gazebo world is used, which can be changed with the argument
|
2025-03-11 04:06:46 +00:00
|
|
|
pkg_ros_gz_sim = get_package_share_directory("ros_gz_sim")
|
2025-03-08 11:45:28 +00:00
|
|
|
gazebo = IncludeLaunchDescription(
|
|
|
|
|
PythonLaunchDescriptionSource(
|
2025-03-11 04:06:46 +00:00
|
|
|
os.path.join(pkg_ros_gz_sim, "launch", "gz_sim.launch.py"),
|
2025-03-08 11:45:28 +00:00
|
|
|
),
|
2025-03-11 04:06:46 +00:00
|
|
|
launch_arguments=launch_arguments
|
|
|
|
|
if use_custom_world
|
|
|
|
|
else dict(gz_args="-r " + gazebo_world + " --verbose").items(),
|
2025-03-08 11:45:28 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Spawn
|
|
|
|
|
spawn = Node(
|
2025-03-11 04:06:46 +00:00
|
|
|
package="ros_gz_sim",
|
|
|
|
|
executable="create",
|
|
|
|
|
arguments=[
|
|
|
|
|
"-name",
|
|
|
|
|
"openarm",
|
|
|
|
|
"-x",
|
|
|
|
|
"1.2",
|
|
|
|
|
"-z",
|
|
|
|
|
"2.3",
|
|
|
|
|
"-Y",
|
|
|
|
|
"3.4",
|
|
|
|
|
"-topic",
|
|
|
|
|
"/robot_description",
|
|
|
|
|
],
|
|
|
|
|
output="screen",
|
2025-03-08 11:45:28 +00:00
|
|
|
)
|
|
|
|
|
|
2025-03-11 04:06:46 +00:00
|
|
|
use_sim_time = LaunchConfiguration("use_sim_time")
|
|
|
|
|
use_sim_time_launch_arg = DeclareLaunchArgument("use_sim_time", default_value="true")
|
|
|
|
|
use_rviz = LaunchConfiguration("use_rviz")
|
|
|
|
|
use_rviz_arg = DeclareLaunchArgument("use_rviz", default_value="true")
|
2025-03-08 11:45:28 +00:00
|
|
|
|
|
|
|
|
robot_state_publisher = IncludeLaunchDescription(
|
2025-03-11 04:06:46 +00:00
|
|
|
PythonLaunchDescriptionSource(
|
|
|
|
|
[
|
|
|
|
|
PathJoinSubstitution(
|
|
|
|
|
[
|
|
|
|
|
FindPackageShare(resources_package),
|
|
|
|
|
"launch",
|
|
|
|
|
"description.launch.py",
|
|
|
|
|
]
|
|
|
|
|
),
|
|
|
|
|
]
|
|
|
|
|
),
|
|
|
|
|
condition=UnlessCondition(use_rviz), # rviz launch includes rsp.
|
|
|
|
|
launch_arguments=dict(use_sim_time=use_sim_time).items(),
|
2025-03-08 11:45:28 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
rviz = IncludeLaunchDescription(
|
2025-03-11 04:06:46 +00:00
|
|
|
PythonLaunchDescriptionSource(
|
|
|
|
|
[
|
|
|
|
|
PathJoinSubstitution(
|
|
|
|
|
[
|
|
|
|
|
FindPackageShare(resources_package),
|
|
|
|
|
"launch",
|
|
|
|
|
"display.launch.py",
|
|
|
|
|
]
|
|
|
|
|
),
|
|
|
|
|
]
|
|
|
|
|
),
|
2025-03-08 11:45:28 +00:00
|
|
|
condition=IfCondition(use_rviz),
|
|
|
|
|
launch_arguments=dict(use_sim_time=use_sim_time).items(),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
gz_bridge = Node(
|
2025-03-11 04:06:46 +00:00
|
|
|
package="ros_gz_bridge",
|
|
|
|
|
executable="parameter_bridge",
|
|
|
|
|
arguments=["/clock@rosgraph_msgs/msg/Clock[ignition.msgs.Clock"],
|
|
|
|
|
output="screen",
|
|
|
|
|
parameters=[
|
|
|
|
|
{
|
|
|
|
|
"use_sim_time": use_sim_time,
|
|
|
|
|
}
|
|
|
|
|
],
|
2025-03-08 11:45:28 +00:00
|
|
|
)
|
|
|
|
|
|
2025-03-11 04:06:46 +00:00
|
|
|
return LaunchDescription(
|
|
|
|
|
[
|
|
|
|
|
use_sim_time_launch_arg,
|
|
|
|
|
use_rviz_arg,
|
|
|
|
|
use_custom_world_launch_arg,
|
|
|
|
|
gazebo_world_launch_arg,
|
|
|
|
|
robot_state_publisher,
|
|
|
|
|
rviz,
|
|
|
|
|
gazebo,
|
|
|
|
|
spawn,
|
|
|
|
|
gz_bridge,
|
|
|
|
|
]
|
|
|
|
|
)
|