diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index fc5cf9f..2661feb 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -46,6 +46,11 @@ RUN apt-get update && apt-get install -y \
# ros-${ROS_DISTRO}-ament-lint-auto \
# ros-${ROS_DISTRO}-ament-lint-common
+# URDF / xacro tooling — needed to generate flat URDF for IDE preview
+RUN apt-get update && apt-get install -y \
+ ros-${ROS_DISTRO}-xacro \
+ ros-${ROS_DISTRO}-robot-state-publisher
+
# Node.js for frontend development
RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
&& apt-get install -y nodejs
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 827b1df..9da4688 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -21,7 +21,7 @@
"eamodio.gitlens",
"ms-iot.vscode-ros",
"anthropic.claude-code",
- "Ranch-Hand-Robotics.urdf-editor"
+ "morningfrog.urdf-visualizer"
]
}
},
diff --git a/.gitignore b/.gitignore
index 5578fe3..d94a87b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,9 @@
.vscode/browse.vc.db-wal
.vscode/c_cpp_properties.json
+# Generated URDF preview (regenerate with the "Generate preview URDF" VS Code task)
+**/urdf/preview.urdf
+
# colcon build artefacts
build/
install/
diff --git a/robot/src/raspbot_v2/launch/robot.launch.py b/robot/src/raspbot_v2/launch/robot.launch.py
index 732b562..a54f189 100644
--- a/robot/src/raspbot_v2/launch/robot.launch.py
+++ b/robot/src/raspbot_v2/launch/robot.launch.py
@@ -13,7 +13,10 @@ def generate_launch_description():
get_package_share_directory('raspbot_v2'), 'urdf', 'raspbot_v2.urdf.xacro'
)
robot_description = ParameterValue(
- Command(['xacro ', urdf_file]),
+ Command([
+ 'xacro ', urdf_file,
+ ' wheel_separation:=', LaunchConfiguration('wheel_base'),
+ ]),
value_type=str,
)
diff --git a/robot/src/raspbot_v2/setup.py b/robot/src/raspbot_v2/setup.py
index e7c3816..61221cf 100644
--- a/robot/src/raspbot_v2/setup.py
+++ b/robot/src/raspbot_v2/setup.py
@@ -1,3 +1,5 @@
+import glob
+
from setuptools import setup
package_name = 'raspbot_v2'
@@ -10,7 +12,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']),
+ ('share/' + package_name + '/urdf', glob.glob('urdf/*.xacro')),
],
install_requires=['setuptools'],
zip_safe=True,
diff --git a/robot/src/raspbot_v2/urdf/camera.xacro b/robot/src/raspbot_v2/urdf/camera.xacro
new file mode 100644
index 0000000..c8eca3a
--- /dev/null
+++ b/robot/src/raspbot_v2/urdf/camera.xacro
@@ -0,0 +1,83 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 30
+ true
+
+ ${camera_fov}
+
+ ${camera_width}
+ ${camera_height}
+ R8G8B8
+
+
+ 0.05
+ 50.0
+
+
+ gaussian
+ 0.0
+ 0.007
+
+
+
+ /camera/image
+
+
+
+
diff --git a/robot/src/raspbot_v2/urdf/lidar.xacro b/robot/src/raspbot_v2/urdf/lidar.xacro
new file mode 100644
index 0000000..69e32f9
--- /dev/null
+++ b/robot/src/raspbot_v2/urdf/lidar.xacro
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 10
+ true
+ /scan
+ laser
+
+
+
+ 360
+ 1
+ -3.14159265
+ 3.14159265
+
+
+
+ ${lidar_min_range}
+ ${lidar_max_range}
+ 0.01
+
+
+ gaussian
+ 0.0
+ 0.01
+
+
+
+
+
+
diff --git a/robot/src/raspbot_v2/urdf/pan_tilt.xacro b/robot/src/raspbot_v2/urdf/pan_tilt.xacro
new file mode 100644
index 0000000..636f00b
--- /dev/null
+++ b/robot/src/raspbot_v2/urdf/pan_tilt.xacro
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ transmission_interface/SimpleTransmission
+
+ hardware_interface/PositionJointInterface
+
+
+ hardware_interface/PositionJointInterface
+ 1
+
+
+
+
+ transmission_interface/SimpleTransmission
+
+ hardware_interface/PositionJointInterface
+
+
+ hardware_interface/PositionJointInterface
+ 1
+
+
+
+
+
+
+
+ gz_ros2_control/GazeboSimSystem
+
+
+
+
+ ${pan_min_rad}
+ ${pan_max_rad}
+
+
+
+
+
+
+ ${tilt_min_rad}
+ ${tilt_max_rad}
+
+
+
+
+
+
+
diff --git a/robot/src/raspbot_v2/urdf/raspbot_v2.urdf.xacro b/robot/src/raspbot_v2/urdf/raspbot_v2.urdf.xacro
index 699d35a..8d3e511 100644
--- a/robot/src/raspbot_v2/urdf/raspbot_v2.urdf.xacro
+++ b/robot/src/raspbot_v2/urdf/raspbot_v2.urdf.xacro
@@ -1,132 +1,99 @@
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+ All physical parameters are declared here as xacro:arg so they can
+ be overridden at build time:
+ xacro raspbot_v2.urdf.xacro wheel_separation:=0.14
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ Sub-files reference these properties directly; they are not intended
+ to be included in isolation.
+ ═══════════════════════════════════════════════════════════════════════ -->
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/robot/src/raspbot_v2/urdf/robot_base.xacro b/robot/src/raspbot_v2/urdf/robot_base.xacro
new file mode 100644
index 0000000..2022983
--- /dev/null
+++ b/robot/src/raspbot_v2/urdf/robot_base.xacro
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.0
+ 0.5
+ 1e6
+ 1.0
+
+
+
+
+
+
+
+
+
+
+
+
+ wheel_front_left_joint
+ wheel_rear_left_joint
+ wheel_front_right_joint
+ wheel_rear_right_joint
+ ${wheel_separation}
+ ${wheel_radius}
+ 10
+ cmd_vel
+ odom
+ odom
+ base_footprint
+
+
+
+
diff --git a/robot/src/raspbot_v2/urdf/sonar.xacro b/robot/src/raspbot_v2/urdf/sonar.xacro
new file mode 100644
index 0000000..b6fd96e
--- /dev/null
+++ b/robot/src/raspbot_v2/urdf/sonar.xacro
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 10
+ true
+ /ultrasonic/range
+ ultrasonic
+
+
+ ${sonar_min_range}
+ ${sonar_max_range}
+
+ 0.13
+
+
+
+
+