Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .config/.yamllint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ rules:
line-length:
max: 256
commas: false
document-start: disable
comments:
min-spaces-from-content: 1
new-lines: disable

truthy:
ignore: |
.github/workflows/build_base_images.yml
.github/workflows/build_and_unitest.yml
.github/workflows/pre-commit.yml
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ __pycache__
watod-config.local.sh
**/.DS_Store
draft_*
*copy*
camera-info.txt
src/gazebo/launch/MR24-DT-A00.00 - URDF/
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,62 @@ These steps are to setup the repo to work on your own PC. We utilize docker to e
1. This repo is supported on Linux Ubuntu >= 22.04, Windows (WSL), and MacOS. This is standard practice that roboticists can't get around. To setup, you can either setup an [Ubuntu Virtual Machine](https://ubuntu.com/tutorials/how-to-run-ubuntu-desktop-on-a-virtual-machine-using-virtualbox#1-overview), setting up [WSL](https://learn.microsoft.com/en-us/windows/wsl/install), or setting up your computer to [dual boot](https://opensource.com/article/18/5/dual-boot-linux). You can find online resources for all three approaches.
2. Once inside Linux, [Download Docker Engine using the `apt` repository](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository)
3. You're all set! You can visit the [WATO Wiki](https://wiki.watonomous.ca/autonomous_software_general/monorepo_infrastructure) for more documentation on the WATO infrastructure.

## Demo
https://github.com/user-attachments/assets/d4e821cd-8db7-4176-9e2e-1d9c62aab23d

![Demo Screenshot](assets/demos/demo_nov30.png)

## Simulation Environment

We use Ignition Gazebo for physics simulation. The main world file is `robot_env.sdf`, which defines the entire simulation scene.

### Robot Model (SDF)
A basic model of the rover is defined directly in the SDF with a differential drive base. Key components:
- **Chassis**: 2.0m x 1.0m x 0.5m box with inertial properties
- **Wheels**: Four cylindrical wheels with revolute joints
- **IMU**: Mounted on chassis, publishes to `/imu`
- **RGBD Camera**: Simulated RealSense D435 mounted on the front

### Depth Camera Simulation
The depth camera is configured as an `rgbd_camera` sensor with realistic FOV, intrinsics, etc.

It publishes:
- `/camera/image` ([Image](https://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/Image.html)) - RGB image (used by YOLO object detector)
- `/camera/points` ([PointCloud2](https://docs.ros.org/en/noetic/api/sensor_msgs/html/msg/PointCloud2.html)) - 3D point cloud (used by costmap)

### Mars Environment (URDF)
The environment is loaded from `mars_env.urdf`, which includes meshes for the mars terrain, mallet, and water bottle.

The terrain has collision geometry so the rover can't drive through obstacles.

### ROS2 Bridge
The `ros_gz_bridge` translates Ignition messages to ROS2 topics, bridging `/cmd_vel`, `/imu`, camera streams, and TF transforms. This way, our ROS2 autonomy stack interface seamlessly with the Gazebo sim.

## Autonomy Architecture

### Sensor Simulation
- **gps_sim**: Simulates GPS measurements by reading ground truth transforms from the simulator and injecting realistic noise and dropouts. Publishes [NavSatFix](https://docs.ros.org/en/kinetic/api/sensor_msgs/html/msg/NavSatFix.html) messages.
- **imu_sim**: Adds sensor noise and bias to clean IMU data to mimic real-world sensors. Takes ground truth IMU and outputs noisy orientation and angular velocity.

### Localization
- **localization**: Runs an Extended Kalman Filter (EKF) to fuse (simulated) noisy GPS and IMU data into a smooth, filtered odometry estimate. Outputs robot pose for downstream modules.

### Perception & Mapping
- **costmap**: Converts RGBD camera point clouds into a local 2D occupancy grid centered on the robot. Marks obstacles and inflates them for safety margins.
- **map_memory**: Stitches together local costmaps into a persistent global map as the rover explores. Only updates when the robot moves beyond a threshold distance to reduce computational load.
- **yolo_inference**: Runs YOLOv8 object detection (ONNX runtime) on camera images to detect objects like bottles and mallets. Publishes annotated images with bounding boxes.

### Planning & Control
- **planner**: Implements A* search on the global occupancy grid. Takes the current robot pose and a goal point, outputs a collision-free path. Replans when new goals arrive.
- **control**: Pure pursuit controller that tracks the planned path. Uses a PID loop (configurable Kp, Ki, Kd gains) to compute steering corrections based on cross-track error. Outputs angular velocity to steer toward the target waypoint while maintaining constant forward velocity, publishing [Twist](https://docs.ros.org/en/jade/api/geometry_msgs/html/msg/Twist.html) commands to `/cmd_vel`.

### Data Flow
The pipeline runs as follows:
- Sensor sims generate noisy data
- Localization fuses it into an estimate of the robot's position (odometry)
- Costmap builds local obstacles
- Map memory accumulates into global map
- Planner finds path to goal
- Control executes path
- Motor commands actuate the rover
Binary file added assets/demos/demo_nov30.mp4
Binary file not shown.
Binary file added assets/demos/demo_nov30.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions docker/gazebo/gazeboserver.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends curl \
# Scan for rosdeps
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN apt-get -qq update && rosdep update && \
(rosdep install --from-paths . --ignore-src -r -s \
| grep 'apt-get install' \
(rosdep install --from-paths . --ignore-src -r -s || true) \
| (grep 'apt-get install' || true) \
| awk '{print $3}' \
| sort > /tmp/colcon_install_list || echo "# No additional dependencies needed" > /tmp/colcon_install_list)
| sort > /tmp/colcon_install_list

################################# Dependencies ################################
FROM ${BASE_IMAGE} AS dependencies
Expand Down
27 changes: 15 additions & 12 deletions docker/robot/robot.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,25 @@ RUN apt-get update && apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*

# Copy in source code
COPY src/robot/yolo_inference ./yolo_inference
COPY src/robot/object_detection object_detection
# COPY src/robot/yolo_inference ./yolo_inference
# COPY src/robot/object_detection object_detection
COPY src/robot/odometry_spoof odometry_spoof
COPY src/robot/gps_sim gps_sim
COPY src/robot/imu_sim imu_sim
COPY src/robot/localization localization
COPY src/robot/costmap costmap
COPY src/robot/map_memory map_memory
COPY src/robot/planner planner
COPY src/robot/control control
COPY src/robot/bringup_robot bringup_robot
COPY src/robot/camera_fallback camera_fallback
COPY src/robot/arcade_driver arcade_driver
COPY src/robot/motor_speed_controller motor_speed_controller
COPY src/wato_msgs/drivetrain_msgs drivetrain_msgs

# Scan for rosdeps
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN apt-get -qq update && rosdep update && \
(rosdep install --from-paths . --ignore-src -r -s \
| grep 'apt-get install' \
| awk '{print $3}' \
| sort > /tmp/colcon_install_list || echo "# No additional dependencies needed" > /tmp/colcon_install_list)
(rosdep install --from-paths . --ignore-src -r -s || true) \
| (grep 'apt-get install' || true) \
| awk '{print $3}' \
| sort > /tmp/colcon_install_list || echo "# No additional dependencies needed" > /tmp/colcon_install_list

################################# Dependencies ################################
FROM ${BASE_IMAGE} AS dependencies
Expand All @@ -50,8 +53,8 @@ RUN apt-get -qq update && \
rm -rf /var/lib/apt/lists/*

# Copy in source code from source stage
WORKDIR ${AMENT_WS}/src
COPY src/robot/object_detection object_detection
# WORKDIR ${AMENT_WS}/src
# COPY src/robot/object_detection object_detection
WORKDIR ${AMENT_WS}
COPY --from=source ${AMENT_WS}/src src

Expand Down
7 changes: 3 additions & 4 deletions docker/vis_tools/foxglove.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends curl \
# Scan for rosdeps
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN apt-get -qq update && rosdep update && \
(rosdep install --from-paths . --ignore-src -r -s \
| grep 'apt-get install' \
(rosdep install --from-paths . --ignore-src -r -s || true) \
| (grep 'apt-get install' || true) \
| awk '{print $3}' \
| sort > /tmp/colcon_install_list || echo "# No additional dependencies needed" > /tmp/colcon_install_list)
| sort > /tmp/colcon_install_list

################################# Dependencies ################################
FROM ${BASE_IMAGE} AS dependencies
Expand All @@ -36,7 +36,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends lsb-release sof
apt-add-repository universe && \
rm -rf /var/lib/apt/lists/*

# Install Dependencies
# Install Dependencies
RUN apt-get update && \
apt-get install -y --no-install-recommends \
Expand Down
65 changes: 65 additions & 0 deletions how 0bb5293d52599317a3e300c55897e34a48e5e289 --numstat
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
commit 0bb5293d52599317a3e300c55897e34a48e5e289
Author: Barry Zhang <45883553+bluebarryz@users.noreply.github.com>
Date: Wed Jan 7 19:46:46 2026 -0500

refactor perception and integrate costmap, planner, and control modules

.gitignore | 3 +
docker/gazebo/gazeboserver.Dockerfile | 10 +-
docker/robot/robot.Dockerfile | 29 +-
docker/vis_tools/foxglove.Dockerfile | 11 +-
modules/docker-compose.robot.yaml | 13 +-
src/gazebo/launch/env.urdf | 357 ++++++-----
src/gazebo/launch/mr24/robot.urdf | 365 +++++++++++
src/gazebo/launch/robot_env.sdf | 668 +++++++++------------
src/gazebo/launch/sim.launch.py | 60 +-
src/robot/bringup_robot/launch/robot.launch.py | 206 +++++--
src/robot/bringup_robot/package.xml | 14 +-
src/robot/control/CMakeLists.txt | 7 +-
src/robot/control/config/params.yaml | 14 +-
src/robot/control/include/control_core.hpp | 47 ++
src/robot/control/include/control_node.hpp | 63 ++
src/robot/control/package.xml | 3 +
src/robot/control/src/control_core.cpp | 146 ++++-
src/robot/control/src/control_node.cpp | 101 +++-
src/robot/costmap/CMakeLists.txt | 5 +-
src/robot/costmap/config/params.yaml | 20 +-
src/robot/costmap/include/costmap_core.hpp | 50 ++
src/robot/costmap/include/costmap_node.hpp | 46 ++
src/robot/costmap/package.xml | 3 +
src/robot/costmap/src/costmap_core.cpp | 170 +++++-
src/robot/costmap/src/costmap_node.cpp | 88 ++-
src/robot/gps_sim/CMakeLists.txt | 47 ++
src/robot/gps_sim/config/params.yaml | 13 +
src/robot/gps_sim/include/gps_sim_node.hpp | 46 ++
src/robot/gps_sim/package.xml | 28 +
src/robot/gps_sim/src/gps_sim_node.cpp | 134 +++++
src/robot/imu_sim/CMakeLists.txt | 41 ++
src/robot/imu_sim/config/params.yaml | 18 +
src/robot/imu_sim/include/imu_sim_node.hpp | 53 ++
src/robot/imu_sim/package.xml | 25 +
src/robot/imu_sim/src/imu_sim_node.cpp | 171 ++++++
src/robot/localization/CMakeLists.txt | 56 ++
src/robot/localization/config/params.yaml | 25 +
.../localization/include/localization_core.hpp | 106 ++++
.../localization/include/localization_node.hpp | 73 +++
src/robot/localization/package.xml | 29 +
src/robot/localization/src/localization_core.cpp | 501 ++++++++++++++++
src/robot/localization/src/localization_node.cpp | 225 +++++++
src/robot/map_memory/CMakeLists.txt | 8 +-
src/robot/map_memory/config/params.yaml | 26 +-
src/robot/map_memory/include/map_memory_core.hpp | 38 ++
src/robot/map_memory/include/map_memory_node.hpp | 63 ++
src/robot/map_memory/package.xml | 3 +
src/robot/map_memory/src/map_memory_core.cpp | 110 +++-
src/robot/map_memory/src/map_memory_node.cpp | 141 ++++-
.../odometry_spoof/include/odometry_spoof.hpp | 40 ++
src/robot/odometry_spoof/src/odometry_spoof.cpp | 92 +--
src/robot/planner/CMakeLists.txt | 4 +-
src/robot/planner/config/params.yaml | 16 +-
src/robot/planner/include/planner_core.hpp | 125 +++-
src/robot/planner/include/planner_node.hpp | 70 ++-
src/robot/planner/package.xml | 2 +
src/robot/planner/src/planner_core.cpp | 262 +++++++-
src/robot/planner/src/planner_node.cpp | 186 +++++-
58 files changed, 4503 insertions(+), 773 deletions(-)
9 changes: 0 additions & 9 deletions modules/docker-compose.robot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ services:
profiles:
- deploy
command: /bin/bash -c "ros2 launch bringup_robot robot.launch.py"
devices:
- /dev/bus/usb:/dev/bus/usb
volumes:
- /dev:/dev
privileged: true

robot_dev:
build: *robot_build
Expand All @@ -26,7 +21,3 @@ services:
- develop
volumes:
- ${MONO_DIR}/src/robot:/root/ament_ws/src
- /dev:/dev
devices:
- /dev/bus/usb:/dev/bus/usb
privileged: true
Loading
Loading