diff --git a/README.md b/README.md index 6e85f20..3ec6ef9 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,8 @@ ```zsh ros2 launch pb2025_nav_bringup rm_sentry_reality_launch.py \ world:= \ - slam:=True + slam:=False \ + use_robot_state_pub:=True ``` #### 参数说明 @@ -155,6 +156,15 @@ 2. 自动覆写 point_lio 参数 `pcd_save.pcd_save_en` 为 True,以便保存点云文件。 +- `use_robot_state_pub`: 是否使用 `robot_state_publisher` 发布机器人的 TF 信息。 + + 1. 在仿真环境中,由于配套的 Gazebo 仿真器已经发布了机器人的 TF 信息,故不需要再次发布。 + + 2. 在真实环境中,我们**更推荐**使用独立的功能包发布机器人的 TF 信息,例如由上下位机串口通讯模块提供 gimbal_yaw 和 gimbal_pitch 的关节位姿,此时应将 `use_robot_state_pub` 设置为 False。 + + 如果没有完整的机器人系统,仅测试导航模块时,可将 `use_robot_state_pub` 设置为 True,此时导航模块会发布静态的机器人关节位姿数据以维护 TF 树。 + 注:需要额外克隆并编译 [pb2025_robot_description](https://github.com/SMBU-PolarBear-Robot-Team/pb2025_robot_description.git) + ### 3.2 CMU Navigation Demo(停止维护) > [!NOTE] diff --git a/pb2025_nav_bringup/launch/rm_sentry_reality_launch.py b/pb2025_nav_bringup/launch/rm_sentry_reality_launch.py index 51ea15a..eb269a6 100644 --- a/pb2025_nav_bringup/launch/rm_sentry_reality_launch.py +++ b/pb2025_nav_bringup/launch/rm_sentry_reality_launch.py @@ -7,7 +7,6 @@ from launch.launch_description_sources import PythonLaunchDescriptionSource from launch.substitutions import LaunchConfiguration from launch_ros.actions import Node -from sdformat_tools.urdf_generator import UrdfGenerator def generate_launch_description(): @@ -30,16 +29,9 @@ def generate_launch_description(): # Launch configuration variables specific to simulation rviz_config_file = LaunchConfiguration("rviz_config_file") + use_robot_state_pub = LaunchConfiguration("use_robot_state_pub") use_rviz = LaunchConfiguration("use_rviz") - pkg_simulator = get_package_share_directory("rmul24_gazebo_simulator") - robot_sdf_path = os.path.join( - pkg_simulator, "resource", "xmacro", "rmul24_sentry_robot.sdf" - ) - urdf_generator = UrdfGenerator() - urdf_generator.parse_from_sdf_file(robot_sdf_path) - robot_urdf_xml = urdf_generator.to_string() - # Map fully qualified names to relative ones so the node's namespace can be prepended. # In case of the transforms (tf), currently, there doesn't seem to be a better alternative # https://github.com/ros/geometry2/issues/32 @@ -117,6 +109,12 @@ def generate_launch_description(): description="Whether to respawn if a node crashes. Applied when composition is disabled.", ) + declare_use_robot_state_pub_cmd = DeclareLaunchArgument( + "use_robot_state_pub", + default_value="False", + description="Whether to start the robot state publisher", + ) + declare_rviz_config_file_cmd = DeclareLaunchArgument( "rviz_config_file", default_value=os.path.join(bringup_dir, "rviz", "nav2_namespaced_view.rviz"), @@ -127,27 +125,17 @@ def generate_launch_description(): "use_rviz", default_value="True", description="Whether to start RVIZ" ) - start_joint_state_publisher_cmd = Node( - package="joint_state_publisher", - executable="joint_state_publisher", - name="joint_state_publisher", - output="screen", - namespace=namespace, - # TODO: Using serial_driver to publish `gimbal_yaw` and `gimbal_pitch` joint. - # parameters=[{"source_list": [""]}], - remappings=remappings, - ) - - start_robot_state_publisher_cmd = Node( - package="robot_state_publisher", - executable="robot_state_publisher", - name="robot_state_publisher", - output="screen", - namespace=namespace, - parameters=[ - {"use_sim_time": use_sim_time, "robot_description": robot_urdf_xml} - ], - remappings=remappings, + start_robot_state_publisher_cmd = IncludeLaunchDescription( + PythonLaunchDescriptionSource( + os.path.join(launch_dir, "rm_sentry_state_publisher_launch.py") + ), + # NOTE: This startup file is only used when the navigation module is standalone + condition=IfCondition(use_robot_state_pub), + launch_arguments={ + "namespace": namespace, + "use_namespace": use_namespace, + "use_sim_time": use_sim_time, + }.items(), ) start_livox_ros_driver2_node = Node( @@ -224,11 +212,11 @@ def generate_launch_description(): ld.add_action(declare_autostart_cmd) ld.add_action(declare_use_composition_cmd) ld.add_action(declare_rviz_config_file_cmd) + ld.add_action(declare_use_robot_state_pub_cmd) ld.add_action(declare_use_rviz_cmd) ld.add_action(declare_use_respawn_cmd) # Add the actions to launch all of the navigation nodes - ld.add_action(start_joint_state_publisher_cmd) ld.add_action(start_robot_state_publisher_cmd) ld.add_action(start_livox_ros_driver2_node) ld.add_action(bringup_cmd) diff --git a/pb2025_nav_bringup/launch/rm_sentry_state_publisher_launch.py b/pb2025_nav_bringup/launch/rm_sentry_state_publisher_launch.py new file mode 100644 index 0000000..6ca4686 --- /dev/null +++ b/pb2025_nav_bringup/launch/rm_sentry_state_publisher_launch.py @@ -0,0 +1,123 @@ +# NOTE: This startup file is only used when the navigation module is standalone +# It is used to launch the robot state publisher and joint state publisher. +# But in a complete robot system, this part should be completed by an independent robot startup module + +import os + +from ament_index_python.packages import get_package_share_directory +from launch import LaunchDescription +from launch.actions import DeclareLaunchArgument, GroupAction +from launch.conditions import IfCondition +from launch.substitutions import LaunchConfiguration +from launch_ros.actions import Node, PushRosNamespace +from sdformat_tools.urdf_generator import UrdfGenerator +from xmacro.xmacro4sdf import XMLMacro4sdf + + +def generate_launch_description(): + # Get the launch directory + pkg_pb2025_robot_description_dir = get_package_share_directory( + "pb2025_robot_description" + ) + + namespace = LaunchConfiguration("namespace") + use_namespace = LaunchConfiguration("use_namespace") + use_sim_time = LaunchConfiguration("use_sim_time") + # xmacro_description = LaunchConfiguration("xmacro_description") + xmacro_description = os.path.join( + pkg_pb2025_robot_description_dir, + "resource", + "xmacro", + "pb2025_sentry_robot.sdf.xmacro", + ) + + # Map fully qualified names to relative ones so the node's namespace can be prepended. + # In case of the transforms (tf), currently, there doesn't seem to be a better alternative + # https://github.com/ros/geometry2/issues/32 + # https://github.com/ros/robot_state_publisher/pull/30 + # TODO(orduno) Substitute with `PushNodeRemapping` + # https://github.com/ros2/launch_ros/issues/56 + remappings = [("/tf", "tf"), ("/tf_static", "tf_static")] + + # Declare the launch arguments + declare_namespace_cmd = DeclareLaunchArgument( + "namespace", + default_value="", + description="Top-level namespace", + ) + + declare_use_namespace_cmd = DeclareLaunchArgument( + "use_namespace", + default_value="false", + description="Whether to apply a namespace to the navigation stack", + ) + + declare_use_sim_time_cmd = DeclareLaunchArgument( + "use_sim_time", + default_value="false", + description="Use simulation (Gazebo) clock if true", + ) + + # declare_xmacro_description_cmd = DeclareLaunchArgument( + # "xmacro_description", + # default_value=os.path.join( + # pkg_pb2025_robot_description_dir, + # "resource", + # "xmacro", + # "rmul24_sentry_robot.sdf.xmacro", + # ), + # description="Robot description in xmacro format", + # ) + + xmacro = XMLMacro4sdf() + xmacro.set_xml_file(xmacro_description) + + # Generate SDF from xmacro + xmacro.generate() + robot_xml = xmacro.to_string() + + # Generate URDF from SDF + urdf_generator = UrdfGenerator() + urdf_generator.parse_from_sdf_string(robot_xml) + robot_urdf_xml = urdf_generator.to_string() + + bringup_cmd_group = GroupAction( + [ + PushRosNamespace(condition=IfCondition(use_namespace), namespace=namespace), + Node( + package="joint_state_publisher", + executable="joint_state_publisher", + name="joint_state_publisher", + output="screen", + # TODO: Using serial_driver to publish `gimbal_yaw` and `gimbal_pitch` joint. + # parameters=[{"source_list": [""]}], + remappings=remappings, + ), + Node( + package="robot_state_publisher", + executable="robot_state_publisher", + name="robot_state_publisher", + remappings=remappings, + parameters=[ + { + "use_sim_time": use_sim_time, + "robot_description": robot_urdf_xml, + } + ], + ), + ] + ) + + # Create the launch description and populate + ld = LaunchDescription() + + # Declare the launch options + ld.add_action(declare_namespace_cmd) + ld.add_action(declare_use_namespace_cmd) + ld.add_action(declare_use_sim_time_cmd) + # ld.add_action(declare_xmacro_description_cmd) + + # Add the actions to launch all nodes + ld.add_action(bringup_cmd_group) + + return ld diff --git a/small_gicp_relocalization b/small_gicp_relocalization index fb57a13..b950087 160000 --- a/small_gicp_relocalization +++ b/small_gicp_relocalization @@ -1 +1 @@ -Subproject commit fb57a13042534cc8b71aedae2dd6115cd4ebea76 +Subproject commit b950087595d32e1ff642cbb428f428b39e088eae