Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 5 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ pixi run submodules # Fetch git submodules (sllidar_ros2, kinematic_icp)
pixi run launch # Full robot bringup (hardware + lidar + camera + localization)
pixi run slam # SLAM stack only (run alongside launch)
pixi run nav # Nav2 stack (requires a saved map at ~/.mote/map.yaml)
pixi run robot # mote_launch + slam together
pixi run mapping # bringup + SLAM together (build/extend a map)
pixi run robot # bringup + Nav2 together (drive a saved map; needs ~/.mote/map.yaml)
pixi run save-map # Save current map to ~/.mote/map
pixi run teleop # Keyboard teleoperation
pixi run sync # rsync project to Pi at SSH host 'mote'
Expand Down Expand Up @@ -65,9 +66,10 @@ Contains `urdf/mote.urdf.xacro` and `config/robot.yaml`. The xacro loads robot.y
Launch files, config, udev rules, and systemd services.

**Launch hierarchy:**
- `robot_launch.py` — combines `mote_launch.py` + `slam_launch.py`
- `robot_launch.py` — combines `mote_launch.py` + `nav2_launch.py` (everyday operation: drive a saved map). Forwards a `map` arg, defaulting to `~/.mote/map.yaml`.
- `mapping_launch.py` — combines `mote_launch.py` + `slam_launch.py` (build/extend a map with SLAM)
- `mote_launch.py` — main bringup: robot_state_publisher, ros2_control_node, controller spawners, sllidar, laser_filter, v4l2_camera, and `localization_launch.py`. Reads `robot.yaml` for wheel geometry (injected into DiffDriveController params) and sensor config.
- `localization_launch.py` — AMCL-based localization
- `localization_launch.py` — kinematic_icp LIDAR odometry (publishes `odom`→`base`; the map→odom corrector is slam_toolbox when mapping or AMCL when navigating). Despite the name, it does *not* run AMCL — AMCL lives in `nav2_launch.py`.
- `slam_launch.py` — slam_toolbox (accepts `use_sim_time:=true` for the sim)
- `sim_launch.py` — Gazebo sim (sim environment only): headless gz server with `worlds/mote_world.sdf`, robot spawn, ros_gz bridge (/clock, /scan), controllers, laser_filter. The URDF is processed with `use_sim:=true`, which swaps `MoteHardware` for `gz_ros2_control` and adds a simulated lidar (specs from `robot.yaml` `lidar.sim`). Without that flag the xacro output is unchanged. Controller params are merged into one temp file (gz_ros2_control loads a single `<parameters>` file referenced in the URDF).
- `nav2_launch.py` — Nav2 stack
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ pixi run rviz # Runs rviz to view the map and navigate
pixi run slam # Runs the SLAM stack to create a map
# or
pixi run nav # Runs the nav stack

# Convenience combos (base + the relevant stack in one command):
pixi run mapping # = launch + slam (build/extend a map)
pixi run robot # = launch + nav (drive a saved map at ~/.mote/map.yaml)
```

### Simulation (no hardware required)
Expand Down
25 changes: 25 additions & 0 deletions mote_bringup/launch/mapping_launch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource


def generate_launch_description():
launch_dir = os.path.join(
get_package_share_directory("mote_bringup"), "launch"
)

return LaunchDescription([
IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_dir, "mote_launch.py")
)
),
IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_dir, "slam_launch.py")
)
),
])
15 changes: 12 additions & 3 deletions mote_bringup/launch/robot_launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,33 @@

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration


def generate_launch_description():
launch_dir = os.path.join(
get_package_share_directory("mote_bringup"), "launch"
)

default_map = os.path.join(os.path.expanduser("~"), ".mote", "map.yaml")

return LaunchDescription([
DeclareLaunchArgument(
"map",
default_value=default_map,
description="Full path to the map yaml file Nav2 should load",
),
IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_dir, "mote_launch.py")
)
),
IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(launch_dir, "slam_launch.py")
)
os.path.join(launch_dir, "nav2_launch.py")
),
launch_arguments={"map": LaunchConfiguration("map")}.items(),
),
])
3 changes: 2 additions & 1 deletion pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ build = { cmd = "colcon build --symlink-install --cmake-args -G Ninja -DCMAKE_PO
clean = "pkill -9 -f 'robot_state_publisher|ros2_control_node|sllidar|v4l2_camera|spawner'; ros2 daemon stop; rm -f /dev/shm/fast*; ros2 daemon start; true"
install-systemd = "bash mote_bringup/systemd/install.sh"
launch = "ros2 launch mote_bringup mote_launch.py"
mapping = "ros2 launch mote_bringup mapping_launch.py"
nav = "ros2 launch mote_bringup nav2_launch.py map:=$HOME/.mote/map.yaml"
robot = "ros2 launch mote_bringup robot_launch.py"
save-map = "mkdir -p $HOME/.mote && ros2 run nav2_map_saver map_saver_cli -f $HOME/.mote/map"
slam = "ros2 launch mote_bringup slam_launch.py"
sync = "rsync -avz --exclude='.pixi/' --exclude='build/' --exclude='install/' --exclude='log/' --exclude='.git/' --exclude='.claude/' . michael@mote:~/Mote/"
sync = "rsync -avz --exclude='.pixi/' --exclude='build/' --exclude='install/' --exclude='log/' --exclude='.git/' --exclude='.claude/' . michael@auldbot:~/Mote/"
teleop = "ros2 run teleop_twist_keyboard teleop_twist_keyboard --ros-args -p stamped:=true -r /cmd_vel:=/diff_drive_controller/cmd_vel"
udev = "sudo cp mote_bringup/udev/99-mote.rules /etc/udev/rules.d/ && sudo udevadm control --reload-rules && sudo udevadm trigger"
setup-ids = "ros2 run mote_hardware setup_ids"
Expand Down
Loading