This repository contains a ROS 2 description + demo control stack for a Boston Dynamics Spot-like quadruped model (with an optional arm) that you can visualize in RViz2 and drive using a simple keyboard teleop.
At a high level:
spot_descriptionprovides the URDF/Xacro, meshes, RViz configs, and launch files.walk.pyruns a basic gait / IK-based controller that outputs joint angles assensor_msgs/JointStateon/joint_states.teleop.pyreads keyboard input from your terminal and publishes velocity commands asgeometry_msgs/TwistStampedon/twist.
The default walking demo loop is:
teleop.pypublishes/twistwalk.pysubscribes to/twist, computes the next body/foot motion + joint targetswalk.pypublishes/joint_statesrobot_state_publisherconsumes/joint_statesto update TF- RViz shows the robot moving
Directory (inside SpotProject/spot_description/):
launch/: ROS 2 launch files for visualization and demosurdf/: Spot URDF/Xacro sources (Spot-only, Spot+arm, simplified model, standalone arm)meshes/: visual + collision meshes for the base and armrviz/: RViz2 configurationswalk.py: walking/gait demo node (publishes/joint_states, subscribes/twist)teleop.py: keyboard teleop node (publishes/twist)
For the list of URDF variants, see SpotProject/spot_description/urdf/README.md.
For details on inertial properties / how the inertials were extracted, see SpotProject/spot_description/README.md.
- ROS 2 installed (this is a ROS 2 workspace; the launch files use
ros2 launch) - Python deps used by the demo nodes:
numpy- ROS 2 Python libraries (
rclpy,tf2_ros, message packages such asgeometry_msgs,sensor_msgs)
- ROS executables used by launch:
robot_state_publisherjoint_state_publisher/joint_state_publisher_guirviz2xacro
The ROS exec dependencies are also listed in SpotProject/spot_description/package.xml.
From your workspace root (the parent directory of src/):
source /opt/ros/$ROS_DISTRO/setup.bash
cd ~/robotws
colcon build --symlink-install
source install/setup.bashIf your workspace is not ~/robotws, adjust the cd accordingly.
This launches robot_state_publisher, joint_state_publisher(_gui), and RViz:
ros2 launch spot_description description.launch.pyTo include the arm in the model:
ros2 launch spot_description description.launch.py arm:=trueros2 launch spot_description standalone_arm.launch.pyThis launches RViz + walk.py + teleop.py:
ros2 launch spot_description walk.launch.pyteleop.py uses your terminal (reads from /dev/tty) and publishes to /twist:
w: forwards: backwarda: strafe leftd: strafe rightq: yaw lefte: yaw right- Space: stop (zero command)
Safety/behavior notes:
- Commands timeout quickly (about 0.1s) if you stop pressing keys, so the robot returns to zero velocity.
- If you run through SSH or a non-interactive terminal,
/dev/ttyinput may not work; runteleop.pylocally in a real terminal session.
The walking demo is intentionally simple and uses two global topics:
/twist(geometry_msgs/TwistStamped): teleop velocity command (linear + angular)/joint_states(sensor_msgs/JointState): joint positions/velocities produced bywalk.py
walk.py also publishes a TF transform from world → body so RViz can display the body moving in the world frame.
walk.py implements a lightweight quadruped gait loop:
- Tracks a desired body pose (position + orientation) by integrating commanded twist (
/twist). - Keeps feet within an elliptical reachability region relative to the body; when a foot drifts out of range, it is switched into a swing phase.
- Swing legs follow a parabolic swing trajectory (lift + land), while stance legs hold position.
- Uses Jacobian-based IK tasks:
- Primary: match desired foot positions (all four feet)
- Secondary: keep body height near a nominal (Z) (stability)
- Tertiary: bias joints toward “natural-looking” centers
The output is a 12-DOF leg joint vector published as JointState.
-
RViz opens but robot doesn’t move:
- Make sure you launched the walking demo (
walk.launch.py), not justdescription.launch.py. - Confirm that
/twistis being published (press keys in the teleop terminal). - Confirm that
/joint_statesis being published (ros2 topic echo /joint_states).
- Make sure you launched the walking demo (
-
Teleop doesn’t respond to keypresses:
teleop.pyreads from/dev/tty. Run it in a real interactive terminal (not piped, not redirected).- If you’re using SSH, ensure you have a proper TTY (
ssh -t) and that your terminal supports raw input.
-
Launch can’t find package:
- Rebuild and re-source:
cd ~/robotws
colcon build --symlink-install
source install/setup.bash