diff --git a/robot/Dockerfile b/robot/Dockerfile index 48efa03..da98bfc 100644 --- a/robot/Dockerfile +++ b/robot/Dockerfile @@ -7,6 +7,7 @@ SHELL ["/bin/bash", "-c"] RUN apt-get update && apt-get install -y --no-install-recommends \ python3-colcon-common-extensions \ + ros-${ROS_DISTRO}-xacro \ && rm -rf /var/lib/apt/lists/* WORKDIR /ws @@ -26,6 +27,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ ros-${ROS_DISTRO}-std-msgs \ ros-${ROS_DISTRO}-sensor-msgs \ ros-${ROS_DISTRO}-launch-ros \ + ros-${ROS_DISTRO}-robot-state-publisher \ + ros-${ROS_DISTRO}-xacro \ + ros-${ROS_DISTRO}-tf2-ros \ python3-smbus \ && rm -rf /var/lib/apt/lists/* diff --git a/robot/src/raspbot_v2/launch/robot.launch.py b/robot/src/raspbot_v2/launch/robot.launch.py index fa65af5..014ff8f 100644 --- a/robot/src/raspbot_v2/launch/robot.launch.py +++ b/robot/src/raspbot_v2/launch/robot.launch.py @@ -1,10 +1,22 @@ +import os + +from ament_index_python.packages import get_package_share_directory from launch import LaunchDescription from launch.actions import DeclareLaunchArgument -from launch.substitutions import LaunchConfiguration +from launch.substitutions import LaunchConfiguration, Command from launch_ros.actions import Node +from launch_ros.parameter_descriptions import ParameterValue def generate_launch_description(): + urdf_file = os.path.join( + get_package_share_directory('raspbot_v2'), 'urdf', 'raspbot_v2.urdf.xacro' + ) + robot_description = ParameterValue( + Command(['xacro ', urdf_file]), + value_type=str, + ) + return LaunchDescription([ # ── Motor controller arguments ──────────────────────────────────── @@ -23,6 +35,33 @@ def generate_launch_description(): DeclareLaunchArgument('tilt_center_deg', default_value='60.0', description='Tilt angle at startup and shutdown (degrees)'), + # ── TF / robot description ──────────────────────────────────────── + Node( + package='robot_state_publisher', + executable='robot_state_publisher', + name='robot_state_publisher', + parameters=[{'robot_description': robot_description}], + output='screen', + ), + + # Static: map → odom (identity — replace with SLAM/AMCL when ready) + Node( + package='tf2_ros', + executable='static_transform_publisher', + name='map_to_odom', + arguments=['0', '0', '0', '0', '0', '0', 'map', 'odom'], + output='screen', + ), + + # Static: odom → base_footprint (placeholder until odometry is added) + Node( + package='tf2_ros', + executable='static_transform_publisher', + name='odom_to_base', + arguments=['0', '0', '0', '0', '0', '0', 'odom', 'base_footprint'], + output='screen', + ), + # ── Nodes ───────────────────────────────────────────────────────── Node( package='raspbot_v2', diff --git a/robot/src/raspbot_v2/setup.py b/robot/src/raspbot_v2/setup.py index 3e520db..f4bf635 100644 --- a/robot/src/raspbot_v2/setup.py +++ b/robot/src/raspbot_v2/setup.py @@ -10,6 +10,7 @@ setup( ('share/ament_index/resource_index/packages', ['resource/' + package_name]), ('share/' + package_name, ['package.xml']), ('share/' + package_name + '/launch', ['launch/robot.launch.py']), + ('share/' + package_name + '/urdf', ['urdf/raspbot_v2.urdf.xacro']), ], install_requires=['setuptools'], zip_safe=True, diff --git a/robot/src/raspbot_v2/urdf/raspbot_v2.urdf.xacro b/robot/src/raspbot_v2/urdf/raspbot_v2.urdf.xacro new file mode 100644 index 0000000..4dd7066 --- /dev/null +++ b/robot/src/raspbot_v2/urdf/raspbot_v2.urdf.xacro @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +