From 0e155c6fed9df79a199471a9cc756abc1e3091f1 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Sat, 25 Oct 2025 08:19:24 +0300 Subject: [PATCH 01/38] fix quat --- dimos/navigation/rosnav/nav_bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dimos/navigation/rosnav/nav_bot.py b/dimos/navigation/rosnav/nav_bot.py index 4a5ca0c45a..26060b4926 100644 --- a/dimos/navigation/rosnav/nav_bot.py +++ b/dimos/navigation/rosnav/nav_bot.py @@ -398,7 +398,7 @@ def main(): ts=time.time(), frame_id="map", position=Vector3(1.0, 1.0, 0.0), - orientation=Quaternion(0.0, 0.0, 0.0, 0.0), + orientation=Quaternion(0.0, 0.0, 0.0, 1.0), ) logger.info(f"Sending navigation goal to: (1.0, 1.0, 0.0)") From c1cd3727ea827913040143fdd99ee20b8f4fa1af Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Sat, 25 Oct 2025 08:20:42 +0300 Subject: [PATCH 02/38] add ros docker integration --- ros_docker_integration/.gitignore | 20 +++ ros_docker_integration/Dockerfile | 116 ++++++++++++ ros_docker_integration/README.md | 178 +++++++++++++++++++ ros_docker_integration/build.sh | 70 ++++++++ ros_docker_integration/docker-compose.yml | 66 +++++++ ros_docker_integration/ros_launch_wrapper.py | 132 ++++++++++++++ ros_docker_integration/run_both.sh | 109 ++++++++++++ ros_docker_integration/run_command.sh | 46 +++++ ros_docker_integration/shell.sh | 42 +++++ ros_docker_integration/start.sh | 88 +++++++++ ros_docker_integration/start_clean.sh | 90 ++++++++++ ros_docker_integration/test_integration.sh | 121 +++++++++++++ 12 files changed, 1078 insertions(+) create mode 100644 ros_docker_integration/.gitignore create mode 100644 ros_docker_integration/Dockerfile create mode 100644 ros_docker_integration/README.md create mode 100755 ros_docker_integration/build.sh create mode 100644 ros_docker_integration/docker-compose.yml create mode 100755 ros_docker_integration/ros_launch_wrapper.py create mode 100755 ros_docker_integration/run_both.sh create mode 100755 ros_docker_integration/run_command.sh create mode 100755 ros_docker_integration/shell.sh create mode 100755 ros_docker_integration/start.sh create mode 100755 ros_docker_integration/start_clean.sh create mode 100755 ros_docker_integration/test_integration.sh diff --git a/ros_docker_integration/.gitignore b/ros_docker_integration/.gitignore new file mode 100644 index 0000000000..4933cec4ed --- /dev/null +++ b/ros_docker_integration/.gitignore @@ -0,0 +1,20 @@ +# Cloned repository +autonomy_stack_mecanum_wheel_platform/ + +# Unity models (large binary files) +unity_models/ + +# ROS bag files +bagfiles/ + +# Config files (may contain local settings) +config/ + +# Docker volumes +.docker/ + +# Temporary files +*.tmp +*.log +*.swp +*~ \ No newline at end of file diff --git a/ros_docker_integration/Dockerfile b/ros_docker_integration/Dockerfile new file mode 100644 index 0000000000..0502ba6e11 --- /dev/null +++ b/ros_docker_integration/Dockerfile @@ -0,0 +1,116 @@ +# Base image with ROS Jazzy desktop full +FROM osrf/ros:jazzy-desktop-full + +# Set environment variables +ENV DEBIAN_FRONTEND=noninteractive +ENV ROS_DISTRO=jazzy +ENV WORKSPACE=/ros2_ws +ENV DIMOS_PATH=/home/p/pro/dimensional/dimos + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + # ROS packages + ros-jazzy-pcl-ros \ + # Development tools + git \ + cmake \ + build-essential \ + python3-colcon-common-extensions \ + # PCL and system libraries + libpcl-dev \ + libgoogle-glog-dev \ + libgflags-dev \ + libatlas-base-dev \ + libeigen3-dev \ + libsuitesparse-dev \ + # X11 and GUI support for RVIZ + x11-apps \ + xorg \ + openbox \ + # Networking tools + iputils-ping \ + net-tools \ + iproute2 \ + # Editor (optional but useful) + nano \ + vim \ + # Python tools + python3-pip \ + python3-setuptools \ + python3-venv \ + # Additional dependencies for dimos + ffmpeg \ + portaudio19-dev \ + libsndfile1 \ + # For OpenCV + libgl1 \ + libglib2.0-0 \ + # For Open3D + libgomp1 \ + # Clean up + && rm -rf /var/lib/apt/lists/* + +# Create workspace directory +RUN mkdir -p ${WORKSPACE}/src + +# Copy the autonomy stack repository (should be cloned by build.sh) +COPY ros_docker_integration/autonomy_stack_mecanum_wheel_platform ${WORKSPACE}/src/autonomy_stack_mecanum_wheel_platform + +# Set working directory +WORKDIR ${WORKSPACE} + +# Set up ROS environment +RUN echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> ~/.bashrc + +# Build the autonomy stack workspace (simulation mode - skipping SLAM and Mid-360 driver) +RUN /bin/bash -c "source /opt/ros/${ROS_DISTRO}/setup.bash && \ + cd ${WORKSPACE} && \ + colcon build --symlink-install \ + --cmake-args -DCMAKE_BUILD_TYPE=Release \ + --packages-skip arise_slam_mid360 arise_slam_mid360_msgs livox_ros_driver2" + +# Source the workspace setup +RUN echo "source ${WORKSPACE}/install/setup.bash" >> ~/.bashrc + +# Create directory for Unity environment models +RUN mkdir -p ${WORKSPACE}/src/autonomy_stack_mecanum_wheel_platform/src/base_autonomy/vehicle_simulator/mesh/unity + +# Copy the dimos repository +RUN mkdir -p ${DIMOS_PATH} +COPY . ${DIMOS_PATH}/ + +# Install Python dependencies for dimos +WORKDIR ${DIMOS_PATH} +RUN python3 -m venv .venv && \ + /bin/bash -c "source .venv/bin/activate && \ + pip install --upgrade pip setuptools wheel && \ + pip install -e .[cpu,dev] 'mmengine>=0.10.3' 'mmcv>=2.1.0'" + +# Copy helper scripts +COPY ros_docker_integration/run_both.sh /usr/local/bin/run_both.sh +COPY ros_docker_integration/ros_launch_wrapper.py /usr/local/bin/ros_launch_wrapper.py +RUN chmod +x /usr/local/bin/run_both.sh /usr/local/bin/ros_launch_wrapper.py + +# Set up entrypoint script +RUN echo '#!/bin/bash\n\ +set -e\n\ +\n\ +# Source ROS setup\n\ +source /opt/ros/${ROS_DISTRO}/setup.bash\n\ +source ${WORKSPACE}/install/setup.bash\n\ +\n\ +# Activate Python virtual environment for dimos\n\ +source ${DIMOS_PATH}/.venv/bin/activate\n\ +\n\ +# Export ROBOT_CONFIG_PATH for autonomy stack\n\ +export ROBOT_CONFIG_PATH="unitree/unitree_g1"\n\ +\n\ +# Execute the command\n\ +exec "$@"' > /ros_entrypoint.sh && \ + chmod +x /ros_entrypoint.sh + +# Set the entrypoint +ENTRYPOINT ["/ros_entrypoint.sh"] + +# Default command +CMD ["bash"] \ No newline at end of file diff --git a/ros_docker_integration/README.md b/ros_docker_integration/README.md new file mode 100644 index 0000000000..b976057e6d --- /dev/null +++ b/ros_docker_integration/README.md @@ -0,0 +1,178 @@ +# ROS Docker Integration for DimOS + +This directory contains Docker configuration files to run DimOS and the ROS autonomy stack in the same container, enabling communication between the two systems. + +## Prerequisites + +- Docker with `docker compose` support +- NVIDIA GPU with drivers installed +- NVIDIA Container Toolkit (nvidia-docker2) +- X11 server for GUI applications (RVIZ, Unity simulator) + +## Quick Start + +1. **Build the Docker image:** + ```bash + ./build.sh + ``` + This will: + - Clone the autonomy_stack_mecanum_wheel_platform repository (jazzy branch) + - Build a Docker image with both ROS and DimOS dependencies + - Set up the environment for both systems + +2. **Run the container:** + ```bash + # Interactive bash shell (default) + ./start.sh + + # Start with ROS route planner + ./start.sh --ros-planner + + # Start with DimOS Unitree G1 controller + ./start.sh --dimos + + # Start both systems (basic) + ./start.sh --all + + # Start both systems with improved shutdown handling (recommended) + ./start_clean.sh --all + ``` + +## Directory Structure + +``` +ros_docker_integration/ +├── Dockerfile # Combined Dockerfile for ROS + DimOS +├── docker-compose.yml # Docker Compose configuration +├── build.sh # Script to clone repos and build image +├── start.sh # Script to run the container (basic) +├── start_clean.sh # Script with improved shutdown handling +├── run_both.sh # Bash helper to run both ROS and DimOS +├── ros_launch_wrapper.py # Python wrapper for clean ROS shutdown +├── run_command.sh # Helper script for running custom commands +├── shell.sh # Quick access to interactive shell +├── test_integration.sh # Integration test script +├── README.md # This file +├── autonomy_stack_mecanum_wheel_platform/ # (Created by build.sh) +├── unity_models/ # (Optional) Unity environment models +├── bagfiles/ # (Optional) ROS bag files +└── config/ # (Optional) Configuration files +``` + +## Unity Models (Optional) + +For the Unity simulator to work properly, download the Unity environment models from: +https://drive.google.com/drive/folders/1G1JYkccvoSlxyySuTlPfvmrWoJUO8oSs + +Extract them to: `ros_docker_integration/unity_models/` + +## Manual Commands + +Once inside the container, you can manually run: + +### ROS Autonomy Stack +```bash +cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform +./system_simulation_with_route_planner.sh +``` + +### DimOS +```bash +# Activate virtual environment +source /home/p/pro/dimensional/dimos/.venv/bin/activate + +# Run Unitree G1 controller +python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py + +# Or run other DimOS scripts +python /home/p/pro/dimensional/dimos/dimos/your_script.py +``` + +### ROS Commands +```bash +# List ROS topics +ros2 topic list + +# Send navigation goal +ros2 topic pub /way_point geometry_msgs/msg/PointStamped "{ + header: {frame_id: 'map'}, + point: {x: 5.0, y: 3.0, z: 0.0} +}" --once + +# Monitor robot state +ros2 topic echo /state_estimation +``` + +## Custom Commands + +Use the `run_command.sh` helper script to run custom commands: +```bash +./run_command.sh "ros2 topic list" +./run_command.sh "python /path/to/your/script.py" +``` + +## Development + +The docker-compose.yml mounts the following directories for live development: +- DimOS source: `../dimos` → `/home/p/pro/dimensional/dimos/dimos` +- Autonomy stack source: `./autonomy_stack_mecanum_wheel_platform/src` → `/ros2_ws/src/autonomy_stack_mecanum_wheel_platform/src` + +Changes to these files will be reflected in the container without rebuilding. + +## Environment Variables + +The container sets: +- `ROS_DISTRO=jazzy` +- `ROBOT_CONFIG_PATH=unitree/unitree_g1` +- `ROS_DOMAIN_ID=0` +- GPU and display variables for GUI support + +## Shutdown Handling + +The integration provides two methods for running both systems together: + +### Basic Method (`./start.sh --all`) +Uses the bash script `run_both.sh` with signal trapping and process group management. + +### Improved Method (`./start_clean.sh --all`) +Uses the Python wrapper `ros_launch_wrapper.py` which provides: +- Proper signal forwarding to ROS launch system +- Graceful shutdown with timeouts +- Automatic cleanup of orphaned ROS nodes +- Better handling of ROS2's complex process hierarchy + +**Recommended**: Use `./start_clean.sh --all` for the cleanest shutdown experience. + +## Troubleshooting + +### ROS Nodes Not Shutting Down Cleanly +If you experience issues with ROS nodes hanging during shutdown: +1. Use `./start_clean.sh --all` instead of `./start.sh --all` +2. The improved handler will automatically clean up remaining processes +3. If issues persist, you can manually clean up with: + ```bash + docker compose -f ros_docker_integration/docker-compose.yml down + ``` + +### X11 Display Issues +If you get display errors: +```bash +xhost +local:docker +``` + +### GPU Not Available +Ensure NVIDIA Container Toolkit is installed: +```bash +sudo apt-get install nvidia-container-toolkit +sudo systemctl restart docker +``` + +### Permission Issues +The container runs with `--privileged` and `--network=host` for hardware access. + +## Notes + +- The container uses `--network=host` for ROS communication +- GPU passthrough is enabled via `runtime: nvidia` +- X11 forwarding is configured for GUI applications +- The ROS workspace is built without SLAM and Mid-360 packages (simulation mode) \ No newline at end of file diff --git a/ros_docker_integration/build.sh b/ros_docker_integration/build.sh new file mode 100755 index 0000000000..603a841324 --- /dev/null +++ b/ros_docker_integration/build.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}Building DimOS + ROS Autonomy Stack Docker Image${NC}" +echo -e "${GREEN}=========================================${NC}" +echo "" + +# Get the directory where the script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$SCRIPT_DIR" + +# Check if autonomy stack already exists +if [ ! -d "autonomy_stack_mecanum_wheel_platform" ]; then + echo -e "${YELLOW}Cloning autonomy_stack_mecanum_wheel_platform repository...${NC}" + git clone https://github.com/alexlin2/autonomy_stack_mecanum_wheel_platform.git + echo -e "${GREEN}Repository cloned successfully!${NC}" +fi + +# Check if Unity models directory exists (warn if not) +if [ ! -d "unity_models" ]; then + echo "" + echo -e "${YELLOW}WARNING: Unity models directory not found!${NC}" + echo "If you want to use the Unity simulator, please download Unity environment models" + echo "and extract them to: ${SCRIPT_DIR}/unity_models/" + echo "Download from: https://drive.google.com/drive/folders/1G1JYkccvoSlxyySuTlPfvmrWoJUO8oSs" + echo "" + read -p "Continue building without Unity models? (y/n) " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + exit 1 + fi +fi + +# Build the Docker image using docker compose +echo "" +echo -e "${YELLOW}Building Docker image with docker compose...${NC}" +echo "This may take a while as it needs to:" +echo " - Download base ROS Jazzy image" +echo " - Install ROS packages and dependencies" +echo " - Build the autonomy stack" +echo " - Install Python dependencies for DimOS" +echo "" + +# Go to the dimos directory (parent of ros_docker_integration) for the build context +cd .. + +# Build using docker compose +docker compose -f ros_docker_integration/docker-compose.yml build + +echo "" +echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}Docker image built successfully!${NC}" +echo -e "${GREEN}=========================================${NC}" +echo "" +echo "You can now run the container using:" +echo -e "${YELLOW} ./start.sh${NC}" +echo "" +echo "Available options:" +echo " - Run with default configuration (starts bash): ./start.sh" +echo " - Run with ROS route planner: ./start.sh --ros-planner" +echo " - Run with DimOS only: ./start.sh --dimos" +echo " - Run with both: ./start.sh --all" diff --git a/ros_docker_integration/docker-compose.yml b/ros_docker_integration/docker-compose.yml new file mode 100644 index 0000000000..fc411c7400 --- /dev/null +++ b/ros_docker_integration/docker-compose.yml @@ -0,0 +1,66 @@ +services: + dimos_autonomy_stack: + build: + context: .. + dockerfile: ros_docker_integration/Dockerfile + image: dimos_autonomy_stack:jazzy + container_name: dimos_autonomy_container + + # Enable interactive terminal + stdin_open: true + tty: true + + # Network configuration - required for ROS communication + network_mode: host + + # Privileged mode for hardware access (required for real robot and some devices) + privileged: true + + # GPU support (NVIDIA runtime) + runtime: nvidia + + # Environment variables for display and ROS + environment: + - DISPLAY=${DISPLAY} + - QT_X11_NO_MITSHM=1 + - NVIDIA_VISIBLE_DEVICES=all + - NVIDIA_DRIVER_CAPABILITIES=all + - ROS_DOMAIN_ID=0 + - ROBOT_CONFIG_PATH=unitree/unitree_g1 + + # Volume mounts + volumes: + # X11 socket for GUI + - /tmp/.X11-unix:/tmp/.X11-unix:rw + - ${HOME}/.Xauthority:/root/.Xauthority:rw + + # Mount Unity environment models (if available) + - ./unity_models:/ros2_ws/src/autonomy_stack_mecanum_wheel_platform/src/base_autonomy/vehicle_simulator/mesh/unity:rw + + # Mount the autonomy stack source for development (optional - comment out if not needed) + - ./autonomy_stack_mecanum_wheel_platform/src:/ros2_ws/src/autonomy_stack_mecanum_wheel_platform/src:rw + + # Mount dimos source code for live development + - ../dimos:/home/p/pro/dimensional/dimos/dimos:rw + + # Mount bagfiles directory (optional) + - ./bagfiles:/ros2_ws/bagfiles:rw + + # Mount config files for easy editing + - ./config:/ros2_ws/config:rw + + # Device access (for joystick controllers, serial devices, and cameras) + devices: + - /dev/input:/dev/input + - /dev/dri:/dev/dri + # Uncomment if using real robot with motor controller + # - /dev/ttyACM0:/dev/ttyACM0 + # - /dev/ttyUSB0:/dev/ttyUSB0 + # Uncomment if using cameras + # - /dev/video0:/dev/video0 + + # Working directory + working_dir: /home/p/pro/dimensional/dimos + + # Command to run (can be overridden) + command: bash \ No newline at end of file diff --git a/ros_docker_integration/ros_launch_wrapper.py b/ros_docker_integration/ros_launch_wrapper.py new file mode 100755 index 0000000000..42f59fe606 --- /dev/null +++ b/ros_docker_integration/ros_launch_wrapper.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +""" +Wrapper script to properly handle ROS2 launch file shutdown. +This script ensures clean shutdown of all ROS nodes when receiving SIGINT. +""" + +import os +import sys +import signal +import subprocess +import time +import threading + +class ROSLaunchWrapper: + def __init__(self): + self.ros_process = None + self.dimos_process = None + self.shutdown_in_progress = False + + def signal_handler(self, signum, frame): + """Handle shutdown signals gracefully""" + if self.shutdown_in_progress: + return + + self.shutdown_in_progress = True + print("\n\nShutdown signal received. Stopping services gracefully...") + + # Stop DimOS first (it typically shuts down cleanly) + if self.dimos_process and self.dimos_process.poll() is None: + print("Stopping DimOS...") + self.dimos_process.terminate() + try: + self.dimos_process.wait(timeout=5) + print("DimOS stopped cleanly.") + except subprocess.TimeoutExpired: + print("Force stopping DimOS...") + self.dimos_process.kill() + self.dimos_process.wait() + + # Stop ROS - send SIGINT first for graceful shutdown + if self.ros_process and self.ros_process.poll() is None: + print("Stopping ROS nodes (this may take a moment)...") + + # Send SIGINT to trigger graceful ROS shutdown + self.ros_process.send_signal(signal.SIGINT) + + # Wait for graceful shutdown with timeout + try: + self.ros_process.wait(timeout=15) + print("ROS stopped cleanly.") + except subprocess.TimeoutExpired: + print("ROS is taking too long to stop. Sending SIGTERM...") + self.ros_process.terminate() + try: + self.ros_process.wait(timeout=5) + except subprocess.TimeoutExpired: + print("Force stopping ROS...") + self.ros_process.kill() + self.ros_process.wait() + + # Clean up any remaining processes + print("Cleaning up any remaining processes...") + cleanup_commands = [ + "pkill -f 'ros2' || true", + "pkill -f 'localPlanner' || true", + "pkill -f 'pathFollower' || true", + "pkill -f 'terrainAnalysis' || true", + "pkill -f 'sensorScanGeneration' || true", + "pkill -f 'vehicleSimulator' || true", + "pkill -f 'visualizationTools' || true", + "pkill -f 'far_planner' || true", + "pkill -f 'graph_decoder' || true", + ] + + for cmd in cleanup_commands: + subprocess.run(cmd, shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + + print("All services stopped.") + sys.exit(0) + + def run(self): + """Main execution function""" + # Register signal handlers + signal.signal(signal.SIGINT, self.signal_handler) + signal.signal(signal.SIGTERM, self.signal_handler) + + print("Starting ROS route planner and DimOS...") + + # Change to the ROS workspace directory + os.chdir("/ros2_ws/src/autonomy_stack_mecanum_wheel_platform") + + # Start ROS route planner + print("Starting ROS route planner...") + self.ros_process = subprocess.Popen( + ["bash", "./system_simulation_with_route_planner.sh"], + preexec_fn=os.setsid # Create new process group + ) + + # Wait for ROS to initialize + print("Waiting for ROS to initialize...") + time.sleep(5) + + # Start DimOS + print("Starting DimOS Unitree G1 controller...") + self.dimos_process = subprocess.Popen( + [sys.executable, "/home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py"] + ) + + print("Both systems are running. Press Ctrl+C to stop.") + print("") + + # Wait for processes + try: + # Monitor both processes + while True: + # Check if either process has died + if self.ros_process.poll() is not None: + print("ROS process has stopped unexpectedly.") + self.signal_handler(signal.SIGTERM, None) + break + if self.dimos_process.poll() is not None: + print("DimOS process has stopped.") + # DimOS stopping is less critical, but we should still clean up ROS + self.signal_handler(signal.SIGTERM, None) + break + time.sleep(1) + except KeyboardInterrupt: + pass # Signal handler will take care of cleanup + +if __name__ == "__main__": + wrapper = ROSLaunchWrapper() + wrapper.run() \ No newline at end of file diff --git a/ros_docker_integration/run_both.sh b/ros_docker_integration/run_both.sh new file mode 100755 index 0000000000..878022c28a --- /dev/null +++ b/ros_docker_integration/run_both.sh @@ -0,0 +1,109 @@ +#!/bin/bash +# Script to run both ROS route planner and DimOS together + +echo "Starting ROS route planner and DimOS..." + +# Variables for process IDs +ROS_PID="" +DIMOS_PID="" +SHUTDOWN_IN_PROGRESS=false + +# Function to handle cleanup +cleanup() { + if [ "$SHUTDOWN_IN_PROGRESS" = true ]; then + return + fi + SHUTDOWN_IN_PROGRESS=true + + echo "" + echo "Shutdown initiated. Stopping services..." + + # First, try to gracefully stop DimOS + if [ -n "$DIMOS_PID" ] && kill -0 $DIMOS_PID 2>/dev/null; then + echo "Stopping DimOS..." + kill -TERM $DIMOS_PID 2>/dev/null || true + + # Wait up to 5 seconds for DimOS to stop + for i in {1..10}; do + if ! kill -0 $DIMOS_PID 2>/dev/null; then + echo "DimOS stopped cleanly." + break + fi + sleep 0.5 + done + + # Force kill if still running + if kill -0 $DIMOS_PID 2>/dev/null; then + echo "Force stopping DimOS..." + kill -9 $DIMOS_PID 2>/dev/null || true + fi + fi + + # Then handle ROS - send SIGINT to the launch process group + if [ -n "$ROS_PID" ] && kill -0 $ROS_PID 2>/dev/null; then + echo "Stopping ROS nodes (this may take a moment)..." + + # Send SIGINT to the process group to properly trigger ROS shutdown + kill -INT -$ROS_PID 2>/dev/null || kill -INT $ROS_PID 2>/dev/null || true + + # Wait up to 15 seconds for graceful shutdown + for i in {1..30}; do + if ! kill -0 $ROS_PID 2>/dev/null; then + echo "ROS stopped cleanly." + break + fi + sleep 0.5 + done + + # If still running, send SIGTERM + if kill -0 $ROS_PID 2>/dev/null; then + echo "Sending SIGTERM to ROS..." + kill -TERM -$ROS_PID 2>/dev/null || kill -TERM $ROS_PID 2>/dev/null || true + sleep 2 + fi + + # Final resort: SIGKILL + if kill -0 $ROS_PID 2>/dev/null; then + echo "Force stopping ROS..." + kill -9 -$ROS_PID 2>/dev/null || kill -9 $ROS_PID 2>/dev/null || true + fi + fi + + # Clean up any remaining ROS2 processes + echo "Cleaning up any remaining processes..." + pkill -f "ros2" 2>/dev/null || true + pkill -f "localPlanner" 2>/dev/null || true + pkill -f "pathFollower" 2>/dev/null || true + pkill -f "terrainAnalysis" 2>/dev/null || true + pkill -f "sensorScanGeneration" 2>/dev/null || true + pkill -f "vehicleSimulator" 2>/dev/null || true + pkill -f "visualizationTools" 2>/dev/null || true + pkill -f "far_planner" 2>/dev/null || true + pkill -f "graph_decoder" 2>/dev/null || true + + echo "All services stopped." +} + +# Set up trap to call cleanup on exit +trap cleanup EXIT INT TERM + +# Start ROS route planner in background (in new process group) +echo "Starting ROS route planner..." +cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform +setsid bash -c './system_simulation_with_route_planner.sh' & +ROS_PID=$! + +# Wait a bit for ROS to initialize +echo "Waiting for ROS to initialize..." +sleep 5 + +# Start DimOS +echo "Starting DimOS Unitree G1 controller..." +python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py & +DIMOS_PID=$! + +echo "Both systems are running. Press Ctrl+C to stop." +echo "" + +# Wait for both processes +wait $ROS_PID $DIMOS_PID 2>/dev/null || true \ No newline at end of file diff --git a/ros_docker_integration/run_command.sh b/ros_docker_integration/run_command.sh new file mode 100755 index 0000000000..36187ac30d --- /dev/null +++ b/ros_docker_integration/run_command.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Get the directory where the script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$SCRIPT_DIR" + +# Check if command was provided +if [ $# -eq 0 ]; then + echo -e "${RED}Error: No command provided${NC}" + echo "" + echo "Usage: $0 \"command to run\"" + echo "" + echo "Examples:" + echo " $0 \"ros2 topic list\"" + echo " $0 \"ros2 launch base_autonomy unity_simulation_bringup.launch.py\"" + echo " $0 \"python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py\"" + echo " $0 \"bash\" # For interactive shell" + exit 1 +fi + +# Allow X server connection from Docker +xhost +local:docker 2>/dev/null || true + +echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}Running command in DimOS + ROS Container${NC}" +echo -e "${GREEN}=========================================${NC}" +echo "" +echo -e "${YELLOW}Command: $@${NC}" +echo "" + +# Go to dimos directory (parent of ros_docker_integration) for docker compose context +cd .. + +# Run the command in the container +docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c "$@" + +# Revoke X server access when done +xhost -local:docker 2>/dev/null || true \ No newline at end of file diff --git a/ros_docker_integration/shell.sh b/ros_docker_integration/shell.sh new file mode 100755 index 0000000000..70898400e8 --- /dev/null +++ b/ros_docker_integration/shell.sh @@ -0,0 +1,42 @@ +#!/bin/bash + +# Quick script to enter an interactive shell in the container + +set -e + +# Colors for output +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Get the directory where the script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$SCRIPT_DIR" + +# Allow X server connection from Docker +xhost +local:docker 2>/dev/null || true + +echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}Entering DimOS + ROS Container Shell${NC}" +echo -e "${GREEN}=========================================${NC}" +echo "" +echo -e "${YELLOW}Environment:${NC}" +echo " - ROS workspace: /ros2_ws" +echo " - DimOS path: /home/p/pro/dimensional/dimos" +echo " - Python venv: /home/p/pro/dimensional/dimos/.venv" +echo "" +echo -e "${YELLOW}Useful commands:${NC}" +echo " - ros2 topic list" +echo " - ros2 launch base_autonomy unity_simulation_bringup.launch.py" +echo " - source /home/p/pro/dimensional/dimos/.venv/bin/activate" +echo " - python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py" +echo "" + +# Go to dimos directory (parent of ros_docker_integration) for docker compose context +cd .. + +# Enter interactive shell +docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash + +# Revoke X server access when done +xhost -local:docker 2>/dev/null || true \ No newline at end of file diff --git a/ros_docker_integration/start.sh b/ros_docker_integration/start.sh new file mode 100755 index 0000000000..900729fbff --- /dev/null +++ b/ros_docker_integration/start.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Get the directory where the script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$SCRIPT_DIR" + +# Allow X server connection from Docker +xhost +local:docker 2>/dev/null || true + +echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}Starting DimOS + ROS Autonomy Stack Container${NC}" +echo -e "${GREEN}=========================================${NC}" +echo "" + +# Check if Unity models exist (warn if not) +if [ ! -d "unity_models" ] && [[ "$*" == *"--ros-planner"* || "$*" == *"--all"* ]]; then + echo -e "${YELLOW}WARNING: Unity models directory not found!${NC}" + echo "The Unity simulator may not work properly." + echo "Download from: https://drive.google.com/drive/folders/1G1JYkccvoSlxyySuTlPfvmrWoJUO8oSs" + echo "" +fi + +# Parse command line arguments +MODE="default" +if [[ "$1" == "--ros-planner" ]]; then + MODE="ros-planner" +elif [[ "$1" == "--dimos" ]]; then + MODE="dimos" +elif [[ "$1" == "--all" ]]; then + MODE="all" +elif [[ "$1" == "--help" || "$1" == "-h" ]]; then + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " --ros-planner Start with ROS route planner" + echo " --dimos Start with DimOS Unitree G1 controller" + echo " --all Start both ROS planner and DimOS" + echo " --help Show this help message" + echo "" + echo "Without options, starts an interactive bash shell" + exit 0 +fi + +# Go to dimos directory (parent of ros_docker_integration) for docker compose context +cd .. + +# Set the command based on mode +case $MODE in + "ros-planner") + echo -e "${YELLOW}Starting with ROS route planner...${NC}" + CMD="bash -c 'cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh'" + ;; + "dimos") + echo -e "${YELLOW}Starting with DimOS Unitree G1 controller...${NC}" + CMD="python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py" + ;; + "all") + echo -e "${YELLOW}Starting both ROS planner and DimOS...${NC}" + # Use the helper script to run both + CMD="/usr/local/bin/run_both.sh" + ;; + "default") + echo -e "${YELLOW}Starting interactive bash shell...${NC}" + echo "" + echo "You can manually run:" + echo " ROS planner: cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh" + echo " DimOS: python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py" + echo "" + CMD="bash" + ;; +esac + +# Run the container +docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack $CMD + +# Revoke X server access when done +xhost -local:docker 2>/dev/null || true + +echo "" +echo -e "${GREEN}Container stopped.${NC}" \ No newline at end of file diff --git a/ros_docker_integration/start_clean.sh b/ros_docker_integration/start_clean.sh new file mode 100755 index 0000000000..af1e8de11b --- /dev/null +++ b/ros_docker_integration/start_clean.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Get the directory where the script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$SCRIPT_DIR" + +# Allow X server connection from Docker +xhost +local:docker 2>/dev/null || true + +echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}Starting DimOS + ROS Autonomy Stack Container${NC}" +echo -e "${GREEN}(Using improved signal handling)${NC}" +echo -e "${GREEN}=========================================${NC}" +echo "" + +# Check if Unity models exist (warn if not) +if [ ! -d "unity_models" ] && [[ "$*" == *"--ros-planner"* || "$*" == *"--all"* ]]; then + echo -e "${YELLOW}WARNING: Unity models directory not found!${NC}" + echo "The Unity simulator may not work properly." + echo "Download from: https://drive.google.com/drive/folders/1G1JYkccvoSlxyySuTlPfvmrWoJUO8oSs" + echo "" +fi + +# Parse command line arguments +MODE="default" +if [[ "$1" == "--ros-planner" ]]; then + MODE="ros-planner" +elif [[ "$1" == "--dimos" ]]; then + MODE="dimos" +elif [[ "$1" == "--all" ]]; then + MODE="all" +elif [[ "$1" == "--help" || "$1" == "-h" ]]; then + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " --ros-planner Start with ROS route planner" + echo " --dimos Start with DimOS Unitree G1 controller" + echo " --all Start both ROS planner and DimOS (with clean shutdown)" + echo " --help Show this help message" + echo "" + echo "Without options, starts an interactive bash shell" + exit 0 +fi + +# Go to dimos directory (parent of ros_docker_integration) for docker compose context +cd .. + +# Set the command based on mode +case $MODE in + "ros-planner") + echo -e "${YELLOW}Starting with ROS route planner...${NC}" + CMD="bash -c 'cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh'" + ;; + "dimos") + echo -e "${YELLOW}Starting with DimOS Unitree G1 controller...${NC}" + CMD="python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py" + ;; + "all") + echo -e "${YELLOW}Starting both ROS planner and DimOS with improved signal handling...${NC}" + # Use the Python wrapper for better signal handling + CMD="python3 /usr/local/bin/ros_launch_wrapper.py" + ;; + "default") + echo -e "${YELLOW}Starting interactive bash shell...${NC}" + echo "" + echo "You can manually run:" + echo " ROS planner: cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh" + echo " DimOS: python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py" + echo " Both (clean shutdown): python3 /usr/local/bin/ros_launch_wrapper.py" + echo "" + CMD="bash" + ;; +esac + +# Run the container +docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack $CMD + +# Revoke X server access when done +xhost -local:docker 2>/dev/null || true + +echo "" +echo -e "${GREEN}Container stopped.${NC}" \ No newline at end of file diff --git a/ros_docker_integration/test_integration.sh b/ros_docker_integration/test_integration.sh new file mode 100755 index 0000000000..8df94e77bb --- /dev/null +++ b/ros_docker_integration/test_integration.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +# Test script to verify ROS-DimOS integration + +set -e + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +CYAN='\033[0;36m' +NC='\033[0m' # No Color + +echo -e "${CYAN}=========================================${NC}" +echo -e "${CYAN}Testing ROS-DimOS Integration${NC}" +echo -e "${CYAN}=========================================${NC}" +echo "" + +# Get the directory where the script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$SCRIPT_DIR" + +# Allow X server connection from Docker +xhost +local:docker 2>/dev/null || true + +# Go to dimos directory (parent of ros_docker_integration) for docker compose context +cd .. + +echo -e "${YELLOW}Test 1: Checking ROS environment...${NC}" +docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " + source /opt/ros/jazzy/setup.bash && + source /ros2_ws/install/setup.bash && + echo 'ROS_DISTRO: \$ROS_DISTRO' && + echo 'ROS workspace: /ros2_ws' && + ros2 pkg list | grep -E '(base_autonomy|vehicle_simulator)' | head -5 +" + +if [ $? -eq 0 ]; then + echo -e "${GREEN}✓ ROS environment is properly configured${NC}" +else + echo -e "${RED}✗ ROS environment check failed${NC}" +fi + +echo "" +echo -e "${YELLOW}Test 2: Checking DimOS Python environment...${NC}" +docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " + source /home/p/pro/dimensional/dimos/.venv/bin/activate && + python -c ' +import sys +print(f\"Python: {sys.version}\") +try: + import dimos + print(\"✓ DimOS package is importable\") +except ImportError as e: + print(f\"✗ DimOS import failed: {e}\") + sys.exit(1) + +try: + import cv2 + print(\"✓ OpenCV is available\") +except ImportError: + print(\"✗ OpenCV import failed\") + +try: + import torch + print(f\"✓ PyTorch is available\") +except ImportError: + print(\"✓ PyTorch not installed (CPU mode)\") +' +" + +if [ $? -eq 0 ]; then + echo -e "${GREEN}✓ DimOS Python environment is properly configured${NC}" +else + echo -e "${RED}✗ DimOS Python environment check failed${NC}" +fi + +echo "" +echo -e "${YELLOW}Test 3: Checking GPU access...${NC}" +docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " + if command -v nvidia-smi &> /dev/null; then + nvidia-smi --query-gpu=name,driver_version,memory.total --format=csv,noheader + echo '✓ GPU is accessible' + else + echo '✗ nvidia-smi not found - GPU may not be accessible' + fi +" + +echo "" +echo -e "${YELLOW}Test 4: Checking network configuration...${NC}" +docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " + echo 'Network mode: host' + echo -n 'Can access localhost: ' + if ping -c 1 localhost &> /dev/null; then + echo '✓ Yes' + else + echo '✗ No' + fi +" + +echo "" +echo -e "${YELLOW}Test 5: Checking ROS topic availability...${NC}" +docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " + source /opt/ros/jazzy/setup.bash && + source /ros2_ws/install/setup.bash && + timeout 2 ros2 topic list 2>/dev/null | head -10 || echo 'Note: No ROS nodes running (this is expected)' +" + +# Revoke X server access when done +xhost -local:docker 2>/dev/null || true + +echo "" +echo -e "${CYAN}=========================================${NC}" +echo -e "${CYAN}Integration Test Complete${NC}" +echo -e "${CYAN}=========================================${NC}" +echo "" +echo "To run the full system:" +echo -e "${YELLOW} ./start.sh --all${NC}" +echo "" +echo "For interactive testing:" +echo -e "${YELLOW} ./shell.sh${NC}" \ No newline at end of file From 264779f00ef36c308d7f217c17dedd613e7e6d54 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Sat, 25 Oct 2025 08:23:25 +0300 Subject: [PATCH 03/38] new path --- dimos/navigation/rosnav/nav_bot.py | 4 ++-- ros_docker_integration/README.md | 2 +- ros_docker_integration/ros_launch_wrapper.py | 22 +++++++++++++++++--- ros_docker_integration/run_both.sh | 2 +- ros_docker_integration/run_command.sh | 2 +- ros_docker_integration/shell.sh | 2 +- ros_docker_integration/start.sh | 4 ++-- ros_docker_integration/start_clean.sh | 4 ++-- 8 files changed, 29 insertions(+), 13 deletions(-) diff --git a/dimos/navigation/rosnav/nav_bot.py b/dimos/navigation/rosnav/nav_bot.py index 26060b4926..8e93c29c6f 100644 --- a/dimos/navigation/rosnav/nav_bot.py +++ b/dimos/navigation/rosnav/nav_bot.py @@ -391,8 +391,8 @@ def main(): nav_bot = NavBot() nav_bot.start() - logger.info("\nTesting navigation in 2 seconds...") - time.sleep(2) + logger.info("\nTesting navigation in 10 seconds...") + time.sleep(10) test_pose = PoseStamped( ts=time.time(), diff --git a/ros_docker_integration/README.md b/ros_docker_integration/README.md index b976057e6d..39afb5615d 100644 --- a/ros_docker_integration/README.md +++ b/ros_docker_integration/README.md @@ -82,7 +82,7 @@ cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform source /home/p/pro/dimensional/dimos/.venv/bin/activate # Run Unitree G1 controller -python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py +python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py # Or run other DimOS scripts python /home/p/pro/dimensional/dimos/dimos/your_script.py diff --git a/ros_docker_integration/ros_launch_wrapper.py b/ros_docker_integration/ros_launch_wrapper.py index 42f59fe606..7ef0c60eec 100755 --- a/ros_docker_integration/ros_launch_wrapper.py +++ b/ros_docker_integration/ros_launch_wrapper.py @@ -1,4 +1,18 @@ #!/usr/bin/env python3 +# Copyright 2025 Dimensional Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + """ Wrapper script to properly handle ROS2 launch file shutdown. This script ensures clean shutdown of all ROS nodes when receiving SIGINT. @@ -11,6 +25,7 @@ import time import threading + class ROSLaunchWrapper: def __init__(self): self.ros_process = None @@ -93,7 +108,7 @@ def run(self): print("Starting ROS route planner...") self.ros_process = subprocess.Popen( ["bash", "./system_simulation_with_route_planner.sh"], - preexec_fn=os.setsid # Create new process group + preexec_fn=os.setsid, # Create new process group ) # Wait for ROS to initialize @@ -103,7 +118,7 @@ def run(self): # Start DimOS print("Starting DimOS Unitree G1 controller...") self.dimos_process = subprocess.Popen( - [sys.executable, "/home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py"] + [sys.executable, "/home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py"] ) print("Both systems are running. Press Ctrl+C to stop.") @@ -127,6 +142,7 @@ def run(self): except KeyboardInterrupt: pass # Signal handler will take care of cleanup + if __name__ == "__main__": wrapper = ROSLaunchWrapper() - wrapper.run() \ No newline at end of file + wrapper.run() diff --git a/ros_docker_integration/run_both.sh b/ros_docker_integration/run_both.sh index 878022c28a..edbff60841 100755 --- a/ros_docker_integration/run_both.sh +++ b/ros_docker_integration/run_both.sh @@ -99,7 +99,7 @@ sleep 5 # Start DimOS echo "Starting DimOS Unitree G1 controller..." -python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py & +python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py & DIMOS_PID=$! echo "Both systems are running. Press Ctrl+C to stop." diff --git a/ros_docker_integration/run_command.sh b/ros_docker_integration/run_command.sh index 36187ac30d..387f45cff3 100755 --- a/ros_docker_integration/run_command.sh +++ b/ros_docker_integration/run_command.sh @@ -21,7 +21,7 @@ if [ $# -eq 0 ]; then echo "Examples:" echo " $0 \"ros2 topic list\"" echo " $0 \"ros2 launch base_autonomy unity_simulation_bringup.launch.py\"" - echo " $0 \"python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py\"" + echo " $0 \"python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py\"" echo " $0 \"bash\" # For interactive shell" exit 1 fi diff --git a/ros_docker_integration/shell.sh b/ros_docker_integration/shell.sh index 70898400e8..17e45c362b 100755 --- a/ros_docker_integration/shell.sh +++ b/ros_docker_integration/shell.sh @@ -29,7 +29,7 @@ echo -e "${YELLOW}Useful commands:${NC}" echo " - ros2 topic list" echo " - ros2 launch base_autonomy unity_simulation_bringup.launch.py" echo " - source /home/p/pro/dimensional/dimos/.venv/bin/activate" -echo " - python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py" +echo " - python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py" echo "" # Go to dimos directory (parent of ros_docker_integration) for docker compose context diff --git a/ros_docker_integration/start.sh b/ros_docker_integration/start.sh index 900729fbff..f744f2f9ef 100755 --- a/ros_docker_integration/start.sh +++ b/ros_docker_integration/start.sh @@ -60,7 +60,7 @@ case $MODE in ;; "dimos") echo -e "${YELLOW}Starting with DimOS Unitree G1 controller...${NC}" - CMD="python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py" + CMD="python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py" ;; "all") echo -e "${YELLOW}Starting both ROS planner and DimOS...${NC}" @@ -72,7 +72,7 @@ case $MODE in echo "" echo "You can manually run:" echo " ROS planner: cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh" - echo " DimOS: python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py" + echo " DimOS: python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py" echo "" CMD="bash" ;; diff --git a/ros_docker_integration/start_clean.sh b/ros_docker_integration/start_clean.sh index af1e8de11b..1e63376c1a 100755 --- a/ros_docker_integration/start_clean.sh +++ b/ros_docker_integration/start_clean.sh @@ -61,7 +61,7 @@ case $MODE in ;; "dimos") echo -e "${YELLOW}Starting with DimOS Unitree G1 controller...${NC}" - CMD="python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py" + CMD="python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py" ;; "all") echo -e "${YELLOW}Starting both ROS planner and DimOS with improved signal handling...${NC}" @@ -73,7 +73,7 @@ case $MODE in echo "" echo "You can manually run:" echo " ROS planner: cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh" - echo " DimOS: python /home/p/pro/dimensional/dimos/dimos/robot/unitree_webrtc/unitree_g1.py" + echo " DimOS: python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py" echo " Both (clean shutdown): python3 /usr/local/bin/ros_launch_wrapper.py" echo "" CMD="bash" From 6d3c7a9b77f05fe5442ff454c0ca402d5e435caa Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Sat, 25 Oct 2025 09:37:46 +0300 Subject: [PATCH 04/38] improve names --- ros_docker_integration/Dockerfile | 4 ++-- ros_docker_integration/README.md | 17 +++++++++-------- ros_docker_integration/docker-compose.yml | 8 ++++---- ros_docker_integration/ros_launch_wrapper.py | 4 ++-- ros_docker_integration/run_both.sh | 4 ++-- ros_docker_integration/run_command.sh | 2 +- ros_docker_integration/shell.sh | 8 ++++---- ros_docker_integration/start.sh | 6 +++--- ros_docker_integration/start_clean.sh | 6 +++--- ros_docker_integration/test_integration.sh | 2 +- 10 files changed, 31 insertions(+), 30 deletions(-) diff --git a/ros_docker_integration/Dockerfile b/ros_docker_integration/Dockerfile index 0502ba6e11..666e5a2f19 100644 --- a/ros_docker_integration/Dockerfile +++ b/ros_docker_integration/Dockerfile @@ -5,7 +5,7 @@ FROM osrf/ros:jazzy-desktop-full ENV DEBIAN_FRONTEND=noninteractive ENV ROS_DISTRO=jazzy ENV WORKSPACE=/ros2_ws -ENV DIMOS_PATH=/home/p/pro/dimensional/dimos +ENV DIMOS_PATH=/workspace/dimos # Install system dependencies RUN apt-get update && apt-get install -y \ @@ -103,7 +103,7 @@ source ${WORKSPACE}/install/setup.bash\n\ source ${DIMOS_PATH}/.venv/bin/activate\n\ \n\ # Export ROBOT_CONFIG_PATH for autonomy stack\n\ -export ROBOT_CONFIG_PATH="unitree/unitree_g1"\n\ +export ROBOT_CONFIG_PATH="mechanum_drive"\n\ \n\ # Execute the command\n\ exec "$@"' > /ros_entrypoint.sh && \ diff --git a/ros_docker_integration/README.md b/ros_docker_integration/README.md index 39afb5615d..fe4f79f9ba 100644 --- a/ros_docker_integration/README.md +++ b/ros_docker_integration/README.md @@ -28,7 +28,7 @@ This directory contains Docker configuration files to run DimOS and the ROS auto # Start with ROS route planner ./start.sh --ros-planner - # Start with DimOS Unitree G1 controller + # Start with DimOS navigation bot ./start.sh --dimos # Start both systems (basic) @@ -79,13 +79,13 @@ cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform ### DimOS ```bash # Activate virtual environment -source /home/p/pro/dimensional/dimos/.venv/bin/activate +source /workspace/dimos/.venv/bin/activate -# Run Unitree G1 controller -python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py +# Run navigation bot +python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py # Or run other DimOS scripts -python /home/p/pro/dimensional/dimos/dimos/your_script.py +python /workspace/dimos/dimos/your_script.py ``` ### ROS Commands @@ -108,13 +108,13 @@ ros2 topic echo /state_estimation Use the `run_command.sh` helper script to run custom commands: ```bash ./run_command.sh "ros2 topic list" -./run_command.sh "python /path/to/your/script.py" +./run_command.sh "python /workspace/dimos/dimos/your_script.py" ``` ## Development The docker-compose.yml mounts the following directories for live development: -- DimOS source: `../dimos` → `/home/p/pro/dimensional/dimos/dimos` +- DimOS source: `..` → `/workspace/dimos` - Autonomy stack source: `./autonomy_stack_mecanum_wheel_platform/src` → `/ros2_ws/src/autonomy_stack_mecanum_wheel_platform/src` Changes to these files will be reflected in the container without rebuilding. @@ -123,8 +123,9 @@ Changes to these files will be reflected in the container without rebuilding. The container sets: - `ROS_DISTRO=jazzy` -- `ROBOT_CONFIG_PATH=unitree/unitree_g1` +- `ROBOT_CONFIG_PATH=mechanum_drive` - `ROS_DOMAIN_ID=0` +- `DIMOS_PATH=/workspace/dimos` - GPU and display variables for GUI support ## Shutdown Handling diff --git a/ros_docker_integration/docker-compose.yml b/ros_docker_integration/docker-compose.yml index fc411c7400..df9332e62d 100644 --- a/ros_docker_integration/docker-compose.yml +++ b/ros_docker_integration/docker-compose.yml @@ -26,7 +26,7 @@ services: - NVIDIA_VISIBLE_DEVICES=all - NVIDIA_DRIVER_CAPABILITIES=all - ROS_DOMAIN_ID=0 - - ROBOT_CONFIG_PATH=unitree/unitree_g1 + - ROBOT_CONFIG_PATH=mechanum_drive # Volume mounts volumes: @@ -40,8 +40,8 @@ services: # Mount the autonomy stack source for development (optional - comment out if not needed) - ./autonomy_stack_mecanum_wheel_platform/src:/ros2_ws/src/autonomy_stack_mecanum_wheel_platform/src:rw - # Mount dimos source code for live development - - ../dimos:/home/p/pro/dimensional/dimos/dimos:rw + # Mount entire dimos directory for live development + - ..:/workspace/dimos:rw # Mount bagfiles directory (optional) - ./bagfiles:/ros2_ws/bagfiles:rw @@ -60,7 +60,7 @@ services: # - /dev/video0:/dev/video0 # Working directory - working_dir: /home/p/pro/dimensional/dimos + working_dir: /workspace/dimos # Command to run (can be overridden) command: bash \ No newline at end of file diff --git a/ros_docker_integration/ros_launch_wrapper.py b/ros_docker_integration/ros_launch_wrapper.py index 7ef0c60eec..11aa77157e 100755 --- a/ros_docker_integration/ros_launch_wrapper.py +++ b/ros_docker_integration/ros_launch_wrapper.py @@ -116,9 +116,9 @@ def run(self): time.sleep(5) # Start DimOS - print("Starting DimOS Unitree G1 controller...") + print("Starting DimOS navigation bot...") self.dimos_process = subprocess.Popen( - [sys.executable, "/home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py"] + [sys.executable, "/workspace/dimos/dimos/navigation/rosnav/nav_bot.py"] ) print("Both systems are running. Press Ctrl+C to stop.") diff --git a/ros_docker_integration/run_both.sh b/ros_docker_integration/run_both.sh index edbff60841..914d4c1ebb 100755 --- a/ros_docker_integration/run_both.sh +++ b/ros_docker_integration/run_both.sh @@ -98,8 +98,8 @@ echo "Waiting for ROS to initialize..." sleep 5 # Start DimOS -echo "Starting DimOS Unitree G1 controller..." -python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py & +echo "Starting DimOS navigation bot..." +python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py & DIMOS_PID=$! echo "Both systems are running. Press Ctrl+C to stop." diff --git a/ros_docker_integration/run_command.sh b/ros_docker_integration/run_command.sh index 387f45cff3..e9d5707c8d 100755 --- a/ros_docker_integration/run_command.sh +++ b/ros_docker_integration/run_command.sh @@ -21,7 +21,7 @@ if [ $# -eq 0 ]; then echo "Examples:" echo " $0 \"ros2 topic list\"" echo " $0 \"ros2 launch base_autonomy unity_simulation_bringup.launch.py\"" - echo " $0 \"python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py\"" + echo " $0 \"python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py\"" echo " $0 \"bash\" # For interactive shell" exit 1 fi diff --git a/ros_docker_integration/shell.sh b/ros_docker_integration/shell.sh index 17e45c362b..63c1970d6d 100755 --- a/ros_docker_integration/shell.sh +++ b/ros_docker_integration/shell.sh @@ -22,14 +22,14 @@ echo -e "${GREEN}=========================================${NC}" echo "" echo -e "${YELLOW}Environment:${NC}" echo " - ROS workspace: /ros2_ws" -echo " - DimOS path: /home/p/pro/dimensional/dimos" -echo " - Python venv: /home/p/pro/dimensional/dimos/.venv" +echo " - DimOS path: /workspace/dimos" +echo " - Python venv: /workspace/dimos/.venv" echo "" echo -e "${YELLOW}Useful commands:${NC}" echo " - ros2 topic list" echo " - ros2 launch base_autonomy unity_simulation_bringup.launch.py" -echo " - source /home/p/pro/dimensional/dimos/.venv/bin/activate" -echo " - python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py" +echo " - source /workspace/dimos/.venv/bin/activate" +echo " - python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" echo "" # Go to dimos directory (parent of ros_docker_integration) for docker compose context diff --git a/ros_docker_integration/start.sh b/ros_docker_integration/start.sh index f744f2f9ef..7da1300119 100755 --- a/ros_docker_integration/start.sh +++ b/ros_docker_integration/start.sh @@ -59,8 +59,8 @@ case $MODE in CMD="bash -c 'cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh'" ;; "dimos") - echo -e "${YELLOW}Starting with DimOS Unitree G1 controller...${NC}" - CMD="python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py" + echo -e "${YELLOW}Starting with DimOS navigation bot...${NC}" + CMD="python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" ;; "all") echo -e "${YELLOW}Starting both ROS planner and DimOS...${NC}" @@ -72,7 +72,7 @@ case $MODE in echo "" echo "You can manually run:" echo " ROS planner: cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh" - echo " DimOS: python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py" + echo " DimOS: python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" echo "" CMD="bash" ;; diff --git a/ros_docker_integration/start_clean.sh b/ros_docker_integration/start_clean.sh index 1e63376c1a..a6603cbb52 100755 --- a/ros_docker_integration/start_clean.sh +++ b/ros_docker_integration/start_clean.sh @@ -60,8 +60,8 @@ case $MODE in CMD="bash -c 'cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh'" ;; "dimos") - echo -e "${YELLOW}Starting with DimOS Unitree G1 controller...${NC}" - CMD="python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py" + echo -e "${YELLOW}Starting with DimOS navigation bot...${NC}" + CMD="python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" ;; "all") echo -e "${YELLOW}Starting both ROS planner and DimOS with improved signal handling...${NC}" @@ -73,7 +73,7 @@ case $MODE in echo "" echo "You can manually run:" echo " ROS planner: cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh" - echo " DimOS: python /home/p/pro/dimensional/dimos/dimos/navigation/rosnav/nav_bot.py" + echo " DimOS: python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" echo " Both (clean shutdown): python3 /usr/local/bin/ros_launch_wrapper.py" echo "" CMD="bash" diff --git a/ros_docker_integration/test_integration.sh b/ros_docker_integration/test_integration.sh index 8df94e77bb..6a17293990 100755 --- a/ros_docker_integration/test_integration.sh +++ b/ros_docker_integration/test_integration.sh @@ -44,7 +44,7 @@ fi echo "" echo -e "${YELLOW}Test 2: Checking DimOS Python environment...${NC}" docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " - source /home/p/pro/dimensional/dimos/.venv/bin/activate && + source /workspace/dimos/.venv/bin/activate && python -c ' import sys print(f\"Python: {sys.version}\") From da2c87fb8d603b85e84a9ee47b0e6a610fbc23c1 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Sat, 25 Oct 2025 23:57:12 +0300 Subject: [PATCH 05/38] fix it --- dimos/navigation/rosnav/nav_bot.py | 6 +- ros_docker_integration/Dockerfile | 13 ++-- ros_docker_integration/README.md | 15 ++++- ros_docker_integration/debug.sh | 31 +++++++++ ros_docker_integration/debug_paths.sh | 71 ++++++++++++++++++++ ros_docker_integration/ros_launch_wrapper.py | 62 +++++++++++++++-- ros_docker_integration/run_both.sh | 48 +++++++++++-- ros_docker_integration/shell.sh | 4 +- ros_docker_integration/test_integration.sh | 2 +- 9 files changed, 231 insertions(+), 21 deletions(-) create mode 100755 ros_docker_integration/debug.sh create mode 100755 ros_docker_integration/debug_paths.sh diff --git a/dimos/navigation/rosnav/nav_bot.py b/dimos/navigation/rosnav/nav_bot.py index 8e93c29c6f..6f4e84e0a0 100644 --- a/dimos/navigation/rosnav/nav_bot.py +++ b/dimos/navigation/rosnav/nav_bot.py @@ -391,13 +391,13 @@ def main(): nav_bot = NavBot() nav_bot.start() - logger.info("\nTesting navigation in 10 seconds...") - time.sleep(10) + logger.info("\nTesting navigation in 2 seconds...") + time.sleep(2) test_pose = PoseStamped( ts=time.time(), frame_id="map", - position=Vector3(1.0, 1.0, 0.0), + position=Vector3(2.0, 2.0, 0.0), orientation=Quaternion(0.0, 0.0, 0.0, 1.0), ) diff --git a/ros_docker_integration/Dockerfile b/ros_docker_integration/Dockerfile index 666e5a2f19..ddf7c28f96 100644 --- a/ros_docker_integration/Dockerfile +++ b/ros_docker_integration/Dockerfile @@ -79,17 +79,22 @@ RUN mkdir -p ${WORKSPACE}/src/autonomy_stack_mecanum_wheel_platform/src/base_aut RUN mkdir -p ${DIMOS_PATH} COPY . ${DIMOS_PATH}/ +# Create a virtual environment in /opt (not in /workspace/dimos) +# This ensures the venv won't be overwritten when we mount the host dimos directory +# The container will always use its own dependencies, independent of the host +RUN python3 -m venv /opt/dimos-venv + # Install Python dependencies for dimos WORKDIR ${DIMOS_PATH} -RUN python3 -m venv .venv && \ - /bin/bash -c "source .venv/bin/activate && \ +RUN /bin/bash -c "source /opt/dimos-venv/bin/activate && \ pip install --upgrade pip setuptools wheel && \ pip install -e .[cpu,dev] 'mmengine>=0.10.3' 'mmcv>=2.1.0'" # Copy helper scripts COPY ros_docker_integration/run_both.sh /usr/local/bin/run_both.sh COPY ros_docker_integration/ros_launch_wrapper.py /usr/local/bin/ros_launch_wrapper.py -RUN chmod +x /usr/local/bin/run_both.sh /usr/local/bin/ros_launch_wrapper.py +COPY ros_docker_integration/debug_paths.sh /usr/local/bin/debug_paths.sh +RUN chmod +x /usr/local/bin/run_both.sh /usr/local/bin/ros_launch_wrapper.py /usr/local/bin/debug_paths.sh # Set up entrypoint script RUN echo '#!/bin/bash\n\ @@ -100,7 +105,7 @@ source /opt/ros/${ROS_DISTRO}/setup.bash\n\ source ${WORKSPACE}/install/setup.bash\n\ \n\ # Activate Python virtual environment for dimos\n\ -source ${DIMOS_PATH}/.venv/bin/activate\n\ +source /opt/dimos-venv/bin/activate\n\ \n\ # Export ROBOT_CONFIG_PATH for autonomy stack\n\ export ROBOT_CONFIG_PATH="mechanum_drive"\n\ diff --git a/ros_docker_integration/README.md b/ros_docker_integration/README.md index fe4f79f9ba..5f1fbeedb4 100644 --- a/ros_docker_integration/README.md +++ b/ros_docker_integration/README.md @@ -52,6 +52,8 @@ ros_docker_integration/ ├── run_command.sh # Helper script for running custom commands ├── shell.sh # Quick access to interactive shell ├── test_integration.sh # Integration test script +├── debug.sh # Debug script to check paths and setup +├── debug_paths.sh # Internal debug script (runs in container) ├── README.md # This file ├── autonomy_stack_mecanum_wheel_platform/ # (Created by build.sh) ├── unity_models/ # (Optional) Unity environment models @@ -79,7 +81,7 @@ cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform ### DimOS ```bash # Activate virtual environment -source /workspace/dimos/.venv/bin/activate +source /opt/dimos-venv/bin/activate # Run navigation bot python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py @@ -119,6 +121,8 @@ The docker-compose.yml mounts the following directories for live development: Changes to these files will be reflected in the container without rebuilding. +**Note**: The Python virtual environment is installed at `/opt/dimos-venv` inside the container (not in the mounted `/workspace/dimos` directory). This ensures the container uses its own dependencies regardless of whether the host has a `.venv` or not. + ## Environment Variables The container sets: @@ -126,6 +130,7 @@ The container sets: - `ROBOT_CONFIG_PATH=mechanum_drive` - `ROS_DOMAIN_ID=0` - `DIMOS_PATH=/workspace/dimos` +- Python venv: `/opt/dimos-venv` - GPU and display variables for GUI support ## Shutdown Handling @@ -146,6 +151,14 @@ Uses the Python wrapper `ros_launch_wrapper.py` which provides: ## Troubleshooting +### DimOS Not Starting +If DimOS doesn't start when running `./start.sh --all`: +1. Run the debug script to check paths: `./debug.sh` +2. Rebuild the image: `./build.sh` +3. Check if nav_bot.py exists at `/workspace/dimos/dimos/navigation/rosnav/nav_bot.py` +4. Verify the Python virtual environment exists at `/opt/dimos-venv` (not in `/workspace/dimos/.venv`) +5. The container uses its own Python environment - host `.venv` is not needed + ### ROS Nodes Not Shutting Down Cleanly If you experience issues with ROS nodes hanging during shutdown: 1. Use `./start_clean.sh --all` instead of `./start.sh --all` diff --git a/ros_docker_integration/debug.sh b/ros_docker_integration/debug.sh new file mode 100755 index 0000000000..7e2635a166 --- /dev/null +++ b/ros_docker_integration/debug.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Quick script to debug paths in the container + +set -e + +# Colors for output +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Get the directory where the script is located +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$SCRIPT_DIR" + +# Allow X server connection from Docker +xhost +local:docker 2>/dev/null || true + +echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}Running debug diagnostics in container${NC}" +echo -e "${GREEN}=========================================${NC}" +echo "" + +# Go to dimos directory (parent of ros_docker_integration) for docker compose context +cd .. + +# Run the debug script in the container +docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack /usr/local/bin/debug_paths.sh + +# Revoke X server access when done +xhost -local:docker 2>/dev/null || true \ No newline at end of file diff --git a/ros_docker_integration/debug_paths.sh b/ros_docker_integration/debug_paths.sh new file mode 100755 index 0000000000..2927a6a1d2 --- /dev/null +++ b/ros_docker_integration/debug_paths.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# Debug script to check paths in the container + +echo "=========================================" +echo "Debugging DimOS paths in container" +echo "=========================================" +echo "" + +echo "1. Checking DimOS directory:" +if [ -d "/workspace/dimos" ]; then + echo " ✓ /workspace/dimos exists" + echo " Contents:" + ls -la /workspace/dimos/ | head -10 +else + echo " ✗ /workspace/dimos NOT FOUND" +fi + +echo "" +echo "2. Checking navigation directory:" +if [ -d "/workspace/dimos/dimos/navigation" ]; then + echo " ✓ /workspace/dimos/dimos/navigation exists" + echo " Contents:" + ls -la /workspace/dimos/dimos/navigation/ +else + echo " ✗ /workspace/dimos/dimos/navigation NOT FOUND" +fi + +echo "" +echo "3. Checking rosnav directory:" +if [ -d "/workspace/dimos/dimos/navigation/rosnav" ]; then + echo " ✓ /workspace/dimos/dimos/navigation/rosnav exists" + echo " Contents:" + ls -la /workspace/dimos/dimos/navigation/rosnav/ | head -10 +else + echo " ✗ /workspace/dimos/dimos/navigation/rosnav NOT FOUND" +fi + +echo "" +echo "4. Checking nav_bot.py:" +if [ -f "/workspace/dimos/dimos/navigation/rosnav/nav_bot.py" ]; then + echo " ✓ nav_bot.py exists" + echo " File info:" + ls -la /workspace/dimos/dimos/navigation/rosnav/nav_bot.py +else + echo " ✗ nav_bot.py NOT FOUND" +fi + +echo "" +echo "5. Checking Python virtual environment:" +if [ -d "/opt/dimos-venv" ]; then + echo " ✓ /opt/dimos-venv directory exists" + if [ -f "/opt/dimos-venv/bin/python" ]; then + echo " ✓ venv Python exists" + /opt/dimos-venv/bin/python --version + else + echo " ✗ venv Python NOT FOUND" + fi +else + echo " ✗ /opt/dimos-venv directory NOT FOUND" +fi + +echo "" +echo "6. Environment variables:" +echo " DIMOS_PATH=$DIMOS_PATH" +echo " ROBOT_CONFIG_PATH=$ROBOT_CONFIG_PATH" +echo " WORKSPACE=$WORKSPACE" +echo " PWD=$PWD" + +echo "" +echo "=========================================" \ No newline at end of file diff --git a/ros_docker_integration/ros_launch_wrapper.py b/ros_docker_integration/ros_launch_wrapper.py index 11aa77157e..851e74dae3 100755 --- a/ros_docker_integration/ros_launch_wrapper.py +++ b/ros_docker_integration/ros_launch_wrapper.py @@ -117,11 +117,63 @@ def run(self): # Start DimOS print("Starting DimOS navigation bot...") - self.dimos_process = subprocess.Popen( - [sys.executable, "/workspace/dimos/dimos/navigation/rosnav/nav_bot.py"] - ) - print("Both systems are running. Press Ctrl+C to stop.") + # Check if the script exists + nav_bot_path = "/workspace/dimos/dimos/navigation/rosnav/nav_bot.py" + venv_python = "/opt/dimos-venv/bin/python" + + if not os.path.exists(nav_bot_path): + print(f"ERROR: nav_bot.py not found at {nav_bot_path}") + nav_dir = "/workspace/dimos/dimos/navigation/" + if os.path.exists(nav_dir): + print(f"Contents of {nav_dir}:") + for item in os.listdir(nav_dir): + print(f" - {item}") + else: + print(f"Directory not found: {nav_dir}") + return + + if not os.path.exists(venv_python): + print(f"WARNING: venv Python not found at {venv_python}, using system Python") + venv_python = sys.executable + + print(f"Using Python: {venv_python}") + print(f"Starting script: {nav_bot_path}") + + # Use the venv Python explicitly + try: + self.dimos_process = subprocess.Popen( + [venv_python, nav_bot_path], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + bufsize=1, + universal_newlines=True + ) + + # Give it a moment to start and check if it's still running + time.sleep(2) + poll_result = self.dimos_process.poll() + if poll_result is not None: + # Process exited immediately + stdout, stderr = self.dimos_process.communicate(timeout=1) + print(f"ERROR: DimOS failed to start (exit code: {poll_result})") + if stdout: + print(f"STDOUT: {stdout}") + if stderr: + print(f"STDERR: {stderr}") + self.dimos_process = None + else: + print(f"DimOS started successfully (PID: {self.dimos_process.pid})") + + except Exception as e: + print(f"ERROR: Failed to start DimOS: {e}") + self.dimos_process = None + + if self.dimos_process: + print("Both systems are running. Press Ctrl+C to stop.") + else: + print("ROS is running (DimOS failed to start). Press Ctrl+C to stop.") print("") # Wait for processes @@ -133,7 +185,7 @@ def run(self): print("ROS process has stopped unexpectedly.") self.signal_handler(signal.SIGTERM, None) break - if self.dimos_process.poll() is not None: + if self.dimos_process and self.dimos_process.poll() is not None: print("DimOS process has stopped.") # DimOS stopping is less critical, but we should still clean up ROS self.signal_handler(signal.SIGTERM, None) diff --git a/ros_docker_integration/run_both.sh b/ros_docker_integration/run_both.sh index 914d4c1ebb..d27a19758e 100755 --- a/ros_docker_integration/run_both.sh +++ b/ros_docker_integration/run_both.sh @@ -99,11 +99,49 @@ sleep 5 # Start DimOS echo "Starting DimOS navigation bot..." -python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py & -DIMOS_PID=$! -echo "Both systems are running. Press Ctrl+C to stop." +# Check if the script exists +if [ ! -f "/workspace/dimos/dimos/navigation/rosnav/nav_bot.py" ]; then + echo "ERROR: nav_bot.py not found at /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" + echo "Available files in /workspace/dimos/dimos/navigation/:" + ls -la /workspace/dimos/dimos/navigation/ 2>/dev/null || echo "Directory not found" +else + echo "Found nav_bot.py, activating virtual environment..." + if [ -f "/opt/dimos-venv/bin/activate" ]; then + source /opt/dimos-venv/bin/activate + echo "Python path: $(which python)" + echo "Python version: $(python --version)" + else + echo "WARNING: Virtual environment not found at /opt/dimos-venv, using system Python" + fi + + echo "Starting nav_bot.py..." + # Capture any startup errors + python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py 2>&1 & + DIMOS_PID=$! + + # Give it a moment to start and check if it's still running + sleep 2 + if kill -0 $DIMOS_PID 2>/dev/null; then + echo "DimOS started successfully with PID: $DIMOS_PID" + else + echo "ERROR: DimOS failed to start (process exited immediately)" + echo "Check the logs above for error messages" + DIMOS_PID="" + fi +fi + +echo "" +if [ -n "$DIMOS_PID" ]; then + echo "Both systems are running. Press Ctrl+C to stop." +else + echo "ROS is running (DimOS failed to start). Press Ctrl+C to stop." +fi echo "" -# Wait for both processes -wait $ROS_PID $DIMOS_PID 2>/dev/null || true \ No newline at end of file +# Wait for processes +if [ -n "$DIMOS_PID" ]; then + wait $ROS_PID $DIMOS_PID 2>/dev/null || true +else + wait $ROS_PID 2>/dev/null || true +fi \ No newline at end of file diff --git a/ros_docker_integration/shell.sh b/ros_docker_integration/shell.sh index 63c1970d6d..d907933c5f 100755 --- a/ros_docker_integration/shell.sh +++ b/ros_docker_integration/shell.sh @@ -23,12 +23,12 @@ echo "" echo -e "${YELLOW}Environment:${NC}" echo " - ROS workspace: /ros2_ws" echo " - DimOS path: /workspace/dimos" -echo " - Python venv: /workspace/dimos/.venv" +echo " - Python venv: /opt/dimos-venv" echo "" echo -e "${YELLOW}Useful commands:${NC}" echo " - ros2 topic list" echo " - ros2 launch base_autonomy unity_simulation_bringup.launch.py" -echo " - source /workspace/dimos/.venv/bin/activate" +echo " - source /opt/dimos-venv/bin/activate" echo " - python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" echo "" diff --git a/ros_docker_integration/test_integration.sh b/ros_docker_integration/test_integration.sh index 6a17293990..16b6460c46 100755 --- a/ros_docker_integration/test_integration.sh +++ b/ros_docker_integration/test_integration.sh @@ -44,7 +44,7 @@ fi echo "" echo -e "${YELLOW}Test 2: Checking DimOS Python environment...${NC}" docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " - source /workspace/dimos/.venv/bin/activate && + source /opt/dimos-venv/bin/activate && python -c ' import sys print(f\"Python: {sys.version}\") From 6cc7cf5baf6a24182019725b132e46451209a80e Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Sun, 26 Oct 2025 01:16:57 +0300 Subject: [PATCH 06/38] Add initial environment. --- data/.lfs/office_building_1.tar.gz | 3 + ros_docker_integration/README.md | 52 +-------- ros_docker_integration/build.sh | 33 +----- ros_docker_integration/test_integration.sh | 121 --------------------- 4 files changed, 14 insertions(+), 195 deletions(-) create mode 100644 data/.lfs/office_building_1.tar.gz delete mode 100755 ros_docker_integration/test_integration.sh diff --git a/data/.lfs/office_building_1.tar.gz b/data/.lfs/office_building_1.tar.gz new file mode 100644 index 0000000000..0dc013bd94 --- /dev/null +++ b/data/.lfs/office_building_1.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:70aac31ca76597b3eee1ddfcbe2ba71d432fd427176f66d8281d75da76641f49 +size 1061581652 diff --git a/ros_docker_integration/README.md b/ros_docker_integration/README.md index 5f1fbeedb4..dfcb92f9d6 100644 --- a/ros_docker_integration/README.md +++ b/ros_docker_integration/README.md @@ -4,10 +4,9 @@ This directory contains Docker configuration files to run DimOS and the ROS auto ## Prerequisites -- Docker with `docker compose` support -- NVIDIA GPU with drivers installed -- NVIDIA Container Toolkit (nvidia-docker2) -- X11 server for GUI applications (RVIZ, Unity simulator) +1. **Install Docker with `docker compose` support**. Follow the [official Docker installation guide](https://docs.docker.com/engine/install/). +2. **Install NVIDIA GPU drivers**. See [NVIDIA driver installation](https://www.nvidia.com/download/index.aspx). +3. **Install NVIDIA Container Toolkit**. Follow the [installation guide](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html). ## Quick Start @@ -20,54 +19,13 @@ This directory contains Docker configuration files to run DimOS and the ROS auto - Build a Docker image with both ROS and DimOS dependencies - Set up the environment for both systems + Note that the build will take over 10 minutes and build an image over 30GiB. + 2. **Run the container:** ```bash - # Interactive bash shell (default) - ./start.sh - - # Start with ROS route planner - ./start.sh --ros-planner - - # Start with DimOS navigation bot - ./start.sh --dimos - - # Start both systems (basic) ./start.sh --all - - # Start both systems with improved shutdown handling (recommended) - ./start_clean.sh --all ``` -## Directory Structure - -``` -ros_docker_integration/ -├── Dockerfile # Combined Dockerfile for ROS + DimOS -├── docker-compose.yml # Docker Compose configuration -├── build.sh # Script to clone repos and build image -├── start.sh # Script to run the container (basic) -├── start_clean.sh # Script with improved shutdown handling -├── run_both.sh # Bash helper to run both ROS and DimOS -├── ros_launch_wrapper.py # Python wrapper for clean ROS shutdown -├── run_command.sh # Helper script for running custom commands -├── shell.sh # Quick access to interactive shell -├── test_integration.sh # Integration test script -├── debug.sh # Debug script to check paths and setup -├── debug_paths.sh # Internal debug script (runs in container) -├── README.md # This file -├── autonomy_stack_mecanum_wheel_platform/ # (Created by build.sh) -├── unity_models/ # (Optional) Unity environment models -├── bagfiles/ # (Optional) ROS bag files -└── config/ # (Optional) Configuration files -``` - -## Unity Models (Optional) - -For the Unity simulator to work properly, download the Unity environment models from: -https://drive.google.com/drive/folders/1G1JYkccvoSlxyySuTlPfvmrWoJUO8oSs - -Extract them to: `ros_docker_integration/unity_models/` - ## Manual Commands Once inside the container, you can manually run: diff --git a/ros_docker_integration/build.sh b/ros_docker_integration/build.sh index 603a841324..085a215e76 100755 --- a/ros_docker_integration/build.sh +++ b/ros_docker_integration/build.sh @@ -2,57 +2,41 @@ set -e -# Colors for output -RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' -NC='\033[0m' # No Color +NC='\033[0m' echo -e "${GREEN}=========================================${NC}" echo -e "${GREEN}Building DimOS + ROS Autonomy Stack Docker Image${NC}" echo -e "${GREEN}=========================================${NC}" echo "" -# Get the directory where the script is located SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$SCRIPT_DIR" -# Check if autonomy stack already exists if [ ! -d "autonomy_stack_mecanum_wheel_platform" ]; then echo -e "${YELLOW}Cloning autonomy_stack_mecanum_wheel_platform repository...${NC}" git clone https://github.com/alexlin2/autonomy_stack_mecanum_wheel_platform.git echo -e "${GREEN}Repository cloned successfully!${NC}" fi -# Check if Unity models directory exists (warn if not) if [ ! -d "unity_models" ]; then - echo "" - echo -e "${YELLOW}WARNING: Unity models directory not found!${NC}" - echo "If you want to use the Unity simulator, please download Unity environment models" - echo "and extract them to: ${SCRIPT_DIR}/unity_models/" - echo "Download from: https://drive.google.com/drive/folders/1G1JYkccvoSlxyySuTlPfvmrWoJUO8oSs" - echo "" - read -p "Continue building without Unity models? (y/n) " -n 1 -r - echo - if [[ ! $REPLY =~ ^[Yy]$ ]]; then - exit 1 - fi + echo -e "${YELLOW}Using office_building_1 as the Unity environment...${NC}" + tar -xf ../data/.lfs/office_building_1.tar.gz + mv office_building_1 unity_models fi -# Build the Docker image using docker compose echo "" echo -e "${YELLOW}Building Docker image with docker compose...${NC}" -echo "This may take a while as it needs to:" +echo "This will take a while as it needs to:" echo " - Download base ROS Jazzy image" echo " - Install ROS packages and dependencies" echo " - Build the autonomy stack" echo " - Install Python dependencies for DimOS" echo "" -# Go to the dimos directory (parent of ros_docker_integration) for the build context cd .. -# Build using docker compose docker compose -f ros_docker_integration/docker-compose.yml build echo "" @@ -61,10 +45,5 @@ echo -e "${GREEN}Docker image built successfully!${NC}" echo -e "${GREEN}=========================================${NC}" echo "" echo "You can now run the container using:" -echo -e "${YELLOW} ./start.sh${NC}" +echo -e "${YELLOW} ./start.sh --all${NC}" echo "" -echo "Available options:" -echo " - Run with default configuration (starts bash): ./start.sh" -echo " - Run with ROS route planner: ./start.sh --ros-planner" -echo " - Run with DimOS only: ./start.sh --dimos" -echo " - Run with both: ./start.sh --all" diff --git a/ros_docker_integration/test_integration.sh b/ros_docker_integration/test_integration.sh deleted file mode 100755 index 16b6460c46..0000000000 --- a/ros_docker_integration/test_integration.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/bash - -# Test script to verify ROS-DimOS integration - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -CYAN='\033[0;36m' -NC='\033[0m' # No Color - -echo -e "${CYAN}=========================================${NC}" -echo -e "${CYAN}Testing ROS-DimOS Integration${NC}" -echo -e "${CYAN}=========================================${NC}" -echo "" - -# Get the directory where the script is located -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd "$SCRIPT_DIR" - -# Allow X server connection from Docker -xhost +local:docker 2>/dev/null || true - -# Go to dimos directory (parent of ros_docker_integration) for docker compose context -cd .. - -echo -e "${YELLOW}Test 1: Checking ROS environment...${NC}" -docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " - source /opt/ros/jazzy/setup.bash && - source /ros2_ws/install/setup.bash && - echo 'ROS_DISTRO: \$ROS_DISTRO' && - echo 'ROS workspace: /ros2_ws' && - ros2 pkg list | grep -E '(base_autonomy|vehicle_simulator)' | head -5 -" - -if [ $? -eq 0 ]; then - echo -e "${GREEN}✓ ROS environment is properly configured${NC}" -else - echo -e "${RED}✗ ROS environment check failed${NC}" -fi - -echo "" -echo -e "${YELLOW}Test 2: Checking DimOS Python environment...${NC}" -docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " - source /opt/dimos-venv/bin/activate && - python -c ' -import sys -print(f\"Python: {sys.version}\") -try: - import dimos - print(\"✓ DimOS package is importable\") -except ImportError as e: - print(f\"✗ DimOS import failed: {e}\") - sys.exit(1) - -try: - import cv2 - print(\"✓ OpenCV is available\") -except ImportError: - print(\"✗ OpenCV import failed\") - -try: - import torch - print(f\"✓ PyTorch is available\") -except ImportError: - print(\"✓ PyTorch not installed (CPU mode)\") -' -" - -if [ $? -eq 0 ]; then - echo -e "${GREEN}✓ DimOS Python environment is properly configured${NC}" -else - echo -e "${RED}✗ DimOS Python environment check failed${NC}" -fi - -echo "" -echo -e "${YELLOW}Test 3: Checking GPU access...${NC}" -docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " - if command -v nvidia-smi &> /dev/null; then - nvidia-smi --query-gpu=name,driver_version,memory.total --format=csv,noheader - echo '✓ GPU is accessible' - else - echo '✗ nvidia-smi not found - GPU may not be accessible' - fi -" - -echo "" -echo -e "${YELLOW}Test 4: Checking network configuration...${NC}" -docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " - echo 'Network mode: host' - echo -n 'Can access localhost: ' - if ping -c 1 localhost &> /dev/null; then - echo '✓ Yes' - else - echo '✗ No' - fi -" - -echo "" -echo -e "${YELLOW}Test 5: Checking ROS topic availability...${NC}" -docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c " - source /opt/ros/jazzy/setup.bash && - source /ros2_ws/install/setup.bash && - timeout 2 ros2 topic list 2>/dev/null | head -10 || echo 'Note: No ROS nodes running (this is expected)' -" - -# Revoke X server access when done -xhost -local:docker 2>/dev/null || true - -echo "" -echo -e "${CYAN}=========================================${NC}" -echo -e "${CYAN}Integration Test Complete${NC}" -echo -e "${CYAN}=========================================${NC}" -echo "" -echo "To run the full system:" -echo -e "${YELLOW} ./start.sh --all${NC}" -echo "" -echo "For interactive testing:" -echo -e "${YELLOW} ./shell.sh${NC}" \ No newline at end of file From ee8fcf05c4c51019f5ee2974db3855d6b1891b26 Mon Sep 17 00:00:00 2001 From: paul-nechifor <1262969+paul-nechifor@users.noreply.github.com> Date: Sat, 25 Oct 2025 22:21:19 +0000 Subject: [PATCH 07/38] CI code cleanup --- ros_docker_integration/ros_launch_wrapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ros_docker_integration/ros_launch_wrapper.py b/ros_docker_integration/ros_launch_wrapper.py index 851e74dae3..00745ff7c7 100755 --- a/ros_docker_integration/ros_launch_wrapper.py +++ b/ros_docker_integration/ros_launch_wrapper.py @@ -148,7 +148,7 @@ def run(self): stderr=subprocess.PIPE, text=True, bufsize=1, - universal_newlines=True + universal_newlines=True, ) # Give it a moment to start and check if it's still running From 2d65c977b978686b09e25bc956f508df8cba47c8 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Sun, 26 Oct 2025 02:53:27 +0300 Subject: [PATCH 08/38] remove more unnecessary stuff --- ros_docker_integration/Dockerfile | 3 +- ros_docker_integration/README.md | 70 +-------------------- ros_docker_integration/debug.sh | 31 --------- ros_docker_integration/debug_paths.sh | 71 --------------------- ros_docker_integration/start_clean.sh | 90 --------------------------- 5 files changed, 2 insertions(+), 263 deletions(-) delete mode 100755 ros_docker_integration/debug.sh delete mode 100755 ros_docker_integration/debug_paths.sh delete mode 100755 ros_docker_integration/start_clean.sh diff --git a/ros_docker_integration/Dockerfile b/ros_docker_integration/Dockerfile index ddf7c28f96..62e5834567 100644 --- a/ros_docker_integration/Dockerfile +++ b/ros_docker_integration/Dockerfile @@ -93,8 +93,7 @@ RUN /bin/bash -c "source /opt/dimos-venv/bin/activate && \ # Copy helper scripts COPY ros_docker_integration/run_both.sh /usr/local/bin/run_both.sh COPY ros_docker_integration/ros_launch_wrapper.py /usr/local/bin/ros_launch_wrapper.py -COPY ros_docker_integration/debug_paths.sh /usr/local/bin/debug_paths.sh -RUN chmod +x /usr/local/bin/run_both.sh /usr/local/bin/ros_launch_wrapper.py /usr/local/bin/debug_paths.sh +RUN chmod +x /usr/local/bin/run_both.sh /usr/local/bin/ros_launch_wrapper.py # Set up entrypoint script RUN echo '#!/bin/bash\n\ diff --git a/ros_docker_integration/README.md b/ros_docker_integration/README.md index dfcb92f9d6..35edcbad60 100644 --- a/ros_docker_integration/README.md +++ b/ros_docker_integration/README.md @@ -79,72 +79,4 @@ The docker-compose.yml mounts the following directories for live development: Changes to these files will be reflected in the container without rebuilding. -**Note**: The Python virtual environment is installed at `/opt/dimos-venv` inside the container (not in the mounted `/workspace/dimos` directory). This ensures the container uses its own dependencies regardless of whether the host has a `.venv` or not. - -## Environment Variables - -The container sets: -- `ROS_DISTRO=jazzy` -- `ROBOT_CONFIG_PATH=mechanum_drive` -- `ROS_DOMAIN_ID=0` -- `DIMOS_PATH=/workspace/dimos` -- Python venv: `/opt/dimos-venv` -- GPU and display variables for GUI support - -## Shutdown Handling - -The integration provides two methods for running both systems together: - -### Basic Method (`./start.sh --all`) -Uses the bash script `run_both.sh` with signal trapping and process group management. - -### Improved Method (`./start_clean.sh --all`) -Uses the Python wrapper `ros_launch_wrapper.py` which provides: -- Proper signal forwarding to ROS launch system -- Graceful shutdown with timeouts -- Automatic cleanup of orphaned ROS nodes -- Better handling of ROS2's complex process hierarchy - -**Recommended**: Use `./start_clean.sh --all` for the cleanest shutdown experience. - -## Troubleshooting - -### DimOS Not Starting -If DimOS doesn't start when running `./start.sh --all`: -1. Run the debug script to check paths: `./debug.sh` -2. Rebuild the image: `./build.sh` -3. Check if nav_bot.py exists at `/workspace/dimos/dimos/navigation/rosnav/nav_bot.py` -4. Verify the Python virtual environment exists at `/opt/dimos-venv` (not in `/workspace/dimos/.venv`) -5. The container uses its own Python environment - host `.venv` is not needed - -### ROS Nodes Not Shutting Down Cleanly -If you experience issues with ROS nodes hanging during shutdown: -1. Use `./start_clean.sh --all` instead of `./start.sh --all` -2. The improved handler will automatically clean up remaining processes -3. If issues persist, you can manually clean up with: - ```bash - docker compose -f ros_docker_integration/docker-compose.yml down - ``` - -### X11 Display Issues -If you get display errors: -```bash -xhost +local:docker -``` - -### GPU Not Available -Ensure NVIDIA Container Toolkit is installed: -```bash -sudo apt-get install nvidia-container-toolkit -sudo systemctl restart docker -``` - -### Permission Issues -The container runs with `--privileged` and `--network=host` for hardware access. - -## Notes - -- The container uses `--network=host` for ROS communication -- GPU passthrough is enabled via `runtime: nvidia` -- X11 forwarding is configured for GUI applications -- The ROS workspace is built without SLAM and Mid-360 packages (simulation mode) \ No newline at end of file +**Note**: The Python virtual environment is installed at `/opt/dimos-venv` inside the container (not in the mounted `/workspace/dimos` directory). This ensures the container uses its own dependencies regardless of whether the host has a `.venv` or not. \ No newline at end of file diff --git a/ros_docker_integration/debug.sh b/ros_docker_integration/debug.sh deleted file mode 100755 index 7e2635a166..0000000000 --- a/ros_docker_integration/debug.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -# Quick script to debug paths in the container - -set -e - -# Colors for output -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -# Get the directory where the script is located -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd "$SCRIPT_DIR" - -# Allow X server connection from Docker -xhost +local:docker 2>/dev/null || true - -echo -e "${GREEN}=========================================${NC}" -echo -e "${GREEN}Running debug diagnostics in container${NC}" -echo -e "${GREEN}=========================================${NC}" -echo "" - -# Go to dimos directory (parent of ros_docker_integration) for docker compose context -cd .. - -# Run the debug script in the container -docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack /usr/local/bin/debug_paths.sh - -# Revoke X server access when done -xhost -local:docker 2>/dev/null || true \ No newline at end of file diff --git a/ros_docker_integration/debug_paths.sh b/ros_docker_integration/debug_paths.sh deleted file mode 100755 index 2927a6a1d2..0000000000 --- a/ros_docker_integration/debug_paths.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash - -# Debug script to check paths in the container - -echo "=========================================" -echo "Debugging DimOS paths in container" -echo "=========================================" -echo "" - -echo "1. Checking DimOS directory:" -if [ -d "/workspace/dimos" ]; then - echo " ✓ /workspace/dimos exists" - echo " Contents:" - ls -la /workspace/dimos/ | head -10 -else - echo " ✗ /workspace/dimos NOT FOUND" -fi - -echo "" -echo "2. Checking navigation directory:" -if [ -d "/workspace/dimos/dimos/navigation" ]; then - echo " ✓ /workspace/dimos/dimos/navigation exists" - echo " Contents:" - ls -la /workspace/dimos/dimos/navigation/ -else - echo " ✗ /workspace/dimos/dimos/navigation NOT FOUND" -fi - -echo "" -echo "3. Checking rosnav directory:" -if [ -d "/workspace/dimos/dimos/navigation/rosnav" ]; then - echo " ✓ /workspace/dimos/dimos/navigation/rosnav exists" - echo " Contents:" - ls -la /workspace/dimos/dimos/navigation/rosnav/ | head -10 -else - echo " ✗ /workspace/dimos/dimos/navigation/rosnav NOT FOUND" -fi - -echo "" -echo "4. Checking nav_bot.py:" -if [ -f "/workspace/dimos/dimos/navigation/rosnav/nav_bot.py" ]; then - echo " ✓ nav_bot.py exists" - echo " File info:" - ls -la /workspace/dimos/dimos/navigation/rosnav/nav_bot.py -else - echo " ✗ nav_bot.py NOT FOUND" -fi - -echo "" -echo "5. Checking Python virtual environment:" -if [ -d "/opt/dimos-venv" ]; then - echo " ✓ /opt/dimos-venv directory exists" - if [ -f "/opt/dimos-venv/bin/python" ]; then - echo " ✓ venv Python exists" - /opt/dimos-venv/bin/python --version - else - echo " ✗ venv Python NOT FOUND" - fi -else - echo " ✗ /opt/dimos-venv directory NOT FOUND" -fi - -echo "" -echo "6. Environment variables:" -echo " DIMOS_PATH=$DIMOS_PATH" -echo " ROBOT_CONFIG_PATH=$ROBOT_CONFIG_PATH" -echo " WORKSPACE=$WORKSPACE" -echo " PWD=$PWD" - -echo "" -echo "=========================================" \ No newline at end of file diff --git a/ros_docker_integration/start_clean.sh b/ros_docker_integration/start_clean.sh deleted file mode 100755 index a6603cbb52..0000000000 --- a/ros_docker_integration/start_clean.sh +++ /dev/null @@ -1,90 +0,0 @@ -#!/bin/bash - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -# Get the directory where the script is located -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd "$SCRIPT_DIR" - -# Allow X server connection from Docker -xhost +local:docker 2>/dev/null || true - -echo -e "${GREEN}=========================================${NC}" -echo -e "${GREEN}Starting DimOS + ROS Autonomy Stack Container${NC}" -echo -e "${GREEN}(Using improved signal handling)${NC}" -echo -e "${GREEN}=========================================${NC}" -echo "" - -# Check if Unity models exist (warn if not) -if [ ! -d "unity_models" ] && [[ "$*" == *"--ros-planner"* || "$*" == *"--all"* ]]; then - echo -e "${YELLOW}WARNING: Unity models directory not found!${NC}" - echo "The Unity simulator may not work properly." - echo "Download from: https://drive.google.com/drive/folders/1G1JYkccvoSlxyySuTlPfvmrWoJUO8oSs" - echo "" -fi - -# Parse command line arguments -MODE="default" -if [[ "$1" == "--ros-planner" ]]; then - MODE="ros-planner" -elif [[ "$1" == "--dimos" ]]; then - MODE="dimos" -elif [[ "$1" == "--all" ]]; then - MODE="all" -elif [[ "$1" == "--help" || "$1" == "-h" ]]; then - echo "Usage: $0 [OPTIONS]" - echo "" - echo "Options:" - echo " --ros-planner Start with ROS route planner" - echo " --dimos Start with DimOS Unitree G1 controller" - echo " --all Start both ROS planner and DimOS (with clean shutdown)" - echo " --help Show this help message" - echo "" - echo "Without options, starts an interactive bash shell" - exit 0 -fi - -# Go to dimos directory (parent of ros_docker_integration) for docker compose context -cd .. - -# Set the command based on mode -case $MODE in - "ros-planner") - echo -e "${YELLOW}Starting with ROS route planner...${NC}" - CMD="bash -c 'cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh'" - ;; - "dimos") - echo -e "${YELLOW}Starting with DimOS navigation bot...${NC}" - CMD="python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" - ;; - "all") - echo -e "${YELLOW}Starting both ROS planner and DimOS with improved signal handling...${NC}" - # Use the Python wrapper for better signal handling - CMD="python3 /usr/local/bin/ros_launch_wrapper.py" - ;; - "default") - echo -e "${YELLOW}Starting interactive bash shell...${NC}" - echo "" - echo "You can manually run:" - echo " ROS planner: cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh" - echo " DimOS: python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" - echo " Both (clean shutdown): python3 /usr/local/bin/ros_launch_wrapper.py" - echo "" - CMD="bash" - ;; -esac - -# Run the container -docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack $CMD - -# Revoke X server access when done -xhost -local:docker 2>/dev/null || true - -echo "" -echo -e "${GREEN}Container stopped.${NC}" \ No newline at end of file From 47bb9cc83c68b066496d88f2532fbc8cfbf0fbba Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Sun, 26 Oct 2025 03:06:31 +0300 Subject: [PATCH 09/38] more cleanup --- ros_docker_integration/build.sh | 8 ++++---- ros_docker_integration/ros_launch_wrapper.py | 13 ++++--------- ros_docker_integration/run_command.sh | 12 +++--------- ros_docker_integration/shell.sh | 11 +++-------- ros_docker_integration/start.sh | 16 +++------------- 5 files changed, 17 insertions(+), 43 deletions(-) diff --git a/ros_docker_integration/build.sh b/ros_docker_integration/build.sh index 085a215e76..dcb8e13bfb 100755 --- a/ros_docker_integration/build.sh +++ b/ros_docker_integration/build.sh @@ -6,9 +6,9 @@ GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' -echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}================================================${NC}" echo -e "${GREEN}Building DimOS + ROS Autonomy Stack Docker Image${NC}" -echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}================================================${NC}" echo "" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" @@ -40,9 +40,9 @@ cd .. docker compose -f ros_docker_integration/docker-compose.yml build echo "" -echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}================================${NC}" echo -e "${GREEN}Docker image built successfully!${NC}" -echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}================================${NC}" echo "" echo "You can now run the container using:" echo -e "${YELLOW} ./start.sh --all${NC}" diff --git a/ros_docker_integration/ros_launch_wrapper.py b/ros_docker_integration/ros_launch_wrapper.py index 00745ff7c7..289d48aa88 100755 --- a/ros_docker_integration/ros_launch_wrapper.py +++ b/ros_docker_integration/ros_launch_wrapper.py @@ -23,7 +23,6 @@ import signal import subprocess import time -import threading class ROSLaunchWrapper: @@ -32,7 +31,7 @@ def __init__(self): self.dimos_process = None self.shutdown_in_progress = False - def signal_handler(self, signum, frame): + def signal_handler(self, _signum, _frame): """Handle shutdown signals gracefully""" if self.shutdown_in_progress: return @@ -40,7 +39,7 @@ def signal_handler(self, signum, frame): self.shutdown_in_progress = True print("\n\nShutdown signal received. Stopping services gracefully...") - # Stop DimOS first (it typically shuts down cleanly) + # Stop DimOS first if self.dimos_process and self.dimos_process.poll() is None: print("Stopping DimOS...") self.dimos_process.terminate() @@ -94,7 +93,6 @@ def signal_handler(self, signum, frame): sys.exit(0) def run(self): - """Main execution function""" # Register signal handlers signal.signal(signal.SIGINT, self.signal_handler) signal.signal(signal.SIGTERM, self.signal_handler) @@ -111,14 +109,11 @@ def run(self): preexec_fn=os.setsid, # Create new process group ) - # Wait for ROS to initialize print("Waiting for ROS to initialize...") time.sleep(5) - # Start DimOS print("Starting DimOS navigation bot...") - # Check if the script exists nav_bot_path = "/workspace/dimos/dimos/navigation/rosnav/nav_bot.py" venv_python = "/opt/dimos-venv/bin/python" @@ -134,8 +129,8 @@ def run(self): return if not os.path.exists(venv_python): - print(f"WARNING: venv Python not found at {venv_python}, using system Python") - venv_python = sys.executable + print(f"ERROR: venv Python not found at {venv_python}, using system Python") + return print(f"Using Python: {venv_python}") print(f"Starting script: {nav_bot_path}") diff --git a/ros_docker_integration/run_command.sh b/ros_docker_integration/run_command.sh index e9d5707c8d..e92718459c 100755 --- a/ros_docker_integration/run_command.sh +++ b/ros_docker_integration/run_command.sh @@ -2,17 +2,14 @@ set -e -# Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' -NC='\033[0m' # No Color +NC='\033[0m' -# Get the directory where the script is located SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$SCRIPT_DIR" -# Check if command was provided if [ $# -eq 0 ]; then echo -e "${RED}Error: No command provided${NC}" echo "" @@ -26,21 +23,18 @@ if [ $# -eq 0 ]; then exit 1 fi -# Allow X server connection from Docker xhost +local:docker 2>/dev/null || true -echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}========================================${NC}" echo -e "${GREEN}Running command in DimOS + ROS Container${NC}" -echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}========================================${NC}" echo "" echo -e "${YELLOW}Command: $@${NC}" echo "" -# Go to dimos directory (parent of ros_docker_integration) for docker compose context cd .. # Run the command in the container docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c "$@" -# Revoke X server access when done xhost -local:docker 2>/dev/null || true \ No newline at end of file diff --git a/ros_docker_integration/shell.sh b/ros_docker_integration/shell.sh index d907933c5f..130efc1a04 100755 --- a/ros_docker_integration/shell.sh +++ b/ros_docker_integration/shell.sh @@ -4,21 +4,18 @@ set -e -# Colors for output GREEN='\033[0;32m' YELLOW='\033[1;33m' -NC='\033[0m' # No Color +NC='\033[0m' -# Get the directory where the script is located SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$SCRIPT_DIR" -# Allow X server connection from Docker xhost +local:docker 2>/dev/null || true -echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}====================================${NC}" echo -e "${GREEN}Entering DimOS + ROS Container Shell${NC}" -echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}====================================${NC}" echo "" echo -e "${YELLOW}Environment:${NC}" echo " - ROS workspace: /ros2_ws" @@ -32,11 +29,9 @@ echo " - source /opt/dimos-venv/bin/activate" echo " - python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" echo "" -# Go to dimos directory (parent of ros_docker_integration) for docker compose context cd .. # Enter interactive shell docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -# Revoke X server access when done xhost -local:docker 2>/dev/null || true \ No newline at end of file diff --git a/ros_docker_integration/start.sh b/ros_docker_integration/start.sh index 7da1300119..93b530ec0c 100755 --- a/ros_docker_integration/start.sh +++ b/ros_docker_integration/start.sh @@ -2,25 +2,20 @@ set -e -# Colors for output -RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' -NC='\033[0m' # No Color +NC='\033[0m' -# Get the directory where the script is located SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$SCRIPT_DIR" -# Allow X server connection from Docker xhost +local:docker 2>/dev/null || true -echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}=============================================${NC}" echo -e "${GREEN}Starting DimOS + ROS Autonomy Stack Container${NC}" -echo -e "${GREEN}=========================================${NC}" +echo -e "${GREEN}=============================================${NC}" echo "" -# Check if Unity models exist (warn if not) if [ ! -d "unity_models" ] && [[ "$*" == *"--ros-planner"* || "$*" == *"--all"* ]]; then echo -e "${YELLOW}WARNING: Unity models directory not found!${NC}" echo "The Unity simulator may not work properly." @@ -28,7 +23,6 @@ if [ ! -d "unity_models" ] && [[ "$*" == *"--ros-planner"* || "$*" == *"--all"* echo "" fi -# Parse command line arguments MODE="default" if [[ "$1" == "--ros-planner" ]]; then MODE="ros-planner" @@ -49,10 +43,8 @@ elif [[ "$1" == "--help" || "$1" == "-h" ]]; then exit 0 fi -# Go to dimos directory (parent of ros_docker_integration) for docker compose context cd .. -# Set the command based on mode case $MODE in "ros-planner") echo -e "${YELLOW}Starting with ROS route planner...${NC}" @@ -64,7 +56,6 @@ case $MODE in ;; "all") echo -e "${YELLOW}Starting both ROS planner and DimOS...${NC}" - # Use the helper script to run both CMD="/usr/local/bin/run_both.sh" ;; "default") @@ -81,7 +72,6 @@ esac # Run the container docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack $CMD -# Revoke X server access when done xhost -local:docker 2>/dev/null || true echo "" From c09c70b1e4266d27dc48f841bb1f68f07d4da3d2 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Wed, 29 Oct 2025 06:45:13 +0200 Subject: [PATCH 10/38] move to docker/navigation --- {ros_docker_integration => docker/navigation}/.gitignore | 0 {ros_docker_integration => docker/navigation}/Dockerfile | 6 +++--- {ros_docker_integration => docker/navigation}/README.md | 0 {ros_docker_integration => docker/navigation}/build.sh | 6 +++--- .../navigation}/docker-compose.yml | 6 +++--- .../navigation}/ros_launch_wrapper.py | 2 +- {ros_docker_integration => docker/navigation}/run_both.sh | 0 .../navigation}/run_command.sh | 4 ++-- {ros_docker_integration => docker/navigation}/shell.sh | 4 ++-- {ros_docker_integration => docker/navigation}/start.sh | 4 ++-- 10 files changed, 16 insertions(+), 16 deletions(-) rename {ros_docker_integration => docker/navigation}/.gitignore (100%) rename {ros_docker_integration => docker/navigation}/Dockerfile (92%) rename {ros_docker_integration => docker/navigation}/README.md (100%) rename {ros_docker_integration => docker/navigation}/build.sh (92%) rename {ros_docker_integration => docker/navigation}/docker-compose.yml (94%) rename {ros_docker_integration => docker/navigation}/ros_launch_wrapper.py (100%) rename {ros_docker_integration => docker/navigation}/run_both.sh (100%) rename {ros_docker_integration => docker/navigation}/run_command.sh (89%) rename {ros_docker_integration => docker/navigation}/shell.sh (90%) rename {ros_docker_integration => docker/navigation}/start.sh (95%) diff --git a/ros_docker_integration/.gitignore b/docker/navigation/.gitignore similarity index 100% rename from ros_docker_integration/.gitignore rename to docker/navigation/.gitignore diff --git a/ros_docker_integration/Dockerfile b/docker/navigation/Dockerfile similarity index 92% rename from ros_docker_integration/Dockerfile rename to docker/navigation/Dockerfile index 62e5834567..9169bf2343 100644 --- a/ros_docker_integration/Dockerfile +++ b/docker/navigation/Dockerfile @@ -54,7 +54,7 @@ RUN apt-get update && apt-get install -y \ RUN mkdir -p ${WORKSPACE}/src # Copy the autonomy stack repository (should be cloned by build.sh) -COPY ros_docker_integration/autonomy_stack_mecanum_wheel_platform ${WORKSPACE}/src/autonomy_stack_mecanum_wheel_platform +COPY docker/navigation/autonomy_stack_mecanum_wheel_platform ${WORKSPACE}/src/autonomy_stack_mecanum_wheel_platform # Set working directory WORKDIR ${WORKSPACE} @@ -91,8 +91,8 @@ RUN /bin/bash -c "source /opt/dimos-venv/bin/activate && \ pip install -e .[cpu,dev] 'mmengine>=0.10.3' 'mmcv>=2.1.0'" # Copy helper scripts -COPY ros_docker_integration/run_both.sh /usr/local/bin/run_both.sh -COPY ros_docker_integration/ros_launch_wrapper.py /usr/local/bin/ros_launch_wrapper.py +COPY docker/navigation/run_both.sh /usr/local/bin/run_both.sh +COPY docker/navigation/ros_launch_wrapper.py /usr/local/bin/ros_launch_wrapper.py RUN chmod +x /usr/local/bin/run_both.sh /usr/local/bin/ros_launch_wrapper.py # Set up entrypoint script diff --git a/ros_docker_integration/README.md b/docker/navigation/README.md similarity index 100% rename from ros_docker_integration/README.md rename to docker/navigation/README.md diff --git a/ros_docker_integration/build.sh b/docker/navigation/build.sh similarity index 92% rename from ros_docker_integration/build.sh rename to docker/navigation/build.sh index dcb8e13bfb..a9302e20c2 100755 --- a/ros_docker_integration/build.sh +++ b/docker/navigation/build.sh @@ -22,7 +22,7 @@ fi if [ ! -d "unity_models" ]; then echo -e "${YELLOW}Using office_building_1 as the Unity environment...${NC}" - tar -xf ../data/.lfs/office_building_1.tar.gz + tar -xf ../../data/.lfs/office_building_1.tar.gz mv office_building_1 unity_models fi @@ -35,9 +35,9 @@ echo " - Build the autonomy stack" echo " - Install Python dependencies for DimOS" echo "" -cd .. +cd ../.. -docker compose -f ros_docker_integration/docker-compose.yml build +docker compose -f docker/navigation/docker-compose.yml build echo "" echo -e "${GREEN}================================${NC}" diff --git a/ros_docker_integration/docker-compose.yml b/docker/navigation/docker-compose.yml similarity index 94% rename from ros_docker_integration/docker-compose.yml rename to docker/navigation/docker-compose.yml index df9332e62d..625f3eb75f 100644 --- a/ros_docker_integration/docker-compose.yml +++ b/docker/navigation/docker-compose.yml @@ -1,8 +1,8 @@ services: dimos_autonomy_stack: build: - context: .. - dockerfile: ros_docker_integration/Dockerfile + context: ../.. + dockerfile: docker/navigation/Dockerfile image: dimos_autonomy_stack:jazzy container_name: dimos_autonomy_container @@ -41,7 +41,7 @@ services: - ./autonomy_stack_mecanum_wheel_platform/src:/ros2_ws/src/autonomy_stack_mecanum_wheel_platform/src:rw # Mount entire dimos directory for live development - - ..:/workspace/dimos:rw + - ../..:/workspace/dimos:rw # Mount bagfiles directory (optional) - ./bagfiles:/ros2_ws/bagfiles:rw diff --git a/ros_docker_integration/ros_launch_wrapper.py b/docker/navigation/ros_launch_wrapper.py similarity index 100% rename from ros_docker_integration/ros_launch_wrapper.py rename to docker/navigation/ros_launch_wrapper.py index 289d48aa88..0eb5c18aef 100755 --- a/ros_docker_integration/ros_launch_wrapper.py +++ b/docker/navigation/ros_launch_wrapper.py @@ -19,9 +19,9 @@ """ import os -import sys import signal import subprocess +import sys import time diff --git a/ros_docker_integration/run_both.sh b/docker/navigation/run_both.sh similarity index 100% rename from ros_docker_integration/run_both.sh rename to docker/navigation/run_both.sh diff --git a/ros_docker_integration/run_command.sh b/docker/navigation/run_command.sh similarity index 89% rename from ros_docker_integration/run_command.sh rename to docker/navigation/run_command.sh index e92718459c..d6818b23d7 100755 --- a/ros_docker_integration/run_command.sh +++ b/docker/navigation/run_command.sh @@ -32,9 +32,9 @@ echo "" echo -e "${YELLOW}Command: $@${NC}" echo "" -cd .. +cd ../.. # Run the command in the container -docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash -c "$@" +docker compose -f docker/navigation/docker-compose.yml run --rm dimos_autonomy_stack bash -c "$@" xhost -local:docker 2>/dev/null || true \ No newline at end of file diff --git a/ros_docker_integration/shell.sh b/docker/navigation/shell.sh similarity index 90% rename from ros_docker_integration/shell.sh rename to docker/navigation/shell.sh index 130efc1a04..08cbfb7780 100755 --- a/ros_docker_integration/shell.sh +++ b/docker/navigation/shell.sh @@ -29,9 +29,9 @@ echo " - source /opt/dimos-venv/bin/activate" echo " - python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" echo "" -cd .. +cd ../.. # Enter interactive shell -docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack bash +docker compose -f docker/navigation/docker-compose.yml run --rm dimos_autonomy_stack bash xhost -local:docker 2>/dev/null || true \ No newline at end of file diff --git a/ros_docker_integration/start.sh b/docker/navigation/start.sh similarity index 95% rename from ros_docker_integration/start.sh rename to docker/navigation/start.sh index 93b530ec0c..b75a6b1007 100755 --- a/ros_docker_integration/start.sh +++ b/docker/navigation/start.sh @@ -43,7 +43,7 @@ elif [[ "$1" == "--help" || "$1" == "-h" ]]; then exit 0 fi -cd .. +cd ../.. case $MODE in "ros-planner") @@ -70,7 +70,7 @@ case $MODE in esac # Run the container -docker compose -f ros_docker_integration/docker-compose.yml run --rm dimos_autonomy_stack $CMD +docker compose -f docker/navigation/docker-compose.yml run --rm dimos_autonomy_stack $CMD xhost -local:docker 2>/dev/null || true From e28779a0a570ea532651fd70b82fb1f9fc31d7ff Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Wed, 29 Oct 2025 07:07:29 +0200 Subject: [PATCH 11/38] fix import --- dimos/navigation/rosnav/nav_bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dimos/navigation/rosnav/nav_bot.py b/dimos/navigation/rosnav/nav_bot.py index 0f2b652bb8..e5abdb0dcc 100644 --- a/dimos/navigation/rosnav/nav_bot.py +++ b/dimos/navigation/rosnav/nav_bot.py @@ -42,7 +42,7 @@ from dimos.msgs.sensor_msgs import PointCloud2 from dimos.msgs.std_msgs import Bool from dimos.msgs.tf2_msgs.TFMessage import TFMessage -from dimos.navigation.rosnav import ROSNav +from dimos.navigation.rosnav.rosnav import ROSNav from dimos.protocol import pubsub from dimos.utils.logging_config import setup_logger from dimos.utils.transform_utils import euler_to_quaternion From ef988dc8bf46452e7a9f0b0ed60bcb13b104b55f Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Wed, 29 Oct 2025 07:31:49 +0200 Subject: [PATCH 12/38] fix log --- dimos/navigation/rosnav/nav_bot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dimos/navigation/rosnav/nav_bot.py b/dimos/navigation/rosnav/nav_bot.py index e5abdb0dcc..d76a6e092e 100644 --- a/dimos/navigation/rosnav/nav_bot.py +++ b/dimos/navigation/rosnav/nav_bot.py @@ -400,7 +400,7 @@ def main() -> None: orientation=Quaternion(0.0, 0.0, 0.0, 1.0), ) - logger.info("Sending navigation goal to: (1.0, 1.0, 0.0)") + logger.info("Sending navigation goal to: (2.0, 2.0, 0.0)") if nav_bot.navigation_module: success = nav_bot.navigation_module.navigate_to(test_pose, timeout=30.0) From 91bfe37b6b97904da00dd2ded593d4afb1df2180 Mon Sep 17 00:00:00 2001 From: Naveen Date: Wed, 29 Oct 2025 14:48:53 -0700 Subject: [PATCH 13/38] fix nvidia runtime error with GPU auto-detection and CPU fallback --- docker/navigation/docker-compose.yml | 7 +++---- docker/navigation/start.sh | 19 ++++++++++++++++++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docker/navigation/docker-compose.yml b/docker/navigation/docker-compose.yml index 625f3eb75f..4b14eccb7e 100644 --- a/docker/navigation/docker-compose.yml +++ b/docker/navigation/docker-compose.yml @@ -16,15 +16,14 @@ services: # Privileged mode for hardware access (required for real robot and some devices) privileged: true - # GPU support (NVIDIA runtime) - runtime: nvidia + runtime: ${DOCKER_RUNTIME:-runc} # Environment variables for display and ROS environment: - DISPLAY=${DISPLAY} - QT_X11_NO_MITSHM=1 - - NVIDIA_VISIBLE_DEVICES=all - - NVIDIA_DRIVER_CAPABILITIES=all + - NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES:-} + - NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES:-} - ROS_DOMAIN_ID=0 - ROBOT_CONFIG_PATH=mechanum_drive diff --git a/docker/navigation/start.sh b/docker/navigation/start.sh index b75a6b1007..9bec55382b 100755 --- a/docker/navigation/start.sh +++ b/docker/navigation/start.sh @@ -23,6 +23,20 @@ if [ ! -d "unity_models" ] && [[ "$*" == *"--ros-planner"* || "$*" == *"--all"* echo "" fi +if command -v nvidia-smi &> /dev/null && nvidia-smi &> /dev/null; then + export DOCKER_RUNTIME=nvidia + export NVIDIA_VISIBLE_DEVICES=all + export NVIDIA_DRIVER_CAPABILITIES=all + echo -e "${GREEN}GPU mode enabled${NC} (using nvidia runtime)" + echo "" +else + export DOCKER_RUNTIME=runc + export NVIDIA_VISIBLE_DEVICES= + export NVIDIA_DRIVER_CAPABILITIES= + echo -e "${YELLOW}CPU-only mode${NC} (no GPU detected)" + echo "" +fi + MODE="default" if [[ "$1" == "--ros-planner" ]]; then MODE="ros-planner" @@ -39,7 +53,11 @@ elif [[ "$1" == "--help" || "$1" == "-h" ]]; then echo " --all Start both ROS planner and DimOS" echo " --help Show this help message" echo "" + echo "GPU auto-detection: Automatically uses GPU if nvidia-smi is available" echo "Without options, starts an interactive bash shell" + echo "" + echo "Example:" + echo " $0 --all" exit 0 fi @@ -69,7 +87,6 @@ case $MODE in ;; esac -# Run the container docker compose -f docker/navigation/docker-compose.yml run --rm dimos_autonomy_stack $CMD xhost -local:docker 2>/dev/null || true From f6e6983284e8eabb59a0b3df385e288b19e59d78 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Thu, 30 Oct 2025 04:44:56 +0200 Subject: [PATCH 14/38] switch to ros-navigation-autonomy-stack --- docker/navigation/.gitignore | 2 +- docker/navigation/Dockerfile | 4 ++-- docker/navigation/README.md | 6 +++--- docker/navigation/build.sh | 6 +++--- docker/navigation/docker-compose.yml | 4 ++-- docker/navigation/ros_launch_wrapper.py | 2 +- docker/navigation/run_both.sh | 2 +- docker/navigation/start.sh | 4 ++-- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docker/navigation/.gitignore b/docker/navigation/.gitignore index 4933cec4ed..434f1e37bc 100644 --- a/docker/navigation/.gitignore +++ b/docker/navigation/.gitignore @@ -1,5 +1,5 @@ # Cloned repository -autonomy_stack_mecanum_wheel_platform/ +ros-navigation-autonomy-stack/ # Unity models (large binary files) unity_models/ diff --git a/docker/navigation/Dockerfile b/docker/navigation/Dockerfile index 9169bf2343..a477c86d2c 100644 --- a/docker/navigation/Dockerfile +++ b/docker/navigation/Dockerfile @@ -54,7 +54,7 @@ RUN apt-get update && apt-get install -y \ RUN mkdir -p ${WORKSPACE}/src # Copy the autonomy stack repository (should be cloned by build.sh) -COPY docker/navigation/autonomy_stack_mecanum_wheel_platform ${WORKSPACE}/src/autonomy_stack_mecanum_wheel_platform +COPY docker/navigation/ros-navigation-autonomy-stack ${WORKSPACE}/src/ros-navigation-autonomy-stack # Set working directory WORKDIR ${WORKSPACE} @@ -73,7 +73,7 @@ RUN /bin/bash -c "source /opt/ros/${ROS_DISTRO}/setup.bash && \ RUN echo "source ${WORKSPACE}/install/setup.bash" >> ~/.bashrc # Create directory for Unity environment models -RUN mkdir -p ${WORKSPACE}/src/autonomy_stack_mecanum_wheel_platform/src/base_autonomy/vehicle_simulator/mesh/unity +RUN mkdir -p ${WORKSPACE}/src/ros-navigation-autonomy-stack/src/base_autonomy/vehicle_simulator/mesh/unity # Copy the dimos repository RUN mkdir -p ${DIMOS_PATH} diff --git a/docker/navigation/README.md b/docker/navigation/README.md index 35edcbad60..8efa77c99f 100644 --- a/docker/navigation/README.md +++ b/docker/navigation/README.md @@ -15,7 +15,7 @@ This directory contains Docker configuration files to run DimOS and the ROS auto ./build.sh ``` This will: - - Clone the autonomy_stack_mecanum_wheel_platform repository (jazzy branch) + - Clone the ros-navigation-autonomy-stack repository (jazzy branch) - Build a Docker image with both ROS and DimOS dependencies - Set up the environment for both systems @@ -32,7 +32,7 @@ Once inside the container, you can manually run: ### ROS Autonomy Stack ```bash -cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform +cd /ros2_ws/src/ros-navigation-autonomy-stack ./system_simulation_with_route_planner.sh ``` @@ -75,7 +75,7 @@ Use the `run_command.sh` helper script to run custom commands: The docker-compose.yml mounts the following directories for live development: - DimOS source: `..` → `/workspace/dimos` -- Autonomy stack source: `./autonomy_stack_mecanum_wheel_platform/src` → `/ros2_ws/src/autonomy_stack_mecanum_wheel_platform/src` +- Autonomy stack source: `./ros-navigation-autonomy-stack/src` → `/ros2_ws/src/ros-navigation-autonomy-stack/src` Changes to these files will be reflected in the container without rebuilding. diff --git a/docker/navigation/build.sh b/docker/navigation/build.sh index a9302e20c2..bf89185dc7 100755 --- a/docker/navigation/build.sh +++ b/docker/navigation/build.sh @@ -14,9 +14,9 @@ echo "" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$SCRIPT_DIR" -if [ ! -d "autonomy_stack_mecanum_wheel_platform" ]; then - echo -e "${YELLOW}Cloning autonomy_stack_mecanum_wheel_platform repository...${NC}" - git clone https://github.com/alexlin2/autonomy_stack_mecanum_wheel_platform.git +if [ ! -d "ros-navigation-autonomy-stack" ]; then + echo -e "${YELLOW}Cloning ros-navigation-autonomy-stack repository...${NC}" + git clone -b jazzy git@github.com:dimensionalOS/ros-navigation-autonomy-stack.git echo -e "${GREEN}Repository cloned successfully!${NC}" fi diff --git a/docker/navigation/docker-compose.yml b/docker/navigation/docker-compose.yml index 4b14eccb7e..6187a86f2a 100644 --- a/docker/navigation/docker-compose.yml +++ b/docker/navigation/docker-compose.yml @@ -34,10 +34,10 @@ services: - ${HOME}/.Xauthority:/root/.Xauthority:rw # Mount Unity environment models (if available) - - ./unity_models:/ros2_ws/src/autonomy_stack_mecanum_wheel_platform/src/base_autonomy/vehicle_simulator/mesh/unity:rw + - ./unity_models:/ros2_ws/src/ros-navigation-autonomy-stack/src/base_autonomy/vehicle_simulator/mesh/unity:rw # Mount the autonomy stack source for development (optional - comment out if not needed) - - ./autonomy_stack_mecanum_wheel_platform/src:/ros2_ws/src/autonomy_stack_mecanum_wheel_platform/src:rw + - ./ros-navigation-autonomy-stack/src:/ros2_ws/src/ros-navigation-autonomy-stack/src:rw # Mount entire dimos directory for live development - ../..:/workspace/dimos:rw diff --git a/docker/navigation/ros_launch_wrapper.py b/docker/navigation/ros_launch_wrapper.py index 0eb5c18aef..372cba9844 100755 --- a/docker/navigation/ros_launch_wrapper.py +++ b/docker/navigation/ros_launch_wrapper.py @@ -100,7 +100,7 @@ def run(self): print("Starting ROS route planner and DimOS...") # Change to the ROS workspace directory - os.chdir("/ros2_ws/src/autonomy_stack_mecanum_wheel_platform") + os.chdir("/ros2_ws/src/ros-navigation-autonomy-stack") # Start ROS route planner print("Starting ROS route planner...") diff --git a/docker/navigation/run_both.sh b/docker/navigation/run_both.sh index d27a19758e..c7b5a685fa 100755 --- a/docker/navigation/run_both.sh +++ b/docker/navigation/run_both.sh @@ -89,7 +89,7 @@ trap cleanup EXIT INT TERM # Start ROS route planner in background (in new process group) echo "Starting ROS route planner..." -cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform +cd /ros2_ws/src/ros-navigation-autonomy-stack setsid bash -c './system_simulation_with_route_planner.sh' & ROS_PID=$! diff --git a/docker/navigation/start.sh b/docker/navigation/start.sh index 9bec55382b..b88f413a53 100755 --- a/docker/navigation/start.sh +++ b/docker/navigation/start.sh @@ -66,7 +66,7 @@ cd ../.. case $MODE in "ros-planner") echo -e "${YELLOW}Starting with ROS route planner...${NC}" - CMD="bash -c 'cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh'" + CMD="bash -c 'cd /ros2_ws/src/ros-navigation-autonomy-stack && ./system_simulation_with_route_planner.sh'" ;; "dimos") echo -e "${YELLOW}Starting with DimOS navigation bot...${NC}" @@ -80,7 +80,7 @@ case $MODE in echo -e "${YELLOW}Starting interactive bash shell...${NC}" echo "" echo "You can manually run:" - echo " ROS planner: cd /ros2_ws/src/autonomy_stack_mecanum_wheel_platform && ./system_simulation_with_route_planner.sh" + echo " ROS planner: cd /ros2_ws/src/ros-navigation-autonomy-stack && ./system_simulation_with_route_planner.sh" echo " DimOS: python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" echo "" CMD="bash" From 377cfa0809d614ed7c5f0c6d39193f2ea7fb30ce Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Thu, 30 Oct 2025 04:54:00 +0200 Subject: [PATCH 15/38] add trap to shut down x access --- docker/navigation/run_command.sh | 8 ++++++-- docker/navigation/shell.sh | 8 ++++++-- docker/navigation/start.sh | 10 +++++++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/docker/navigation/run_command.sh b/docker/navigation/run_command.sh index d6818b23d7..44b67deaa9 100755 --- a/docker/navigation/run_command.sh +++ b/docker/navigation/run_command.sh @@ -25,6 +25,12 @@ fi xhost +local:docker 2>/dev/null || true +cleanup() { + xhost -local:docker 2>/dev/null || true +} + +trap cleanup EXIT + echo -e "${GREEN}========================================${NC}" echo -e "${GREEN}Running command in DimOS + ROS Container${NC}" echo -e "${GREEN}========================================${NC}" @@ -36,5 +42,3 @@ cd ../.. # Run the command in the container docker compose -f docker/navigation/docker-compose.yml run --rm dimos_autonomy_stack bash -c "$@" - -xhost -local:docker 2>/dev/null || true \ No newline at end of file diff --git a/docker/navigation/shell.sh b/docker/navigation/shell.sh index 08cbfb7780..f91b7eeb0a 100755 --- a/docker/navigation/shell.sh +++ b/docker/navigation/shell.sh @@ -13,6 +13,12 @@ cd "$SCRIPT_DIR" xhost +local:docker 2>/dev/null || true +cleanup() { + xhost -local:docker 2>/dev/null || true +} + +trap cleanup EXIT + echo -e "${GREEN}====================================${NC}" echo -e "${GREEN}Entering DimOS + ROS Container Shell${NC}" echo -e "${GREEN}====================================${NC}" @@ -33,5 +39,3 @@ cd ../.. # Enter interactive shell docker compose -f docker/navigation/docker-compose.yml run --rm dimos_autonomy_stack bash - -xhost -local:docker 2>/dev/null || true \ No newline at end of file diff --git a/docker/navigation/start.sh b/docker/navigation/start.sh index b88f413a53..7bc5fada83 100755 --- a/docker/navigation/start.sh +++ b/docker/navigation/start.sh @@ -11,6 +11,12 @@ cd "$SCRIPT_DIR" xhost +local:docker 2>/dev/null || true +cleanup() { + xhost -local:docker 2>/dev/null || true +} + +trap cleanup EXIT + echo -e "${GREEN}=============================================${NC}" echo -e "${GREEN}Starting DimOS + ROS Autonomy Stack Container${NC}" echo -e "${GREEN}=============================================${NC}" @@ -89,7 +95,5 @@ esac docker compose -f docker/navigation/docker-compose.yml run --rm dimos_autonomy_stack $CMD -xhost -local:docker 2>/dev/null || true - echo "" -echo -e "${GREEN}Container stopped.${NC}" \ No newline at end of file +echo -e "${GREEN}Container stopped.${NC}" From 483b6c4436e4c235c0df26249b3083ae39822198 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Thu, 30 Oct 2025 08:36:54 +0200 Subject: [PATCH 16/38] use demo_ros_navigation --- dimos/navigation/demo_ros_navigation.py | 137 ++++++++++++++++++++++++ dimos/navigation/rosnav.py | 6 +- docker/navigation/README.md | 4 +- docker/navigation/ros_launch_wrapper.py | 4 +- docker/navigation/run_both.sh | 10 +- docker/navigation/run_command.sh | 2 +- docker/navigation/shell.sh | 2 +- docker/navigation/start.sh | 5 +- 8 files changed, 154 insertions(+), 16 deletions(-) create mode 100755 dimos/navigation/demo_ros_navigation.py diff --git a/dimos/navigation/demo_ros_navigation.py b/dimos/navigation/demo_ros_navigation.py new file mode 100755 index 0000000000..a0544644d9 --- /dev/null +++ b/dimos/navigation/demo_ros_navigation.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 +# Copyright 2025 Dimensional Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Demo script for testing ROS navigation with the ROSNav module.""" + +import logging +import signal +import sys +import threading +import time + +import rclpy +from rclpy.node import Node + +from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Vector3 +from dimos.utils.logging_config import setup_logger + +logger = setup_logger("demo_ros_navigation", level=logging.INFO) + +# Global variable to track if we should keep running +running = True +nav_module = None + + +def signal_handler(signum, frame): + """Handle shutdown signals gracefully.""" + global running, nav_module + logger.info("Shutting down...") + running = False + if nav_module: + nav_module.stop_navigation() + sys.exit(0) + + +def main(): + """Main function to test ROS navigation - simplified standalone version.""" + global running, nav_module + + logger.info("Starting ROS navigation demo (standalone mode)...") + + # Register signal handlers for graceful shutdown + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + + # Initialize ROS2 if not already initialized + if not rclpy.ok(): + rclpy.init() + + # Import here to avoid circular dependencies + from dimos.navigation.rosnav import ROSNav + + # Create the navigation module instance + logger.info("Creating ROSNav module instance...") + nav_module = ROSNav() + + # Since we can't use the full Dimos deployment, we need to handle + # the ROS spinning manually + def spin_thread(): + while running and rclpy.ok(): + try: + rclpy.spin_once(nav_module._node, timeout_sec=0.1) + except Exception as e: + if running: + logger.error(f"ROS2 spin error: {e}") + + # Start the navigation module + logger.info("Starting ROSNav module...") + # Note: We can't call nav_module.start() directly without proper Dimos setup + # Instead, we'll start the ROS spinning thread manually + + spin_thread_obj = threading.Thread(target=spin_thread, daemon=True) + spin_thread_obj.start() + + # Give the system time to initialize + logger.info("Waiting for system initialization...") + time.sleep(5.0) + + # Create a test pose for navigation + # Moving 2 meters forward and 1 meter to the left relative to base_link + test_pose = PoseStamped( + position=Vector3(2.0, 1.0, 0.0), + orientation=Quaternion(0.0, 0.0, 0.0, 1.0), + frame_id="base_link", # Relative to robot's current position + ts=time.time(), + ) + + logger.info( + f"Navigating to test position: ({test_pose.position.x:.2f}, {test_pose.position.y:.2f}, {test_pose.position.z:.2f}) @ {test_pose.frame_id}" + ) + + # Perform navigation + logger.info("Sending navigation command...") + success = nav_module.navigate_to(test_pose, timeout=30.0) + + if success: + logger.info("Navigation successful!") + else: + logger.warning("Navigation failed or timed out") + + # Wait a bit before stopping + time.sleep(2.0) + + # Stop the navigation module + logger.info("Stopping navigation module...") + nav_module.stop_navigation() + + # Clean up + running = False + if nav_module._node: + nav_module._node.destroy_node() + + if rclpy.ok(): + rclpy.shutdown() + + logger.info("Demo completed") + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + logger.info("Interrupted by user") + except Exception as e: + logger.error(f"Error: {e}", exc_info=True) + sys.exit(1) diff --git a/dimos/navigation/rosnav.py b/dimos/navigation/rosnav.py index f0d04926d3..34ed27fb6e 100644 --- a/dimos/navigation/rosnav.py +++ b/dimos/navigation/rosnav.py @@ -19,7 +19,7 @@ """ from collections.abc import Generator -from dataclasses import dataclass +from dataclasses import dataclass, field import logging import threading import time @@ -64,8 +64,8 @@ class Config(ModuleConfig): local_pointcloud_freq: float = 2.0 global_pointcloud_freq: float = 1.0 - sensor_to_base_link_transform: Transform = Transform( - frame_id="sensor", child_frame_id="base_link" + sensor_to_base_link_transform: Transform = field( + default_factory=lambda: Transform(frame_id="sensor", child_frame_id="base_link") ) diff --git a/docker/navigation/README.md b/docker/navigation/README.md index 8efa77c99f..93413ff757 100644 --- a/docker/navigation/README.md +++ b/docker/navigation/README.md @@ -41,8 +41,8 @@ cd /ros2_ws/src/ros-navigation-autonomy-stack # Activate virtual environment source /opt/dimos-venv/bin/activate -# Run navigation bot -python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py +# Run navigation demo +python /workspace/dimos/dimos/navigation/demo_ros_navigation.py # Or run other DimOS scripts python /workspace/dimos/dimos/your_script.py diff --git a/docker/navigation/ros_launch_wrapper.py b/docker/navigation/ros_launch_wrapper.py index 372cba9844..c6458a99c9 100755 --- a/docker/navigation/ros_launch_wrapper.py +++ b/docker/navigation/ros_launch_wrapper.py @@ -114,11 +114,11 @@ def run(self): print("Starting DimOS navigation bot...") - nav_bot_path = "/workspace/dimos/dimos/navigation/rosnav/nav_bot.py" + nav_bot_path = "/workspace/dimos/dimos/navigation/demo_ros_navigation.py" venv_python = "/opt/dimos-venv/bin/python" if not os.path.exists(nav_bot_path): - print(f"ERROR: nav_bot.py not found at {nav_bot_path}") + print(f"ERROR: demo_ros_navigation.py not found at {nav_bot_path}") nav_dir = "/workspace/dimos/dimos/navigation/" if os.path.exists(nav_dir): print(f"Contents of {nav_dir}:") diff --git a/docker/navigation/run_both.sh b/docker/navigation/run_both.sh index c7b5a685fa..a433cf5b01 100755 --- a/docker/navigation/run_both.sh +++ b/docker/navigation/run_both.sh @@ -101,12 +101,12 @@ sleep 5 echo "Starting DimOS navigation bot..." # Check if the script exists -if [ ! -f "/workspace/dimos/dimos/navigation/rosnav/nav_bot.py" ]; then - echo "ERROR: nav_bot.py not found at /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" +if [ ! -f "/workspace/dimos/dimos/navigation/demo_ros_navigation.py" ]; then + echo "ERROR: demo_ros_navigation.py not found at /workspace/dimos/dimos/navigation/demo_ros_navigation.py" echo "Available files in /workspace/dimos/dimos/navigation/:" ls -la /workspace/dimos/dimos/navigation/ 2>/dev/null || echo "Directory not found" else - echo "Found nav_bot.py, activating virtual environment..." + echo "Found demo_ros_navigation.py, activating virtual environment..." if [ -f "/opt/dimos-venv/bin/activate" ]; then source /opt/dimos-venv/bin/activate echo "Python path: $(which python)" @@ -115,9 +115,9 @@ else echo "WARNING: Virtual environment not found at /opt/dimos-venv, using system Python" fi - echo "Starting nav_bot.py..." + echo "Starting demo_ros_navigation.py..." # Capture any startup errors - python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py 2>&1 & + python /workspace/dimos/dimos/navigation/demo_ros_navigation.py 2>&1 & DIMOS_PID=$! # Give it a moment to start and check if it's still running diff --git a/docker/navigation/run_command.sh b/docker/navigation/run_command.sh index 44b67deaa9..cb7d6c3f85 100755 --- a/docker/navigation/run_command.sh +++ b/docker/navigation/run_command.sh @@ -18,7 +18,7 @@ if [ $# -eq 0 ]; then echo "Examples:" echo " $0 \"ros2 topic list\"" echo " $0 \"ros2 launch base_autonomy unity_simulation_bringup.launch.py\"" - echo " $0 \"python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py\"" + echo " $0 \"python /workspace/dimos/dimos/navigation/demo_ros_navigation.py\"" echo " $0 \"bash\" # For interactive shell" exit 1 fi diff --git a/docker/navigation/shell.sh b/docker/navigation/shell.sh index f91b7eeb0a..e2702e3192 100755 --- a/docker/navigation/shell.sh +++ b/docker/navigation/shell.sh @@ -32,7 +32,7 @@ echo -e "${YELLOW}Useful commands:${NC}" echo " - ros2 topic list" echo " - ros2 launch base_autonomy unity_simulation_bringup.launch.py" echo " - source /opt/dimos-venv/bin/activate" -echo " - python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" +echo " - python /workspace/dimos/dimos/navigation/demo_ros_navigation.py" echo "" cd ../.. diff --git a/docker/navigation/start.sh b/docker/navigation/start.sh index 7bc5fada83..deac416d11 100755 --- a/docker/navigation/start.sh +++ b/docker/navigation/start.sh @@ -76,7 +76,7 @@ case $MODE in ;; "dimos") echo -e "${YELLOW}Starting with DimOS navigation bot...${NC}" - CMD="python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" + CMD="python /workspace/dimos/dimos/navigation/demo_ros_navigation.py" ;; "all") echo -e "${YELLOW}Starting both ROS planner and DimOS...${NC}" @@ -87,7 +87,8 @@ case $MODE in echo "" echo "You can manually run:" echo " ROS planner: cd /ros2_ws/src/ros-navigation-autonomy-stack && ./system_simulation_with_route_planner.sh" - echo " DimOS: python /workspace/dimos/dimos/navigation/rosnav/nav_bot.py" + echo " DimOS: python /workspace/dimos/dimos/navigation/demo_ros_navigation.py" + echo "" CMD="bash" ;; From 5758f7a1a40235e5d1c049a7b218b4a1117fc805 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Thu, 30 Oct 2025 08:38:05 +0200 Subject: [PATCH 17/38] spacing --- docker/navigation/start.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/navigation/start.sh b/docker/navigation/start.sh index deac416d11..4ed7d2d568 100755 --- a/docker/navigation/start.sh +++ b/docker/navigation/start.sh @@ -88,7 +88,6 @@ case $MODE in echo "You can manually run:" echo " ROS planner: cd /ros2_ws/src/ros-navigation-autonomy-stack && ./system_simulation_with_route_planner.sh" echo " DimOS: python /workspace/dimos/dimos/navigation/demo_ros_navigation.py" - echo "" CMD="bash" ;; From f0ffa1cfa7529a50e371e3baf0a911dd84968bc2 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Thu, 30 Oct 2025 22:26:49 +0200 Subject: [PATCH 18/38] fix navigation --- dimos/navigation/demo_ros_navigation.py | 152 ++++++------------------ 1 file changed, 37 insertions(+), 115 deletions(-) mode change 100755 => 100644 dimos/navigation/demo_ros_navigation.py diff --git a/dimos/navigation/demo_ros_navigation.py b/dimos/navigation/demo_ros_navigation.py old mode 100755 new mode 100644 index a0544644d9..5c691a61da --- a/dimos/navigation/demo_ros_navigation.py +++ b/dimos/navigation/demo_ros_navigation.py @@ -1,137 +1,59 @@ -#!/usr/bin/env python3 -# Copyright 2025 Dimensional Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Demo script for testing ROS navigation with the ROSNav module.""" - -import logging -import signal -import sys -import threading import time - import rclpy -from rclpy.node import Node - -from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Vector3 -from dimos.utils.logging_config import setup_logger - -logger = setup_logger("demo_ros_navigation", level=logging.INFO) - -# Global variable to track if we should keep running -running = True -nav_module = None - -def signal_handler(signum, frame): - """Handle shutdown signals gracefully.""" - global running, nav_module - logger.info("Shutting down...") - running = False - if nav_module: - nav_module.stop_navigation() - sys.exit(0) +from dimos import core +from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Twist, Vector3 +from dimos.msgs.nav_msgs import Path +from dimos.msgs.sensor_msgs import PointCloud2 +from dimos.navigation.rosnav import ROSNav +from dimos.protocol import pubsub +from dimos.utils.logging_config import setup_logger -def main(): - """Main function to test ROS navigation - simplified standalone version.""" - global running, nav_module - - logger.info("Starting ROS navigation demo (standalone mode)...") - - # Register signal handlers for graceful shutdown - signal.signal(signal.SIGINT, signal_handler) - signal.signal(signal.SIGTERM, signal_handler) - # Initialize ROS2 if not already initialized - if not rclpy.ok(): - rclpy.init() +logger = setup_logger(__file__) - # Import here to avoid circular dependencies - from dimos.navigation.rosnav import ROSNav - # Create the navigation module instance - logger.info("Creating ROSNav module instance...") - nav_module = ROSNav() +def main() -> None: + pubsub.lcm.autoconf() + dimos = core.start(2) - # Since we can't use the full Dimos deployment, we need to handle - # the ROS spinning manually - def spin_thread(): - while running and rclpy.ok(): - try: - rclpy.spin_once(nav_module._node, timeout_sec=0.1) - except Exception as e: - if running: - logger.error(f"ROS2 spin error: {e}") + ros_nav = dimos.deploy(ROSNav) - # Start the navigation module - logger.info("Starting ROSNav module...") - # Note: We can't call nav_module.start() directly without proper Dimos setup - # Instead, we'll start the ROS spinning thread manually + ros_nav.goal_req.transport = core.LCMTransport("/goal", PoseStamped) + ros_nav.pointcloud.transport = core.LCMTransport("/pointcloud_map", PointCloud2) + ros_nav.global_pointcloud.transport = core.LCMTransport("/global_pointcloud", PointCloud2) + ros_nav.goal_active.transport = core.LCMTransport("/goal_active", PoseStamped) + ros_nav.path_active.transport = core.LCMTransport("/path_active", Path) + ros_nav.cmd_vel.transport = core.LCMTransport("/cmd_vel", Twist) - spin_thread_obj = threading.Thread(target=spin_thread, daemon=True) - spin_thread_obj.start() + ros_nav.start() - # Give the system time to initialize - logger.info("Waiting for system initialization...") - time.sleep(5.0) + logger.info("\nTesting navigation in 2 seconds...") + time.sleep(2) - # Create a test pose for navigation - # Moving 2 meters forward and 1 meter to the left relative to base_link test_pose = PoseStamped( - position=Vector3(2.0, 1.0, 0.0), - orientation=Quaternion(0.0, 0.0, 0.0, 1.0), - frame_id="base_link", # Relative to robot's current position ts=time.time(), + frame_id="map", + position=Vector3(2.0, 2.0, 0.0), + orientation=Quaternion(0.0, 0.0, 0.0, 1.0), ) - logger.info( - f"Navigating to test position: ({test_pose.position.x:.2f}, {test_pose.position.y:.2f}, {test_pose.position.z:.2f}) @ {test_pose.frame_id}" - ) - - # Perform navigation - logger.info("Sending navigation command...") - success = nav_module.navigate_to(test_pose, timeout=30.0) - - if success: - logger.info("Navigation successful!") - else: - logger.warning("Navigation failed or timed out") - - # Wait a bit before stopping - time.sleep(2.0) - - # Stop the navigation module - logger.info("Stopping navigation module...") - nav_module.stop_navigation() + logger.info("Sending navigation goal to: (2.0, 2.0, 0.0)") + success = ros_nav.navigate_to(test_pose, timeout=30.0) + logger.info(f"Navigated successfully: {success}") - # Clean up - running = False - if nav_module._node: - nav_module._node.destroy_node() - - if rclpy.ok(): - rclpy.shutdown() + try: + logger.info("\nNavBot running. Press Ctrl+C to stop.") + while True: + time.sleep(1) + except KeyboardInterrupt: + logger.info("\nShutting down...") + ros_nav.stop() - logger.info("Demo completed") + if rclpy.ok(): + rclpy.shutdown() if __name__ == "__main__": - try: - main() - except KeyboardInterrupt: - logger.info("Interrupted by user") - except Exception as e: - logger.error(f"Error: {e}", exc_info=True) - sys.exit(1) + main() \ No newline at end of file From 5d5bc0f17f3e428d8a4e7f699b2b136f62f0d050 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Thu, 30 Oct 2025 22:34:43 +0200 Subject: [PATCH 19/38] use ROS_DOMAIN_ID=42 --- dimos/navigation/demo_ros_navigation.py | 19 ++++++++++++++++--- docker/navigation/docker-compose.yml | 4 ++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/dimos/navigation/demo_ros_navigation.py b/dimos/navigation/demo_ros_navigation.py index 5c691a61da..fac19e1b24 100644 --- a/dimos/navigation/demo_ros_navigation.py +++ b/dimos/navigation/demo_ros_navigation.py @@ -1,6 +1,20 @@ +# Copyright 2025 Dimensional Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import time -import rclpy +import rclpy from dimos import core from dimos.msgs.geometry_msgs import PoseStamped, Quaternion, Twist, Vector3 @@ -10,7 +24,6 @@ from dimos.protocol import pubsub from dimos.utils.logging_config import setup_logger - logger = setup_logger(__file__) @@ -56,4 +69,4 @@ def main() -> None: if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/docker/navigation/docker-compose.yml b/docker/navigation/docker-compose.yml index 6187a86f2a..0b07fc7ee0 100644 --- a/docker/navigation/docker-compose.yml +++ b/docker/navigation/docker-compose.yml @@ -24,7 +24,7 @@ services: - QT_X11_NO_MITSHM=1 - NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES:-} - NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES:-} - - ROS_DOMAIN_ID=0 + - ROS_DOMAIN_ID=42 - ROBOT_CONFIG_PATH=mechanum_drive # Volume mounts @@ -62,4 +62,4 @@ services: working_dir: /workspace/dimos # Command to run (can be overridden) - command: bash \ No newline at end of file + command: bash From 65e72e177f82b12d3899d5b0143f595d91df91d5 Mon Sep 17 00:00:00 2001 From: Naveen Kulandaivelu Date: Tue, 4 Nov 2025 11:34:19 -0800 Subject: [PATCH 20/38] add setup script for new os installation for easy deployments --- docker/navigation/README.md | 53 ++- docker/navigation/setup.sh | 731 ++++++++++++++++++++++++++++++++++++ 2 files changed, 776 insertions(+), 8 deletions(-) create mode 100755 docker/navigation/setup.sh diff --git a/docker/navigation/README.md b/docker/navigation/README.md index 93413ff757..0cc18464fa 100644 --- a/docker/navigation/README.md +++ b/docker/navigation/README.md @@ -2,13 +2,50 @@ This directory contains Docker configuration files to run DimOS and the ROS autonomy stack in the same container, enabling communication between the two systems. -## Prerequisites +## New Ubuntu Installation + +**For fresh Ubuntu systems**, use the automated setup script: + +```bash +curl -fsSL https://raw.githubusercontent.com/dimensionalOS/dimos/dimos-rosnav-docker/docker/navigation/setup.sh | bash +``` + +Or download and run locally: + +```bash +wget https://raw.githubusercontent.com/dimensionalOS/dimos/dimos-rosnav-docker/docker/navigation/setup.sh +chmod +x setup.sh +./setup.sh +``` + +**Installation time:** Approximately 20-30 minutes depending on your internet connection. + +**After installation, start the demo:** +```bash +cd ~/dimos/docker/navigation +./start.sh --all +``` + +**Options:** +```bash +./setup.sh --help # Show all options +./setup.sh --install-dir /opt/dimos # Custom installation directory +./setup.sh --skip-build # Skip Docker image build +``` + +If the automated script encounters issues, follow the manual setup below. + +--- + +## Manual Setup + +### Prerequisites 1. **Install Docker with `docker compose` support**. Follow the [official Docker installation guide](https://docs.docker.com/engine/install/). 2. **Install NVIDIA GPU drivers**. See [NVIDIA driver installation](https://www.nvidia.com/download/index.aspx). 3. **Install NVIDIA Container Toolkit**. Follow the [installation guide](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html). -## Quick Start +### Quick Start 1. **Build the Docker image:** ```bash @@ -26,17 +63,17 @@ This directory contains Docker configuration files to run DimOS and the ROS auto ./start.sh --all ``` -## Manual Commands +### Manual Commands Once inside the container, you can manually run: -### ROS Autonomy Stack +#### ROS Autonomy Stack ```bash cd /ros2_ws/src/ros-navigation-autonomy-stack ./system_simulation_with_route_planner.sh ``` -### DimOS +#### DimOS ```bash # Activate virtual environment source /opt/dimos-venv/bin/activate @@ -48,7 +85,7 @@ python /workspace/dimos/dimos/navigation/demo_ros_navigation.py python /workspace/dimos/dimos/your_script.py ``` -### ROS Commands +#### ROS Commands ```bash # List ROS topics ros2 topic list @@ -63,7 +100,7 @@ ros2 topic pub /way_point geometry_msgs/msg/PointStamped "{ ros2 topic echo /state_estimation ``` -## Custom Commands +### Custom Commands Use the `run_command.sh` helper script to run custom commands: ```bash @@ -71,7 +108,7 @@ Use the `run_command.sh` helper script to run custom commands: ./run_command.sh "python /workspace/dimos/dimos/your_script.py" ``` -## Development +### Development The docker-compose.yml mounts the following directories for live development: - DimOS source: `..` → `/workspace/dimos` diff --git a/docker/navigation/setup.sh b/docker/navigation/setup.sh new file mode 100755 index 0000000000..10d7ec45bb --- /dev/null +++ b/docker/navigation/setup.sh @@ -0,0 +1,731 @@ +#!/bin/bash +set -e +set -o pipefail + +################################################################################ +# DimOS Navigation Setup Script +# +# Usage: ./setup.sh [OPTIONS] +# --install-dir DIR Installation directory (default: ~/dimos) +# --skip-docker Skip Docker installation +# --skip-build Skip building Docker images +# --help Show this help message +# +################################################################################ + +# Color codes for output +readonly RED='\033[0;31m' +readonly GREEN='\033[0;32m' +readonly YELLOW='\033[1;33m' +readonly BLUE='\033[0;34m' +readonly CYAN='\033[0;36m' +readonly NC='\033[0m' +readonly BOLD='\033[1m' + +# Configuration +INSTALL_DIR="${HOME}/dimos" +SKIP_DOCKER=false +SKIP_BUILD=false +LOG_FILE="${HOME}/dimos-setup.log" +SCRIPT_START_TIME=$(date +%s) + +# Step tracking +CURRENT_STEP=0 +TOTAL_STEPS=9 + +################################################################################ +# Utility Functions +################################################################################ + +log() { + local level="$1" + shift + local message="$*" + local timestamp=$(date '+%Y-%m-%d %H:%M:%S') + echo "[${timestamp}] [${level}] ${message}" >> "${LOG_FILE}" +} + +print_banner() { + echo -e "${CYAN}${BOLD}" + cat << "EOF" + ____ _ __ ___ ____ _____ + / __ \(_) |/ / / __ \/ ___/ + / / / / / /|_/ / / / / /\__ \ + / /_/ / / / / / / /_/ /___/ / +/_____/_/_/ /_/ \____//____/ + + Navigation Setup Script +EOF + echo -e "${NC}" + echo -e "${BLUE}This script will set up your Ubuntu system for DimOS Navigation${NC}" + echo -e "${BLUE}Installation may take 20-30 minutes depending on your connection${NC}" + echo "" +} + +step() { + CURRENT_STEP=$((CURRENT_STEP + 1)) + echo "" + echo -e "${CYAN}${BOLD}[Step ${CURRENT_STEP}/${TOTAL_STEPS}]${NC} ${BOLD}$1${NC}" + log "INFO" "Step ${CURRENT_STEP}/${TOTAL_STEPS}: $1" +} + +info() { + echo -e "${BLUE}ℹ${NC} $1" + log "INFO" "$1" +} + +success() { + echo -e "${GREEN}✓${NC} $1" + log "SUCCESS" "$1" +} + +warning() { + echo -e "${YELLOW}⚠${NC} $1" + log "WARNING" "$1" +} + +error() { + echo -e "${RED}✗${NC} $1" + log "ERROR" "$1" +} + +fatal() { + error "$1" + echo "" + echo -e "${RED}${BOLD}Installation failed.${NC}" + echo -e "Check the log file for details: ${LOG_FILE}" + echo "" + exit 1 +} + +confirm() { + local prompt="$1" + local default="${2:-n}" + local response + + if [[ "${default}" == "y" ]]; then + prompt="${prompt} [Y/n]: " + else + prompt="${prompt} [y/N]: " + fi + + read -r -p "$(echo -e "${YELLOW}${prompt}${NC}")" response + response=${response:-${default}} + + [[ "${response,,}" =~ ^y(es)?$ ]] +} + +check_command() { + command -v "$1" >/dev/null 2>&1 +} + +################################################################################ +# Pre-flight Checks +################################################################################ + +preflight_checks() { + step "Running pre-flight checks" + + if [[ "$(uname -s)" != "Linux" ]]; then + fatal "This script is designed for Linux systems only" + fi + + if ! check_command apt-get; then + fatal "This script requires Ubuntu or Debian-based system" + fi + + if [[ -f /etc/os-release ]]; then + source /etc/os-release + info "Detected: ${PRETTY_NAME}" + + OS_VERSION_CODENAME="${VERSION_CODENAME:-}" + + VERSION_NUM=$(echo "${VERSION_ID:-0}" | cut -d. -f1) + if ! [[ "${VERSION_NUM}" =~ ^[0-9]+$ ]]; then + warning "Unable to determine Ubuntu version number" + VERSION_NUM=0 + fi + + if [[ "${VERSION_NUM}" -ne 0 ]] && [[ "${VERSION_NUM}" -lt 24 ]]; then + warning "Ubuntu 24.04 is required. You have ${VERSION_ID}" + if ! confirm "Continue anyway?"; then + exit 0 + fi + fi + fi + + if [[ $EUID -eq 0 ]]; then + fatal "This script should NOT be run as root. Run as a regular user with sudo access." + fi + + if ! sudo -n true 2>/dev/null; then + info "This script requires sudo access. You may be prompted for your password." + if ! sudo true; then + fatal "Failed to obtain sudo access" + fi + fi + + local target_dir=$(dirname "${INSTALL_DIR}") + mkdir -p "${target_dir}" 2>/dev/null || target_dir="${HOME}" + local available_space=$(df -BG "${target_dir}" 2>/dev/null | awk 'NR==2 {print $4}' | sed 's/G//' || echo "0") + info "Available disk space at ${target_dir}: ${available_space}GB" + if [[ "${available_space}" -lt 50 ]]; then + warning "Low disk space detected. At least 50GB is recommended." + warning "Docker images and builds will require significant space." + if ! confirm "Continue anyway?"; then + exit 0 + fi + fi + + info "Checking internet connectivity..." + if ! ping -c 1 8.8.8.8 >/dev/null 2>&1; then + fatal "No internet connection detected. Please check your network." + fi + + success "Pre-flight checks passed" +} + +################################################################################ +# System Setup +################################################################################ + +update_system() { + step "Updating system packages" + + info "Running apt-get update..." + if sudo apt-get update -y >> "${LOG_FILE}" 2>&1; then + success "Package lists updated" + else + warning "Package update had some warnings (check log)" + fi +} + +install_base_tools() { + step "Installing base tools" + + local packages=( + "git" + "ssh" + "zip" + "curl" + "wget" + "jq" + "nano" + "vim" + "htop" + "ca-certificates" + "gnupg" + ) + + info "Installing: ${packages[*]}" + + if sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "${packages[@]}" >> "${LOG_FILE}" 2>&1; then + success "Base tools installed" + else + fatal "Failed to install base tools" + fi + + if check_command ufw; then + info "Configuring firewall (UFW)..." + if sudo ufw status | grep -q "Status: active"; then + info "UFW is active, ensuring SSH is allowed..." + sudo ufw allow 22/tcp >> "${LOG_FILE}" 2>&1 || true + else + info "UFW is inactive, skipping firewall configuration" + fi + fi +} + +################################################################################ +# Docker Installation +################################################################################ + +install_docker() { + if [[ "${SKIP_DOCKER}" == true ]]; then + info "Skipping Docker installation (--skip-docker flag)" + return + fi + + step "Installing Docker" + + if check_command docker; then + local docker_version=$(docker --version 2>/dev/null || echo "unknown") + success "Docker is already installed: ${docker_version}" + + if docker compose version >/dev/null 2>&1; then + success "Docker Compose plugin is available" + else + warning "Docker Compose plugin not found, will attempt to install" + fi + + if ! confirm "Reinstall Docker anyway?" "n"; then + return + fi + fi + + info "Adding Docker's official GPG key..." + sudo install -m 0755 -d /etc/apt/keyrings + + if curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg 2>> "${LOG_FILE}"; then + sudo chmod a+r /etc/apt/keyrings/docker.gpg + success "Docker GPG key added" + else + fatal "Failed to add Docker GPG key" + fi + + info "Adding Docker repository..." + local version_codename="${OS_VERSION_CODENAME}" + if [[ -z "${version_codename}" ]] && [[ -f /etc/os-release ]]; then + version_codename=$(. /etc/os-release && echo "$VERSION_CODENAME") + fi + + echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ + ${version_codename} stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + + success "Docker repository added" + + info "Updating package lists..." + sudo apt-get update -y >> "${LOG_FILE}" 2>&1 + + info "Installing Docker packages (this may take a few minutes)..." + local docker_packages=( + "docker-ce" + "docker-ce-cli" + "containerd.io" + "docker-buildx-plugin" + "docker-compose-plugin" + ) + + if sudo DEBIAN_FRONTEND=noninteractive apt-get install -y "${docker_packages[@]}" >> "${LOG_FILE}" 2>&1; then + success "Docker installed successfully" + else + fatal "Failed to install Docker packages" + fi + + info "Configuring Docker group permissions..." + + if ! getent group docker >/dev/null; then + sudo groupadd docker + fi + + if sudo usermod -aG docker "${USER}"; then + success "User ${USER} added to docker group" + else + warning "Failed to add user to docker group" + fi + + info "Verifying Docker installation..." + if sudo docker run --rm hello-world >> "${LOG_FILE}" 2>&1; then + success "Docker is working correctly" + else + warning "Docker verification failed, but installation may still be successful" + fi + + warning "Docker group changes require logout/login to take effect" + info "For now, we'll use 'sudo docker' commands" +} + +################################################################################ +# Git LFS Setup +################################################################################ + +install_git_lfs() { + step "Installing Git LFS" + + if check_command git-lfs; then + success "Git LFS is already installed" + return + fi + + info "Adding Git LFS repository..." + if curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash >> "${LOG_FILE}" 2>&1; then + success "Git LFS repository added" + else + fatal "Failed to add Git LFS repository" + fi + + info "Installing Git LFS..." + if sudo apt-get install -y git-lfs >> "${LOG_FILE}" 2>&1; then + success "Git LFS installed" + else + fatal "Failed to install Git LFS" + fi + + info "Configuring Git LFS..." + if git lfs install >> "${LOG_FILE}" 2>&1; then + success "Git LFS configured" + else + warning "Git LFS configuration had issues (may already be configured)" + fi +} + +################################################################################ +# SSH Key Configuration +################################################################################ + +setup_ssh_keys() { + step "Configuring GitHub SSH access" + + info "Testing GitHub SSH connection..." + if timeout 10 ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new -T git@github.com 2>&1 | grep -q "successfully authenticated"; then + success "GitHub SSH access is already configured" + return + fi + + warning "GitHub SSH access is not configured" + echo "" + echo -e "${YELLOW}${BOLD}SSH Key Setup Required${NC}" + echo "" + echo "To clone the private DimOS repository, you need SSH access to GitHub." + echo "" + + if [[ -f "${HOME}/.ssh/id_rsa.pub" ]] || [[ -f "${HOME}/.ssh/id_ed25519.pub" ]]; then + info "Existing SSH key found" + echo "" + + if [[ -f "${HOME}/.ssh/id_ed25519.pub" ]]; then + echo -e "${CYAN}Your public key (id_ed25519.pub):${NC}" + cat "${HOME}/.ssh/id_ed25519.pub" + elif [[ -f "${HOME}/.ssh/id_rsa.pub" ]]; then + echo -e "${CYAN}Your public key (id_rsa.pub):${NC}" + cat "${HOME}/.ssh/id_rsa.pub" + fi + + echo "" + echo -e "${YELLOW}Please add this key to your GitHub account:${NC}" + echo " 1. Go to: https://github.com/settings/keys" + echo " 2. Click 'New SSH key'" + echo " 3. Paste the key above" + echo " 4. Click 'Add SSH key'" + echo "" + else + info "No SSH key found. Let's create one." + echo "" + + if confirm "Generate a new SSH key?" "y"; then + local email + echo -n "Enter your GitHub email address: " + read -r email + + info "Generating SSH key..." + if ssh-keygen -t ed25519 -C "${email}" -f "${HOME}/.ssh/id_ed25519" -N "" >> "${LOG_FILE}" 2>&1; then + success "SSH key generated" + + eval "$(ssh-agent -s)" > /dev/null + if ssh-add "${HOME}/.ssh/id_ed25519" 2>> "${LOG_FILE}"; then + success "SSH key added to agent" + else + warning "Could not add key to ssh-agent (non-critical)" + fi + + echo "" + echo -e "${CYAN}Your new public key:${NC}" + cat "${HOME}/.ssh/id_ed25519.pub" + echo "" + echo -e "${YELLOW}Please add this key to your GitHub account:${NC}" + echo " 1. Go to: https://github.com/settings/keys" + echo " 2. Click 'New SSH key'" + echo " 3. Paste the key above" + echo " 4. Click 'Add SSH key'" + echo "" + else + fatal "Failed to generate SSH key" + fi + else + echo "" + error "SSH key is required to continue" + echo "Please set up SSH access manually and run this script again." + exit 1 + fi + fi + + echo "" + if ! confirm "Have you added the SSH key to GitHub?" "n"; then + echo "" + warning "Setup paused. Please add the SSH key and run this script again." + exit 0 + fi + + info "Testing GitHub SSH connection..." + if timeout 10 ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new -T git@github.com 2>&1 | grep -q "successfully authenticated"; then + success "GitHub SSH access verified!" + else + error "GitHub SSH connection failed" + echo "" + echo "Please verify:" + echo " 1. The SSH key was added to GitHub correctly" + echo " 2. You're using the correct GitHub account" + echo " 3. Try: ssh -T git@github.com" + echo "" + if ! confirm "Continue anyway?" "n"; then + exit 1 + fi + fi +} + +################################################################################ +# Repository Setup +################################################################################ + +clone_repository() { + step "Cloning DimOS repository" + + if [[ -d "${INSTALL_DIR}" ]]; then + if [[ -d "${INSTALL_DIR}/.git" ]]; then + success "Repository already exists at ${INSTALL_DIR}" + + local remote_url=$(git -C "${INSTALL_DIR}" remote get-url origin 2>/dev/null || echo "") + if [[ "${remote_url}" =~ "dimos" ]]; then + info "Existing repository verified" + return + else + warning "Directory exists but doesn't appear to be the DimOS repo" + if ! confirm "Remove and re-clone?" "n"; then + fatal "Cannot proceed with existing directory" + fi + rm -rf "${INSTALL_DIR}" + fi + else + warning "Directory ${INSTALL_DIR} exists but is not a git repository" + if ! confirm "Remove and re-clone?" "n"; then + fatal "Cannot proceed with existing directory" + fi + rm -rf "${INSTALL_DIR}" + fi + fi + + info "Cloning to ${INSTALL_DIR}..." + if git clone git@github.com:dimensionalOS/dimos.git "${INSTALL_DIR}" >> "${LOG_FILE}" 2>&1; then + success "Repository cloned successfully" + else + fatal "Failed to clone repository. Check your SSH access." + fi + + info "Pulling Git LFS files (this may take several minutes)..." + if git -C "${INSTALL_DIR}" lfs pull >> "${LOG_FILE}" 2>&1; then + success "LFS files downloaded" + else + warning "Some LFS files may not have downloaded correctly" + fi +} + +checkout_branch() { + step "Checking out dimos-rosnav-docker branch" + + local current_branch=$(git -C "${INSTALL_DIR}" branch --show-current 2>/dev/null || echo "") + if [[ "${current_branch}" == "dimos-rosnav-docker" ]]; then + success "Already on dimos-rosnav-docker branch" + return + fi + + info "Switching to dimos-rosnav-docker branch..." + if git -C "${INSTALL_DIR}" checkout dimos-rosnav-docker >> "${LOG_FILE}" 2>&1; then + success "Branch checked out" + else + info "Fetching remote branches..." + git -C "${INSTALL_DIR}" fetch origin >> "${LOG_FILE}" 2>&1 + + if git -C "${INSTALL_DIR}" checkout dimos-rosnav-docker >> "${LOG_FILE}" 2>&1; then + success "Branch checked out" + else + fatal "Failed to checkout dimos-rosnav-docker branch" + fi + fi +} + +################################################################################ +# Build and Launch +################################################################################ + +build_docker_images() { + if [[ "${SKIP_BUILD}" == true ]]; then + info "Skipping Docker build (--skip-build flag)" + return + fi + + step "Building Docker images" + + local build_dir="${INSTALL_DIR}/docker/navigation" + if [[ ! -d "${build_dir}" ]]; then + fatal "Directory not found: ${build_dir}" + fi + + if [[ ! -f "${build_dir}/build.sh" ]]; then + fatal "build.sh not found in ${build_dir}" + fi + + echo "" + warning "Building Docker images will take 10-15 minutes and download ~30GB" + info "This step will:" + echo " • Clone the ROS navigation autonomy stack" + echo " • Build a large Docker image with ROS Jazzy" + echo " • Install all dependencies" + echo "" + + if ! confirm "Start the build now?" "y"; then + warning "Build skipped. You can build later with:" + echo " cd ${build_dir}" + echo " ./build.sh" + return + fi + + info "Starting build process..." + echo "" + + pushd "${build_dir}" >> "${LOG_FILE}" 2>&1 || fatal "Failed to change to ${build_dir}" + + ./build.sh 2>&1 | tee -a "${LOG_FILE}" + local build_status=${PIPESTATUS[0]} + + popd >> "${LOG_FILE}" 2>&1 || true + + if [[ ${build_status} -eq 0 ]]; then + success "Docker images built successfully" + else + fatal "Docker build failed. Check the log for details." + fi +} + +################################################################################ +# Completion +################################################################################ + +print_summary() { + local elapsed=$(($(date +%s) - SCRIPT_START_TIME)) + local minutes=$((elapsed / 60)) + local seconds=$((elapsed % 60)) + + echo "" + echo "" + echo -e "${GREEN}${BOLD}╔══════════════════════════════════════════════════════════╗${NC}" + echo -e "${GREEN}${BOLD}║ ║${NC}" + echo -e "${GREEN}${BOLD}║ Setup completed successfully! 🎉 ║${NC}" + echo -e "${GREEN}${BOLD}║ ║${NC}" + echo -e "${GREEN}${BOLD}╚══════════════════════════════════════════════════════════╝${NC}" + echo "" + echo -e "${CYAN}Installation time: ${minutes}m ${seconds}s${NC}" + echo -e "${CYAN}Installation directory: ${INSTALL_DIR}${NC}" + echo -e "${CYAN}Log file: ${LOG_FILE}${NC}" + echo "" + echo -e "${BOLD}Next steps:${NC}" + echo "" + echo " 1. If Docker commands failed, log out and back in for group changes" + echo " Or run: newgrp docker" + echo "" + echo " 2. Navigate to the project:" + echo " cd ${INSTALL_DIR}/docker/navigation" + echo "" + echo " 3. Start the demo:" + echo " ./start.sh --all" + echo "" + echo " 4. Or get an interactive shell:" + echo " ./start.sh" + echo "" + echo -e "${CYAN}For more information, see the README.md in docker/navigation/${NC}" + echo "" +} + +################################################################################ +# Argument Parsing +################################################################################ + +parse_arguments() { + while [[ $# -gt 0 ]]; do + case $1 in + --install-dir) + if [[ -z "$2" ]] || [[ "$2" == --* ]]; then + error "Error: --install-dir requires a directory path" + echo "Run '$0 --help' for usage information" + exit 1 + fi + INSTALL_DIR="$2" + shift 2 + ;; + --skip-docker) + SKIP_DOCKER=true + shift + ;; + --skip-build) + SKIP_BUILD=true + shift + ;; + --help) + print_banner + cat << EOF +Usage: $0 [OPTIONS] + +Options: + --install-dir DIR Installation directory (default: ~/dimos) + --skip-docker Skip Docker installation + --skip-build Skip building Docker images + --help Show this help message + +Examples: + $0 # Full installation + $0 --install-dir /opt/dimos # Install to custom directory + $0 --skip-docker # Skip Docker installation + $0 --skip-docker --skip-build # Only clone repository + +After installation, navigate to the project and start the demo: + cd ~/dimos/docker/navigation + ./start.sh --all + +For more information, visit: + https://github.com/dimensionalOS/dimos + +EOF + exit 0 + ;; + *) + error "Unknown option: $1" + echo "Run '$0 --help' for usage information" + exit 1 + ;; + esac + done +} + +################################################################################ +# Main +################################################################################ + +main() { + log "INFO" "DimOS Navigation Setup Script started" + log "INFO" "User: ${USER}" + log "INFO" "Install directory: ${INSTALL_DIR}" + + print_banner + + echo -e "${YELLOW}This script will:${NC}" + echo " • Update your system" + echo " • Install Docker and dependencies" + echo " • Configure Git LFS" + echo " • Set up GitHub SSH access" + echo " • Clone the DimOS repository" + echo " • Build Docker images (~30GB, 10-15 minutes)" + echo "" + + if ! confirm "Continue with installation?" "y"; then + echo "Installation cancelled." + exit 0 + fi + + preflight_checks + update_system + install_base_tools + install_docker + install_git_lfs + setup_ssh_keys + clone_repository + checkout_branch + build_docker_images + + print_summary + + log "INFO" "Setup completed successfully" +} + +parse_arguments "$@" +main From fb9ea0fd1991bcd90ba31492c3fca4aecacc0236 Mon Sep 17 00:00:00 2001 From: Naveen Kulandaivelu Date: Tue, 4 Nov 2025 11:49:08 -0800 Subject: [PATCH 21/38] use main branch for public use --- docker/navigation/README.md | 4 ++-- docker/navigation/setup.sh | 27 +-------------------------- 2 files changed, 3 insertions(+), 28 deletions(-) diff --git a/docker/navigation/README.md b/docker/navigation/README.md index 0cc18464fa..66625bbef8 100644 --- a/docker/navigation/README.md +++ b/docker/navigation/README.md @@ -7,13 +7,13 @@ This directory contains Docker configuration files to run DimOS and the ROS auto **For fresh Ubuntu systems**, use the automated setup script: ```bash -curl -fsSL https://raw.githubusercontent.com/dimensionalOS/dimos/dimos-rosnav-docker/docker/navigation/setup.sh | bash +curl -fsSL https://raw.githubusercontent.com/dimensionalOS/dimos/main/docker/navigation/setup.sh | bash ``` Or download and run locally: ```bash -wget https://raw.githubusercontent.com/dimensionalOS/dimos/dimos-rosnav-docker/docker/navigation/setup.sh +wget https://raw.githubusercontent.com/dimensionalOS/dimos/main/docker/navigation/setup.sh chmod +x setup.sh ./setup.sh ``` diff --git a/docker/navigation/setup.sh b/docker/navigation/setup.sh index 10d7ec45bb..5edf9abfd5 100755 --- a/docker/navigation/setup.sh +++ b/docker/navigation/setup.sh @@ -31,7 +31,7 @@ SCRIPT_START_TIME=$(date +%s) # Step tracking CURRENT_STEP=0 -TOTAL_STEPS=9 +TOTAL_STEPS=8 ################################################################################ # Utility Functions @@ -511,30 +511,6 @@ clone_repository() { fi } -checkout_branch() { - step "Checking out dimos-rosnav-docker branch" - - local current_branch=$(git -C "${INSTALL_DIR}" branch --show-current 2>/dev/null || echo "") - if [[ "${current_branch}" == "dimos-rosnav-docker" ]]; then - success "Already on dimos-rosnav-docker branch" - return - fi - - info "Switching to dimos-rosnav-docker branch..." - if git -C "${INSTALL_DIR}" checkout dimos-rosnav-docker >> "${LOG_FILE}" 2>&1; then - success "Branch checked out" - else - info "Fetching remote branches..." - git -C "${INSTALL_DIR}" fetch origin >> "${LOG_FILE}" 2>&1 - - if git -C "${INSTALL_DIR}" checkout dimos-rosnav-docker >> "${LOG_FILE}" 2>&1; then - success "Branch checked out" - else - fatal "Failed to checkout dimos-rosnav-docker branch" - fi - fi -} - ################################################################################ # Build and Launch ################################################################################ @@ -719,7 +695,6 @@ main() { install_git_lfs setup_ssh_keys clone_repository - checkout_branch build_docker_images print_summary From 2e2b65a521459d9c496c6d15c771dba4c878a0d0 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Wed, 5 Nov 2025 01:04:18 +0200 Subject: [PATCH 22/38] include hardware in docker --- docker/navigation/.env.hardware | 59 ++++++++ docker/navigation/Dockerfile | 56 ++++++- docker/navigation/README.md | 107 +++++++------ docker/navigation/build.sh | 14 +- docker/navigation/docker-compose.yml | 120 ++++++++++++--- docker/navigation/run_command.sh | 44 ------ docker/navigation/shell.sh | 41 ----- docker/navigation/start.sh | 215 ++++++++++++++++++--------- 8 files changed, 421 insertions(+), 235 deletions(-) create mode 100644 docker/navigation/.env.hardware delete mode 100755 docker/navigation/run_command.sh delete mode 100755 docker/navigation/shell.sh diff --git a/docker/navigation/.env.hardware b/docker/navigation/.env.hardware new file mode 100644 index 0000000000..cc0d8741c3 --- /dev/null +++ b/docker/navigation/.env.hardware @@ -0,0 +1,59 @@ +# Hardware Configuration Environment Variables +# Copy this file to .env and customize for your hardware setup + +# ============================================ +# NVIDIA GPU Support +# ============================================ +# Set the Docker runtime to nvidia for GPU support +DOCKER_RUNTIME=nvidia + +# ============================================ +# ROS Configuration +# ============================================ +# ROS domain ID for multi-robot setups +ROS_DOMAIN_ID=42 + +# Robot configuration (mechanum_drive or standard) +ROBOT_CONFIG_PATH=mechanum_drive + +# ============================================ +# Mid-360 Lidar Configuration +# ============================================ +# Network interface connected to the lidar (e.g., eth0, enp0s3) +# Find with: ip addr show +LIDAR_INTERFACE=eth0 + +# Processing computer IP address on the lidar subnet +# Must be 192.168.1.5 as specified in the config +LIDAR_IP=192.168.1.5 + +# Last 2 digits of your lidar serial number +# Find on the sticker under QR code on the lidar +# This will set lidar IP to 192.168.1.1XX where XX is this value +LIDAR_SERIAL=00 + +# ============================================ +# Motor Controller Configuration +# ============================================ +# Serial device for motor controller +# Check with: ls /dev/ttyACM* or ls /dev/ttyUSB* +MOTOR_SERIAL_DEVICE=/dev/ttyACM0 + +# ============================================ +# Network Communication (for base station) +# ============================================ +# Enable WiFi buffer optimization for data transmission +# Set to true if using wireless base station +ENABLE_WIFI_BUFFER=false + +# ============================================ +# Display Configuration +# ============================================ +# X11 display (usually auto-detected) +# DISPLAY=:0 + +# ============================================ +# Camera Configuration (optional) +# ============================================ +# Uncomment if using cameras +# CAMERA_DEVICE=/dev/video0 diff --git a/docker/navigation/Dockerfile b/docker/navigation/Dockerfile index a477c86d2c..dda3131439 100644 --- a/docker/navigation/Dockerfile +++ b/docker/navigation/Dockerfile @@ -31,6 +31,12 @@ RUN apt-get update && apt-get install -y \ iputils-ping \ net-tools \ iproute2 \ + ethtool \ + # USB and serial tools (for hardware support) + usbutils \ + udev \ + # Time synchronization (for multi-computer setup) + chrony \ # Editor (optional but useful) nano \ vim \ @@ -62,12 +68,30 @@ WORKDIR ${WORKSPACE} # Set up ROS environment RUN echo "source /opt/ros/${ROS_DISTRO}/setup.bash" >> ~/.bashrc -# Build the autonomy stack workspace (simulation mode - skipping SLAM and Mid-360 driver) +# Build all hardware dependencies +RUN \ + # Build Livox-SDK2 for Mid-360 lidar + cd ${WORKSPACE}/src/ros-navigation-autonomy-stack/src/utilities/livox_ros_driver2/Livox-SDK2 && \ + mkdir -p build && cd build && \ + cmake .. && make -j$(nproc) && make install && ldconfig && \ + # Install Sophus + cd ${WORKSPACE}/src/ros-navigation-autonomy-stack/src/slam/dependency/Sophus && \ + mkdir -p build && cd build && \ + cmake .. -DBUILD_TESTS=OFF && make -j$(nproc) && make install && \ + # Install Ceres Solver + cd ${WORKSPACE}/src/ros-navigation-autonomy-stack/src/slam/dependency/ceres-solver && \ + mkdir -p build && cd build && \ + cmake .. && make -j$(nproc) && make install && \ + # Install GTSAM + cd ${WORKSPACE}/src/ros-navigation-autonomy-stack/src/slam/dependency/gtsam && \ + mkdir -p build && cd build && \ + cmake .. -DGTSAM_USE_SYSTEM_EIGEN=ON -DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF && \ + make -j$(nproc) && make install && ldconfig + +# Build the autonomy stack RUN /bin/bash -c "source /opt/ros/${ROS_DISTRO}/setup.bash && \ cd ${WORKSPACE} && \ - colcon build --symlink-install \ - --cmake-args -DCMAKE_BUILD_TYPE=Release \ - --packages-skip arise_slam_mid360 arise_slam_mid360_msgs livox_ros_driver2" + colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release" # Source the workspace setup RUN echo "source ${WORKSPACE}/install/setup.bash" >> ~/.bashrc @@ -95,6 +119,10 @@ COPY docker/navigation/run_both.sh /usr/local/bin/run_both.sh COPY docker/navigation/ros_launch_wrapper.py /usr/local/bin/ros_launch_wrapper.py RUN chmod +x /usr/local/bin/run_both.sh /usr/local/bin/ros_launch_wrapper.py +# Set up udev rules for USB devices (motor controller) +RUN echo 'SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", MODE="0666", GROUP="dialout"' > /etc/udev/rules.d/99-motor-controller.rules && \ + usermod -a -G dialout root || true + # Set up entrypoint script RUN echo '#!/bin/bash\n\ set -e\n\ @@ -107,7 +135,23 @@ source ${WORKSPACE}/install/setup.bash\n\ source /opt/dimos-venv/bin/activate\n\ \n\ # Export ROBOT_CONFIG_PATH for autonomy stack\n\ -export ROBOT_CONFIG_PATH="mechanum_drive"\n\ +export ROBOT_CONFIG_PATH="${ROBOT_CONFIG_PATH:-mechanum_drive}"\n\ +\n\ +# Hardware-specific configurations\n\ +if [ "${HARDWARE_MODE}" = "true" ]; then\n\ + # Set network buffer sizes for WiFi data transmission (if needed)\n\ + if [ "${ENABLE_WIFI_BUFFER}" = "true" ]; then\n\ + sysctl -w net.core.rmem_max=67108864 net.core.rmem_default=67108864 2>/dev/null || true\n\ + sysctl -w net.core.wmem_max=67108864 net.core.wmem_default=67108864 2>/dev/null || true\n\ + fi\n\ + \n\ + # Configure network interface for Mid-360 lidar if specified\n\ + if [ -n "${LIDAR_INTERFACE}" ] && [ -n "${LIDAR_IP}" ]; then\n\ + ip addr add ${LIDAR_IP}/24 dev ${LIDAR_INTERFACE} 2>/dev/null || true\n\ + ip link set ${LIDAR_INTERFACE} up 2>/dev/null || true\n\ + fi\n\ + \n\ +fi\n\ \n\ # Execute the command\n\ exec "$@"' > /ros_entrypoint.sh && \ @@ -117,4 +161,4 @@ exec "$@"' > /ros_entrypoint.sh && \ ENTRYPOINT ["/ros_entrypoint.sh"] # Default command -CMD ["bash"] \ No newline at end of file +CMD ["bash"] diff --git a/docker/navigation/README.md b/docker/navigation/README.md index 66625bbef8..c91bb0b273 100644 --- a/docker/navigation/README.md +++ b/docker/navigation/README.md @@ -7,13 +7,13 @@ This directory contains Docker configuration files to run DimOS and the ROS auto **For fresh Ubuntu systems**, use the automated setup script: ```bash -curl -fsSL https://raw.githubusercontent.com/dimensionalOS/dimos/main/docker/navigation/setup.sh | bash +curl -fsSL https://raw.githubusercontent.com/dimensionalOS/dimos/dimos-rosnav-docker/docker/navigation/setup.sh | bash ``` Or download and run locally: ```bash -wget https://raw.githubusercontent.com/dimensionalOS/dimos/main/docker/navigation/setup.sh +wget https://raw.githubusercontent.com/dimensionalOS/dimos/dimos-rosnav-docker/docker/navigation/setup.sh chmod +x setup.sh ./setup.sh ``` @@ -35,85 +35,84 @@ cd ~/dimos/docker/navigation If the automated script encounters issues, follow the manual setup below. ---- - -## Manual Setup - -### Prerequisites +## Prerequisites 1. **Install Docker with `docker compose` support**. Follow the [official Docker installation guide](https://docs.docker.com/engine/install/). 2. **Install NVIDIA GPU drivers**. See [NVIDIA driver installation](https://www.nvidia.com/download/index.aspx). 3. **Install NVIDIA Container Toolkit**. Follow the [installation guide](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html). -### Quick Start +## Quick Start -1. **Build the Docker image:** - ```bash - ./build.sh - ``` - This will: - - Clone the ros-navigation-autonomy-stack repository (jazzy branch) - - Build a Docker image with both ROS and DimOS dependencies - - Set up the environment for both systems +**Build the Docker image:** - Note that the build will take over 10 minutes and build an image over 30GiB. +```bash +./build.sh +``` -2. **Run the container:** - ```bash - ./start.sh --all - ``` +This will: +- Clone the ros-navigation-autonomy-stack repository (jazzy branch) +- Build a Docker image with both ROS and DimOS dependencies +- Set up the environment for both systems -### Manual Commands +Note that the build will take over 10 minutes and build an image over 30GiB. -Once inside the container, you can manually run: +**Run the simulator to test it's working:** -#### ROS Autonomy Stack ```bash -cd /ros2_ws/src/ros-navigation-autonomy-stack -./system_simulation_with_route_planner.sh +./start.sh --simulation ``` -#### DimOS +## On Real Hardware + +### Copy Environment Template ```bash -# Activate virtual environment -source /opt/dimos-venv/bin/activate +cp .env.hardware .env +``` -# Run navigation demo -python /workspace/dimos/dimos/navigation/demo_ros_navigation.py +### Edit `.env` File -# Or run other DimOS scripts -python /workspace/dimos/dimos/your_script.py -``` +Key configuration parameters: -#### ROS Commands ```bash -# List ROS topics -ros2 topic list +# Lidar Configuration +LIDAR_INTERFACE=eth0 # Your ethernet interface (find with: ip link show) +LIDAR_IP=192.168.1.5 # Must be 192.168.1.5 for Mid-360 +LIDAR_SERIAL=42 # Last 2 digits of lidar serial number + +# Motor Controller +MOTOR_SERIAL_DEVICE=/dev/ttyACM0 # Serial device (check with: ls /dev/ttyACM*) +``` -# Send navigation goal -ros2 topic pub /way_point geometry_msgs/msg/PointStamped "{ - header: {frame_id: 'map'}, - point: {x: 5.0, y: 3.0, z: 0.0} -}" --once +### Start the Container -# Monitor robot state -ros2 topic echo /state_estimation +Start the container and leave it open. + +```bash +./start.sh --hardware ``` -### Custom Commands +It doesn't do anything by default. You have to run commands on it by exec-ing: -Use the `run_command.sh` helper script to run custom commands: ```bash -./run_command.sh "ros2 topic list" -./run_command.sh "python /workspace/dimos/dimos/your_script.py" +docker exec -it dimos_hardware_container bash ``` -### Development +### In the container + +In the container you can run any of the ROS or python code. -The docker-compose.yml mounts the following directories for live development: -- DimOS source: `..` → `/workspace/dimos` -- Autonomy stack source: `./ros-navigation-autonomy-stack/src` → `/ros2_ws/src/ros-navigation-autonomy-stack/src` +#### ROS -Changes to these files will be reflected in the container without rebuilding. +```bash +cd /ros2_ws/src/ros-navigation-autonomy-stack +./system_real_robot_with_route_planner.sh +``` -**Note**: The Python virtual environment is installed at `/opt/dimos-venv` inside the container (not in the mounted `/workspace/dimos` directory). This ensures the container uses its own dependencies regardless of whether the host has a `.venv` or not. \ No newline at end of file +### Python + +Move 2 meters forward, and 2 meters left. + +```bash +source /opt/dimos-venv/bin/activate +python3 dimos/navigation/demo_ros_navigation.py +``` diff --git a/docker/navigation/build.sh b/docker/navigation/build.sh index bf89185dc7..da0aa2de8c 100755 --- a/docker/navigation/build.sh +++ b/docker/navigation/build.sh @@ -32,6 +32,8 @@ echo "This will take a while as it needs to:" echo " - Download base ROS Jazzy image" echo " - Install ROS packages and dependencies" echo " - Build the autonomy stack" +echo " - Build Livox-SDK2 for Mid-360 lidar" +echo " - Build SLAM dependencies (Sophus, Ceres, GTSAM)" echo " - Install Python dependencies for DimOS" echo "" @@ -44,6 +46,14 @@ echo -e "${GREEN}================================${NC}" echo -e "${GREEN}Docker image built successfully!${NC}" echo -e "${GREEN}================================${NC}" echo "" -echo "You can now run the container using:" -echo -e "${YELLOW} ./start.sh --all${NC}" +echo "To run in SIMULATION mode:" +echo -e "${YELLOW} ./start.sh${NC}" +echo "" +echo "To run in HARDWARE mode:" +echo " 1. Configure your hardware settings in .env file" +echo " (copy from .env.hardware if needed)" +echo " 2. Run the hardware container:" +echo -e "${YELLOW} ./start.sh --hardware${NC}" +echo "" +echo "The script runs in foreground. Press Ctrl+C to stop." echo "" diff --git a/docker/navigation/docker-compose.yml b/docker/navigation/docker-compose.yml index 0b07fc7ee0..0c88eb9aaf 100644 --- a/docker/navigation/docker-compose.yml +++ b/docker/navigation/docker-compose.yml @@ -1,10 +1,12 @@ services: - dimos_autonomy_stack: + # Simulation profile + dimos_simulation: build: context: ../.. dockerfile: docker/navigation/Dockerfile image: dimos_autonomy_stack:jazzy - container_name: dimos_autonomy_container + container_name: dimos_simulation_container + profiles: ["", "simulation"] # Active by default (empty profile) AND with --profile simulation # Enable interactive terminal stdin_open: true @@ -13,19 +15,18 @@ services: # Network configuration - required for ROS communication network_mode: host - # Privileged mode for hardware access (required for real robot and some devices) - privileged: true - - runtime: ${DOCKER_RUNTIME:-runc} + # Use nvidia runtime for GPU acceleration (falls back to runc if not available) + runtime: ${DOCKER_RUNTIME:-nvidia} # Environment variables for display and ROS environment: - DISPLAY=${DISPLAY} - QT_X11_NO_MITSHM=1 - - NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES:-} - - NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES:-} - - ROS_DOMAIN_ID=42 - - ROBOT_CONFIG_PATH=mechanum_drive + - NVIDIA_VISIBLE_DEVICES=${NVIDIA_VISIBLE_DEVICES:-all} + - NVIDIA_DRIVER_CAPABILITIES=${NVIDIA_DRIVER_CAPABILITIES:-all} + - ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-42} + - ROBOT_CONFIG_PATH=${ROBOT_CONFIG_PATH:-mechanum_drive} + - HARDWARE_MODE=false # Volume mounts volumes: @@ -36,30 +37,113 @@ services: # Mount Unity environment models (if available) - ./unity_models:/ros2_ws/src/ros-navigation-autonomy-stack/src/base_autonomy/vehicle_simulator/mesh/unity:rw - # Mount the autonomy stack source for development (optional - comment out if not needed) - - ./ros-navigation-autonomy-stack/src:/ros2_ws/src/ros-navigation-autonomy-stack/src:rw + # Mount the autonomy stack source for development + - ./ros-navigation-autonomy-stack:/ros2_ws/src/ros-navigation-autonomy-stack:rw # Mount entire dimos directory for live development - ../..:/workspace/dimos:rw - # Mount bagfiles directory (optional) + # Mount bagfiles directory - ./bagfiles:/ros2_ws/bagfiles:rw # Mount config files for easy editing - ./config:/ros2_ws/config:rw - # Device access (for joystick controllers, serial devices, and cameras) + # Device access (for joystick controllers) + devices: + - /dev/input:/dev/input + - /dev/dri:/dev/dri + + # Working directory + working_dir: /workspace/dimos + + # Command to run both ROS and DimOS + command: /usr/local/bin/run_both.sh + + # Hardware profile - for real robot + dimos_hardware: + build: + context: ../.. + dockerfile: docker/navigation/Dockerfile + image: dimos_autonomy_stack:jazzy + container_name: dimos_hardware_container + profiles: ["hardware"] + + # Enable interactive terminal + stdin_open: true + tty: true + + # Network configuration - MUST be host for hardware access + network_mode: host + + # Privileged mode REQUIRED for hardware access + privileged: true + + # Override runtime for GPU support + runtime: ${DOCKER_RUNTIME:-nvidia} + + # Hardware environment variables + environment: + - DISPLAY=${DISPLAY} + - QT_X11_NO_MITSHM=1 + - NVIDIA_VISIBLE_DEVICES=all + - NVIDIA_DRIVER_CAPABILITIES=all + - ROS_DOMAIN_ID=${ROS_DOMAIN_ID:-42} + - ROBOT_CONFIG_PATH=${ROBOT_CONFIG_PATH:-mechanum_drive} + - HARDWARE_MODE=true + # Mid-360 Lidar configuration + - LIDAR_INTERFACE=${LIDAR_INTERFACE:-} + - LIDAR_IP=${LIDAR_IP:-192.168.1.5} + - LIDAR_SERIAL=${LIDAR_SERIAL:-} + # Motor controller + - MOTOR_SERIAL_DEVICE=${MOTOR_SERIAL_DEVICE:-/dev/ttyACM0} + # Network optimization + - ENABLE_WIFI_BUFFER=${ENABLE_WIFI_BUFFER:-false} + + # Volume mounts + volumes: + # X11 socket for GUI + - /tmp/.X11-unix:/tmp/.X11-unix:rw + - ${HOME}/.Xauthority:/root/.Xauthority:rw + # Mount Unity environment models (optional for hardware) + - ./unity_models:/ros2_ws/src/ros-navigation-autonomy-stack/src/base_autonomy/vehicle_simulator/mesh/unity:rw + # Mount the autonomy stack source + - ./ros-navigation-autonomy-stack:/ros2_ws/src/ros-navigation-autonomy-stack:rw + # Mount entire dimos directory + - ../..:/workspace/dimos:rw + # Mount bagfiles directory + - ./bagfiles:/ros2_ws/bagfiles:rw + # Mount config files for easy editing + - ./config:/ros2_ws/config:rw + # Hardware-specific volumes + - ./logs:/ros2_ws/logs:rw + - /etc/localtime:/etc/localtime:ro + - /etc/timezone:/etc/timezone:ro + - /dev/bus/usb:/dev/bus/usb:rw + - /sys:/sys:ro + + # Device access for hardware devices: + # Joystick controllers - /dev/input:/dev/input + # GPU access - /dev/dri:/dev/dri - # Uncomment if using real robot with motor controller - # - /dev/ttyACM0:/dev/ttyACM0 + # Motor controller serial ports + - ${MOTOR_SERIAL_DEVICE:-/dev/ttyACM0}:${MOTOR_SERIAL_DEVICE:-/dev/ttyACM0} + # Additional serial ports (can be enabled via environment) # - /dev/ttyUSB0:/dev/ttyUSB0 - # Uncomment if using cameras + # - /dev/ttyUSB1:/dev/ttyUSB1 + # Cameras (can be enabled via environment) # - /dev/video0:/dev/video0 # Working directory working_dir: /workspace/dimos - # Command to run (can be overridden) + # Command - for hardware, we run bash as the user will launch specific scripts command: bash + + # Capabilities for hardware operations + cap_add: + - NET_ADMIN # Network interface configuration + - SYS_ADMIN # System operations + - SYS_TIME # Time synchronization diff --git a/docker/navigation/run_command.sh b/docker/navigation/run_command.sh deleted file mode 100755 index cb7d6c3f85..0000000000 --- a/docker/navigation/run_command.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -set -e - -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' - -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd "$SCRIPT_DIR" - -if [ $# -eq 0 ]; then - echo -e "${RED}Error: No command provided${NC}" - echo "" - echo "Usage: $0 \"command to run\"" - echo "" - echo "Examples:" - echo " $0 \"ros2 topic list\"" - echo " $0 \"ros2 launch base_autonomy unity_simulation_bringup.launch.py\"" - echo " $0 \"python /workspace/dimos/dimos/navigation/demo_ros_navigation.py\"" - echo " $0 \"bash\" # For interactive shell" - exit 1 -fi - -xhost +local:docker 2>/dev/null || true - -cleanup() { - xhost -local:docker 2>/dev/null || true -} - -trap cleanup EXIT - -echo -e "${GREEN}========================================${NC}" -echo -e "${GREEN}Running command in DimOS + ROS Container${NC}" -echo -e "${GREEN}========================================${NC}" -echo "" -echo -e "${YELLOW}Command: $@${NC}" -echo "" - -cd ../.. - -# Run the command in the container -docker compose -f docker/navigation/docker-compose.yml run --rm dimos_autonomy_stack bash -c "$@" diff --git a/docker/navigation/shell.sh b/docker/navigation/shell.sh deleted file mode 100755 index e2702e3192..0000000000 --- a/docker/navigation/shell.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -# Quick script to enter an interactive shell in the container - -set -e - -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' - -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd "$SCRIPT_DIR" - -xhost +local:docker 2>/dev/null || true - -cleanup() { - xhost -local:docker 2>/dev/null || true -} - -trap cleanup EXIT - -echo -e "${GREEN}====================================${NC}" -echo -e "${GREEN}Entering DimOS + ROS Container Shell${NC}" -echo -e "${GREEN}====================================${NC}" -echo "" -echo -e "${YELLOW}Environment:${NC}" -echo " - ROS workspace: /ros2_ws" -echo " - DimOS path: /workspace/dimos" -echo " - Python venv: /opt/dimos-venv" -echo "" -echo -e "${YELLOW}Useful commands:${NC}" -echo " - ros2 topic list" -echo " - ros2 launch base_autonomy unity_simulation_bringup.launch.py" -echo " - source /opt/dimos-venv/bin/activate" -echo " - python /workspace/dimos/dimos/navigation/demo_ros_navigation.py" -echo "" - -cd ../.. - -# Enter interactive shell -docker compose -f docker/navigation/docker-compose.yml run --rm dimos_autonomy_stack bash diff --git a/docker/navigation/start.sh b/docker/navigation/start.sh index 4ed7d2d568..9b667d894b 100755 --- a/docker/navigation/start.sh +++ b/docker/navigation/start.sh @@ -4,11 +4,121 @@ set -e GREEN='\033[0;32m' YELLOW='\033[1;33m' +RED='\033[0;31m' NC='\033[0m' +# Parse command line arguments +MODE="simulation" +while [[ $# -gt 0 ]]; do + case $1 in + --hardware) + MODE="hardware" + shift + ;; + --simulation) + MODE="simulation" + shift + ;; + --help|-h) + echo "Usage: $0 [OPTIONS]" + echo "" + echo "Options:" + echo " --simulation Start simulation container (default)" + echo " --hardware Start hardware container for real robot" + echo " --help, -h Show this help message" + echo "" + echo "Examples:" + echo " $0 # Start simulation container" + echo " $0 --hardware # Start hardware container" + echo "" + echo "Press Ctrl+C to stop the container" + exit 0 + ;; + *) + echo -e "${RED}Unknown option: $1${NC}" + echo "Run '$0 --help' for usage information" + exit 1 + ;; + esac +done + SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" cd "$SCRIPT_DIR" +echo -e "${GREEN}================================================${NC}" +echo -e "${GREEN}Starting DimOS Docker Container${NC}" +echo -e "${GREEN}Mode: ${MODE}${NC}" +echo -e "${GREEN}================================================${NC}" +echo "" + +# Hardware-specific checks +if [ "$MODE" = "hardware" ]; then + # Check if .env file exists + if [ ! -f ".env" ]; then + if [ -f ".env.hardware" ]; then + echo -e "${YELLOW}Creating .env from .env.hardware template...${NC}" + cp .env.hardware .env + echo -e "${RED}Please edit .env file with your hardware configuration:${NC}" + echo " - LIDAR_SERIAL: Last 2 digits of your Mid-360 serial number" + echo " - LIDAR_INTERFACE: Network interface connected to lidar" + echo " - MOTOR_SERIAL_DEVICE: Serial device for motor controller" + echo "" + echo "After editing, run this script again." + exit 1 + fi + fi + + # Source the environment file + if [ -f ".env" ]; then + set -a + source .env + set +a + + # Check for required environment variables + if [ -z "$LIDAR_SERIAL" ] || [ "$LIDAR_SERIAL" = "00" ]; then + echo -e "${YELLOW}Warning: LIDAR_SERIAL not configured in .env${NC}" + echo "Set LIDAR_SERIAL to the last 2 digits of your Mid-360 serial" + fi + + # Check for serial devices + echo -e "${GREEN}Checking for serial devices...${NC}" + if [ -e "${MOTOR_SERIAL_DEVICE:-/dev/ttyACM0}" ]; then + echo -e " Found device at: ${MOTOR_SERIAL_DEVICE:-/dev/ttyACM0}" + else + echo -e "${YELLOW} Warning: Device not found at ${MOTOR_SERIAL_DEVICE:-/dev/ttyACM0}${NC}" + echo -e "${YELLOW} Available serial devices:${NC}" + ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null || echo " None found" + fi + + # Check network interface for lidar + if [ -n "$LIDAR_INTERFACE" ]; then + echo -e "${GREEN}Checking network interface for lidar...${NC}" + if ip link show "$LIDAR_INTERFACE" &>/dev/null; then + echo -e " Network interface $LIDAR_INTERFACE found" + else + echo -e "${YELLOW} Warning: Interface $LIDAR_INTERFACE not found${NC}" + echo -e "${YELLOW} Available interfaces:${NC}" + ip link show | grep -E "^[0-9]+:" | awk '{print " " $2}' | sed 's/:$//' + fi + fi + fi + +fi + +# Check if unified image exists +if ! docker images | grep -q "dimos_autonomy_stack.*jazzy"; then + echo -e "${YELLOW}Docker image not found. Building...${NC}" + ./build.sh +fi + +# Check for X11 display +if [ -z "$DISPLAY" ]; then + echo -e "${YELLOW}Warning: DISPLAY not set. GUI applications may not work.${NC}" + export DISPLAY=:0 +fi + +# Allow X11 connections from Docker +echo -e "${GREEN}Configuring X11 access...${NC}" xhost +local:docker 2>/dev/null || true cleanup() { @@ -17,83 +127,48 @@ cleanup() { trap cleanup EXIT -echo -e "${GREEN}=============================================${NC}" -echo -e "${GREEN}Starting DimOS + ROS Autonomy Stack Container${NC}" -echo -e "${GREEN}=============================================${NC}" -echo "" - -if [ ! -d "unity_models" ] && [[ "$*" == *"--ros-planner"* || "$*" == *"--all"* ]]; then - echo -e "${YELLOW}WARNING: Unity models directory not found!${NC}" - echo "The Unity simulator may not work properly." - echo "Download from: https://drive.google.com/drive/folders/1G1JYkccvoSlxyySuTlPfvmrWoJUO8oSs" - echo "" +# Check for NVIDIA runtime +if docker info 2>/dev/null | grep -q nvidia; then + echo -e "${GREEN}NVIDIA Docker runtime detected${NC}" + export DOCKER_RUNTIME=nvidia + if [ "$MODE" = "hardware" ]; then + export NVIDIA_VISIBLE_DEVICES=all + export NVIDIA_DRIVER_CAPABILITIES=all + fi +else + echo -e "${RED}NVIDIA Docker runtime not found. GPU acceleration disabled.${NC}" + exit 1 fi -if command -v nvidia-smi &> /dev/null && nvidia-smi &> /dev/null; then - export DOCKER_RUNTIME=nvidia - export NVIDIA_VISIBLE_DEVICES=all - export NVIDIA_DRIVER_CAPABILITIES=all - echo -e "${GREEN}GPU mode enabled${NC} (using nvidia runtime)" - echo "" +# Set container name for reference +if [ "$MODE" = "hardware" ]; then + CONTAINER_NAME="dimos_hardware_container" else - export DOCKER_RUNTIME=runc - export NVIDIA_VISIBLE_DEVICES= - export NVIDIA_DRIVER_CAPABILITIES= - echo -e "${YELLOW}CPU-only mode${NC} (no GPU detected)" - echo "" + CONTAINER_NAME="dimos_simulation_container" fi -MODE="default" -if [[ "$1" == "--ros-planner" ]]; then - MODE="ros-planner" -elif [[ "$1" == "--dimos" ]]; then - MODE="dimos" -elif [[ "$1" == "--all" ]]; then - MODE="all" -elif [[ "$1" == "--help" || "$1" == "-h" ]]; then - echo "Usage: $0 [OPTIONS]" +# Print helpful info before starting +echo "" +if [ "$MODE" = "hardware" ]; then + echo "Hardware mode - Interactive shell" echo "" - echo "Options:" - echo " --ros-planner Start with ROS route planner" - echo " --dimos Start with DimOS Unitree G1 controller" - echo " --all Start both ROS planner and DimOS" - echo " --help Show this help message" + echo -e "${GREEN}=================================================${NC}" + echo -e "${GREEN}The container is running. Exec in to run scripts:${NC}" + echo -e " ${YELLOW}docker exec -it ${CONTAINER_NAME} bash${NC}" + echo -e "${GREEN}=================================================${NC}" +else + echo "Simulation mode - Auto-starting ROS simulation and DimOS" echo "" - echo "GPU auto-detection: Automatically uses GPU if nvidia-smi is available" - echo "Without options, starts an interactive bash shell" + echo "The container will automatically run:" + echo " - ROS navigation stack with route planner" + echo " - DimOS navigation demo" echo "" - echo "Example:" - echo " $0 --all" - exit 0 + echo "To enter the container from another terminal:" + echo " docker exec -it ${CONTAINER_NAME} bash" fi -cd ../.. - -case $MODE in - "ros-planner") - echo -e "${YELLOW}Starting with ROS route planner...${NC}" - CMD="bash -c 'cd /ros2_ws/src/ros-navigation-autonomy-stack && ./system_simulation_with_route_planner.sh'" - ;; - "dimos") - echo -e "${YELLOW}Starting with DimOS navigation bot...${NC}" - CMD="python /workspace/dimos/dimos/navigation/demo_ros_navigation.py" - ;; - "all") - echo -e "${YELLOW}Starting both ROS planner and DimOS...${NC}" - CMD="/usr/local/bin/run_both.sh" - ;; - "default") - echo -e "${YELLOW}Starting interactive bash shell...${NC}" - echo "" - echo "You can manually run:" - echo " ROS planner: cd /ros2_ws/src/ros-navigation-autonomy-stack && ./system_simulation_with_route_planner.sh" - echo " DimOS: python /workspace/dimos/dimos/navigation/demo_ros_navigation.py" - echo "" - CMD="bash" - ;; -esac - -docker compose -f docker/navigation/docker-compose.yml run --rm dimos_autonomy_stack $CMD - -echo "" -echo -e "${GREEN}Container stopped.${NC}" +if [ "$MODE" = "hardware" ]; then + docker compose -f docker-compose.yml --profile hardware up +else + docker compose -f docker-compose.yml up +fi From c762ac659d96a492d2792e0484640e266fd23f26 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Thu, 6 Nov 2025 03:45:11 +0200 Subject: [PATCH 23/38] describe how to configure lidar and wifi --- docker/navigation/MID360_config.json | 42 ++++++++++++++++++++++++++++ docker/navigation/README.md | 14 ++++++++-- docker/navigation/docker-compose.yml | 4 ++- 3 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 docker/navigation/MID360_config.json diff --git a/docker/navigation/MID360_config.json b/docker/navigation/MID360_config.json new file mode 100644 index 0000000000..996fa60140 --- /dev/null +++ b/docker/navigation/MID360_config.json @@ -0,0 +1,42 @@ +{ + "lidar_summary_info" : { + "lidar_type": 8 + }, + "MID360": { + "lidar_net_info" : { + "cmd_data_port": 56100, + "push_msg_port": 56200, + "point_data_port": 56300, + "imu_data_port": 56400, + "log_data_port": 56500 + }, + "host_net_info" : { + "cmd_data_ip" : "192.168.1.5", + "cmd_data_port": 56101, + "push_msg_ip": "192.168.1.5", + "push_msg_port": 56201, + "point_data_ip": "192.168.1.5", + "point_data_port": 56301, + "imu_data_ip" : "192.168.1.5", + "imu_data_port": 56401, + "log_data_ip" : "", + "log_data_port": 56501 + } + }, + "lidar_configs" : [ + { + "ip" : "192.168.1.116", + "pcl_data_type" : 1, + "pattern_mode" : 0, + "extrinsic_parameter" : { + "roll": 0.0, + "pitch": 0.0, + "yaw": 0.0, + "x": 0, + "y": 0, + "z": 0 + } + } + ] +} + diff --git a/docker/navigation/README.md b/docker/navigation/README.md index c91bb0b273..f8cb39ec3d 100644 --- a/docker/navigation/README.md +++ b/docker/navigation/README.md @@ -64,6 +64,14 @@ Note that the build will take over 10 minutes and build an image over 30GiB. ## On Real Hardware +### Configure the WiFi + +[Read this](https://github.com/dimensionalOS/ros-navigation-autonomy-stack/tree/jazzy?tab=readme-ov-file#transmitting-data-over-wifi) to see how to configure the WiFi. + +### Configure the Livox Lidar + +Edit the `MID360_config.json` config if you need to customise the lidar. This file will be mounted in the container. + ### Copy Environment Template ```bash cp .env.hardware .env @@ -91,7 +99,7 @@ Start the container and leave it open. ./start.sh --hardware ``` -It doesn't do anything by default. You have to run commands on it by exec-ing: +It doesn't do anything by default. You have to run commands on it by `exec`-ing: ```bash docker exec -it dimos_hardware_container bash @@ -99,7 +107,7 @@ docker exec -it dimos_hardware_container bash ### In the container -In the container you can run any of the ROS or python code. +In the container you can run any of the ROS or Python code. #### ROS @@ -110,7 +118,7 @@ cd /ros2_ws/src/ros-navigation-autonomy-stack ### Python -Move 2 meters forward, and 2 meters left. +Demo which moves the robot 2 meters forward and 2 meters left. ```bash source /opt/dimos-venv/bin/activate diff --git a/docker/navigation/docker-compose.yml b/docker/navigation/docker-compose.yml index 0c88eb9aaf..0ebf9766de 100644 --- a/docker/navigation/docker-compose.yml +++ b/docker/navigation/docker-compose.yml @@ -98,7 +98,7 @@ services: # Motor controller - MOTOR_SERIAL_DEVICE=${MOTOR_SERIAL_DEVICE:-/dev/ttyACM0} # Network optimization - - ENABLE_WIFI_BUFFER=${ENABLE_WIFI_BUFFER:-false} + - ENABLE_WIFI_BUFFER=true # Volume mounts volumes: @@ -117,6 +117,8 @@ services: - ./config:/ros2_ws/config:rw # Hardware-specific volumes - ./logs:/ros2_ws/logs:rw + # Mount Livox MID360 config for easy customization + - ./MID360_config.json:/ros2_ws/src/ros-navigation-autonomy-stack/src/utilities/livox_ros_driver2/config/MID360_config.json:rw - /etc/localtime:/etc/localtime:ro - /etc/timezone:/etc/timezone:ro - /dev/bus/usb:/dev/bus/usb:rw From 34879caf1cd3d431119623f07a7f5fa61d039119 Mon Sep 17 00:00:00 2001 From: paul-nechifor <1262969+paul-nechifor@users.noreply.github.com> Date: Thu, 6 Nov 2025 01:45:48 +0000 Subject: [PATCH 24/38] CI code cleanup --- docker/navigation/MID360_config.json | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/docker/navigation/MID360_config.json b/docker/navigation/MID360_config.json index 996fa60140..3de2b7c6d8 100644 --- a/docker/navigation/MID360_config.json +++ b/docker/navigation/MID360_config.json @@ -1,34 +1,34 @@ { - "lidar_summary_info" : { + "lidar_summary_info": { "lidar_type": 8 }, "MID360": { - "lidar_net_info" : { + "lidar_net_info": { "cmd_data_port": 56100, "push_msg_port": 56200, "point_data_port": 56300, "imu_data_port": 56400, "log_data_port": 56500 }, - "host_net_info" : { - "cmd_data_ip" : "192.168.1.5", + "host_net_info": { + "cmd_data_ip": "192.168.1.5", "cmd_data_port": 56101, "push_msg_ip": "192.168.1.5", "push_msg_port": 56201, "point_data_ip": "192.168.1.5", "point_data_port": 56301, - "imu_data_ip" : "192.168.1.5", + "imu_data_ip": "192.168.1.5", "imu_data_port": 56401, - "log_data_ip" : "", + "log_data_ip": "", "log_data_port": 56501 } }, - "lidar_configs" : [ + "lidar_configs": [ { - "ip" : "192.168.1.116", - "pcl_data_type" : 1, - "pattern_mode" : 0, - "extrinsic_parameter" : { + "ip": "192.168.1.116", + "pcl_data_type": 1, + "pattern_mode": 0, + "extrinsic_parameter": { "roll": 0.0, "pitch": 0.0, "yaw": 0.0, @@ -39,4 +39,3 @@ } ] } - From 0f697346c0a5a61e63d62ecefd7b1748f2b9c263 Mon Sep 17 00:00:00 2001 From: Stash Pomichter Date: Wed, 5 Nov 2025 20:20:46 -0800 Subject: [PATCH 25/38] Added livox config for G1 edu --- docker/navigation/MID360_G1_EDU_config.json | 46 +++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 docker/navigation/MID360_G1_EDU_config.json diff --git a/docker/navigation/MID360_G1_EDU_config.json b/docker/navigation/MID360_G1_EDU_config.json new file mode 100644 index 0000000000..be43a355ed --- /dev/null +++ b/docker/navigation/MID360_G1_EDU_config.json @@ -0,0 +1,46 @@ +{ + "lidar_summary_info": { + "lidar_type": 8 + }, + + "MID360": { + "lidar_net_info": { + "cmd_data_port": 56100, + "push_msg_port": 56200, + "point_data_port": 56300, + "imu_data_port": 56400, + "log_data_port": 56500 + }, + + "host_net_info": { + "cmd_data_ip": "192.168.123.5", + "cmd_data_port": 56101, + "push_msg_ip": "192.168.123.5", + "push_msg_port": 56201, + "point_data_ip": "192.168.123.5", + "point_data_port": 56301, + "imu_data_ip": "192.168.123.5", + "imu_data_port": 56401, + "log_data_ip": "192.168.123.5", + "log_data_port": 56501 + } + }, + + "lidar_configs": [ + { + "ip": "192.168.123.120", + "pcl_data_type": 1, + "pattern_mode": 0, + "extrinsic_parameter": { + "roll": 0.0, + "pitch": 0.0, + "yaw": 0.0, + "x": 0.0, + "y": 0.0, + "z": 0.0 + } + } + ] + } + + \ No newline at end of file From 311f69ae87188380867dec54c7cb64501ff78094 Mon Sep 17 00:00:00 2001 From: spomichter <12108168+spomichter@users.noreply.github.com> Date: Thu, 6 Nov 2025 04:21:56 +0000 Subject: [PATCH 26/38] CI code cleanup --- docker/navigation/MID360_G1_EDU_config.json | 81 ++++++++++----------- 1 file changed, 38 insertions(+), 43 deletions(-) diff --git a/docker/navigation/MID360_G1_EDU_config.json b/docker/navigation/MID360_G1_EDU_config.json index be43a355ed..8399b2d9a6 100644 --- a/docker/navigation/MID360_G1_EDU_config.json +++ b/docker/navigation/MID360_G1_EDU_config.json @@ -1,46 +1,41 @@ { - "lidar_summary_info": { - "lidar_type": 8 + "lidar_summary_info": { + "lidar_type": 8 + }, + "MID360": { + "lidar_net_info": { + "cmd_data_port": 56100, + "push_msg_port": 56200, + "point_data_port": 56300, + "imu_data_port": 56400, + "log_data_port": 56500 }, - - "MID360": { - "lidar_net_info": { - "cmd_data_port": 56100, - "push_msg_port": 56200, - "point_data_port": 56300, - "imu_data_port": 56400, - "log_data_port": 56500 - }, - - "host_net_info": { - "cmd_data_ip": "192.168.123.5", - "cmd_data_port": 56101, - "push_msg_ip": "192.168.123.5", - "push_msg_port": 56201, - "point_data_ip": "192.168.123.5", - "point_data_port": 56301, - "imu_data_ip": "192.168.123.5", - "imu_data_port": 56401, - "log_data_ip": "192.168.123.5", - "log_data_port": 56501 + "host_net_info": { + "cmd_data_ip": "192.168.123.5", + "cmd_data_port": 56101, + "push_msg_ip": "192.168.123.5", + "push_msg_port": 56201, + "point_data_ip": "192.168.123.5", + "point_data_port": 56301, + "imu_data_ip": "192.168.123.5", + "imu_data_port": 56401, + "log_data_ip": "192.168.123.5", + "log_data_port": 56501 + } + }, + "lidar_configs": [ + { + "ip": "192.168.123.120", + "pcl_data_type": 1, + "pattern_mode": 0, + "extrinsic_parameter": { + "roll": 0.0, + "pitch": 0.0, + "yaw": 0.0, + "x": 0.0, + "y": 0.0, + "z": 0.0 } - }, - - "lidar_configs": [ - { - "ip": "192.168.123.120", - "pcl_data_type": 1, - "pattern_mode": 0, - "extrinsic_parameter": { - "roll": 0.0, - "pitch": 0.0, - "yaw": 0.0, - "x": 0.0, - "y": 0.0, - "z": 0.0 - } - } - ] - } - - \ No newline at end of file + } + ] +} From 8284ccbdcb4712cfa46bddd33096a9e987e75b79 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Fri, 7 Nov 2025 00:28:58 +0200 Subject: [PATCH 27/38] generate MID360_config.json --- docker/navigation/.env.hardware | 12 ++--- docker/navigation/Dockerfile | 52 ++++++++++++++++++++- docker/navigation/MID360_G1_EDU_config.json | 41 ---------------- docker/navigation/MID360_config.json | 41 ---------------- docker/navigation/README.md | 8 ++-- docker/navigation/docker-compose.yml | 6 +-- docker/navigation/start.sh | 9 ++-- 7 files changed, 67 insertions(+), 102 deletions(-) delete mode 100644 docker/navigation/MID360_G1_EDU_config.json delete mode 100644 docker/navigation/MID360_config.json diff --git a/docker/navigation/.env.hardware b/docker/navigation/.env.hardware index cc0d8741c3..00d3503661 100644 --- a/docker/navigation/.env.hardware +++ b/docker/navigation/.env.hardware @@ -24,13 +24,13 @@ ROBOT_CONFIG_PATH=mechanum_drive LIDAR_INTERFACE=eth0 # Processing computer IP address on the lidar subnet -# Must be 192.168.1.5 as specified in the config -LIDAR_IP=192.168.1.5 +# Must be on the same subnet as the lidar (e.g., 192.168.1.5) +LIDAR_COMPUTER_IP=192.168.1.5 -# Last 2 digits of your lidar serial number -# Find on the sticker under QR code on the lidar -# This will set lidar IP to 192.168.1.1XX where XX is this value -LIDAR_SERIAL=00 +# Full IP address of your Mid-360 lidar +# This should match the IP configured on your lidar device +# Common patterns: 192.168.1.1XX or 192.168.123.1XX +LIDAR_IP=192.168.1.116 # ============================================ # Motor Controller Configuration diff --git a/docker/navigation/Dockerfile b/docker/navigation/Dockerfile index dda3131439..7a5f3da648 100644 --- a/docker/navigation/Dockerfile +++ b/docker/navigation/Dockerfile @@ -146,11 +146,59 @@ if [ "${HARDWARE_MODE}" = "true" ]; then\n\ fi\n\ \n\ # Configure network interface for Mid-360 lidar if specified\n\ - if [ -n "${LIDAR_INTERFACE}" ] && [ -n "${LIDAR_IP}" ]; then\n\ - ip addr add ${LIDAR_IP}/24 dev ${LIDAR_INTERFACE} 2>/dev/null || true\n\ + if [ -n "${LIDAR_INTERFACE}" ] && [ -n "${LIDAR_COMPUTER_IP}" ]; then\n\ + ip addr add ${LIDAR_COMPUTER_IP}/24 dev ${LIDAR_INTERFACE} 2>/dev/null || true\n\ ip link set ${LIDAR_INTERFACE} up 2>/dev/null || true\n\ fi\n\ \n\ + # Generate MID360_config.json if LIDAR_COMPUTER_IP and LIDAR_IP are set\n\ + if [ -n "${LIDAR_COMPUTER_IP}" ] && [ -n "${LIDAR_IP}" ]; then\n\ + cat > ${WORKSPACE}/src/ros-navigation-autonomy-stack/src/utilities/livox_ros_driver2/config/MID360_config.json < Date: Fri, 7 Nov 2025 07:01:54 +0200 Subject: [PATCH 28/38] remove CAMERA_DEVICE and update ROBOT_CONFIG_PATH comment --- docker/navigation/.env.hardware | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/docker/navigation/.env.hardware b/docker/navigation/.env.hardware index 00d3503661..2b1d7d6d6b 100644 --- a/docker/navigation/.env.hardware +++ b/docker/navigation/.env.hardware @@ -13,7 +13,7 @@ DOCKER_RUNTIME=nvidia # ROS domain ID for multi-robot setups ROS_DOMAIN_ID=42 -# Robot configuration (mechanum_drive or standard) +# Robot configuration ('mechanum_drive', 'unitree/unitree_g1', 'unitree/unitree_g1', etc) ROBOT_CONFIG_PATH=mechanum_drive # ============================================ @@ -51,9 +51,3 @@ ENABLE_WIFI_BUFFER=false # ============================================ # X11 display (usually auto-detected) # DISPLAY=:0 - -# ============================================ -# Camera Configuration (optional) -# ============================================ -# Uncomment if using cameras -# CAMERA_DEVICE=/dev/video0 From 2f7acbccf83787b2a4a11b23ebbb88ce6f65f3de Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Fri, 7 Nov 2025 07:20:15 +0200 Subject: [PATCH 29/38] add LIDAR_GATEWAY --- docker/navigation/.env.hardware | 3 +++ docker/navigation/Dockerfile | 3 +++ docker/navigation/README.md | 1 + docker/navigation/docker-compose.yml | 1 + docker/navigation/start.sh | 5 +++++ 5 files changed, 13 insertions(+) diff --git a/docker/navigation/.env.hardware b/docker/navigation/.env.hardware index 2b1d7d6d6b..178dec136e 100644 --- a/docker/navigation/.env.hardware +++ b/docker/navigation/.env.hardware @@ -27,6 +27,9 @@ LIDAR_INTERFACE=eth0 # Must be on the same subnet as the lidar (e.g., 192.168.1.5) LIDAR_COMPUTER_IP=192.168.1.5 +# Gateway IP address for the lidar subnet +LIDAR_GATEWAY=192.168.1.1 + # Full IP address of your Mid-360 lidar # This should match the IP configured on your lidar device # Common patterns: 192.168.1.1XX or 192.168.123.1XX diff --git a/docker/navigation/Dockerfile b/docker/navigation/Dockerfile index 7a5f3da648..dfc5e59f55 100644 --- a/docker/navigation/Dockerfile +++ b/docker/navigation/Dockerfile @@ -149,6 +149,9 @@ if [ "${HARDWARE_MODE}" = "true" ]; then\n\ if [ -n "${LIDAR_INTERFACE}" ] && [ -n "${LIDAR_COMPUTER_IP}" ]; then\n\ ip addr add ${LIDAR_COMPUTER_IP}/24 dev ${LIDAR_INTERFACE} 2>/dev/null || true\n\ ip link set ${LIDAR_INTERFACE} up 2>/dev/null || true\n\ + if [ -n "${LIDAR_GATEWAY}" ]; then\n\ + ip route add default via ${LIDAR_GATEWAY} dev ${LIDAR_INTERFACE} 2>/dev/null || true\n\ + fi\n\ fi\n\ \n\ # Generate MID360_config.json if LIDAR_COMPUTER_IP and LIDAR_IP are set\n\ diff --git a/docker/navigation/README.md b/docker/navigation/README.md index 739a624179..0c1dc0523f 100644 --- a/docker/navigation/README.md +++ b/docker/navigation/README.md @@ -85,6 +85,7 @@ Key configuration parameters: # Lidar Configuration LIDAR_INTERFACE=eth0 # Your ethernet interface (find with: ip link show) LIDAR_COMPUTER_IP=192.168.1.5 # Computer IP on the lidar subnet +LIDAR_GATEWAY=192.168.1.1 # Gateway IP address for the lidar subnet LIDAR_IP=192.168.1.116 # Full IP address of your Mid-360 lidar # Motor Controller diff --git a/docker/navigation/docker-compose.yml b/docker/navigation/docker-compose.yml index e1f1aed9a8..1b83bb66ad 100644 --- a/docker/navigation/docker-compose.yml +++ b/docker/navigation/docker-compose.yml @@ -94,6 +94,7 @@ services: # Mid-360 Lidar configuration - LIDAR_INTERFACE=${LIDAR_INTERFACE:-} - LIDAR_COMPUTER_IP=${LIDAR_COMPUTER_IP:-192.168.1.5} + - LIDAR_GATEWAY=${LIDAR_GATEWAY:-192.168.1.1} - LIDAR_IP=${LIDAR_IP:-192.168.1.116} # Motor controller - MOTOR_SERIAL_DEVICE=${MOTOR_SERIAL_DEVICE:-/dev/ttyACM0} diff --git a/docker/navigation/start.sh b/docker/navigation/start.sh index 30a9fc1ea2..a5ede2e0f1 100755 --- a/docker/navigation/start.sh +++ b/docker/navigation/start.sh @@ -81,6 +81,11 @@ if [ "$MODE" = "hardware" ]; then echo "Set LIDAR_IP to the actual IP address of your Mid-360 lidar" fi + if [ -z "$LIDAR_GATEWAY" ]; then + echo -e "${YELLOW}Warning: LIDAR_GATEWAY not configured in .env${NC}" + echo "Set LIDAR_GATEWAY to the gateway IP address for the lidar subnet" + fi + # Check for serial devices echo -e "${GREEN}Checking for serial devices...${NC}" if [ -e "${MOTOR_SERIAL_DEVICE:-/dev/ttyACM0}" ]; then From 90d2b8dc3625fe92cdb8e279df5caf95867f2d6f Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Fri, 7 Nov 2025 07:41:36 +0200 Subject: [PATCH 30/38] continue even without nvidia runtime --- docker/navigation/start.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docker/navigation/start.sh b/docker/navigation/start.sh index a5ede2e0f1..cd05dff69b 100755 --- a/docker/navigation/start.sh +++ b/docker/navigation/start.sh @@ -142,8 +142,7 @@ if docker info 2>/dev/null | grep -q nvidia; then export NVIDIA_DRIVER_CAPABILITIES=all fi else - echo -e "${RED}NVIDIA Docker runtime not found. GPU acceleration disabled.${NC}" - exit 1 + echo -e "${YELLOW}NVIDIA Docker runtime not found. GPU acceleration disabled.${NC}" fi # Set container name for reference From b8dd34d1a0880153c6ca69248382a6a205b0e9c6 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Fri, 7 Nov 2025 07:45:30 +0200 Subject: [PATCH 31/38] use runc for hardware --- docker/navigation/.env.hardware | 4 ++-- docker/navigation/docker-compose.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/navigation/.env.hardware b/docker/navigation/.env.hardware index 178dec136e..4b6b41a03f 100644 --- a/docker/navigation/.env.hardware +++ b/docker/navigation/.env.hardware @@ -4,8 +4,8 @@ # ============================================ # NVIDIA GPU Support # ============================================ -# Set the Docker runtime to nvidia for GPU support -DOCKER_RUNTIME=nvidia +# Set the Docker runtime to nvidia for GPU support (it's runc by default) +#DOCKER_RUNTIME=nvidia # ============================================ # ROS Configuration diff --git a/docker/navigation/docker-compose.yml b/docker/navigation/docker-compose.yml index 1b83bb66ad..8678297e95 100644 --- a/docker/navigation/docker-compose.yml +++ b/docker/navigation/docker-compose.yml @@ -80,7 +80,7 @@ services: privileged: true # Override runtime for GPU support - runtime: ${DOCKER_RUNTIME:-nvidia} + runtime: ${DOCKER_RUNTIME:-runc} # Hardware environment variables environment: From 4ae131f61afde9f19bc21503323b897fa8562983 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Fri, 7 Nov 2025 08:09:18 +0200 Subject: [PATCH 32/38] add turbojpeg --- docker/navigation/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/navigation/Dockerfile b/docker/navigation/Dockerfile index dfc5e59f55..c8d49d706e 100644 --- a/docker/navigation/Dockerfile +++ b/docker/navigation/Dockerfile @@ -53,6 +53,8 @@ RUN apt-get update && apt-get install -y \ libglib2.0-0 \ # For Open3D libgomp1 \ + # For TurboJPEG + libturbojpeg0-dev \ # Clean up && rm -rf /var/lib/apt/lists/* From 4e01815f8296fc92ae4675167bbdcf0568d9e644 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Fri, 7 Nov 2025 08:20:26 +0200 Subject: [PATCH 33/38] describe what ./build.sh does in the readme. --- docker/navigation/README.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/docker/navigation/README.md b/docker/navigation/README.md index 0c1dc0523f..f518cf7674 100644 --- a/docker/navigation/README.md +++ b/docker/navigation/README.md @@ -41,11 +41,14 @@ If the automated script encounters issues, follow the manual setup below. 2. **Install NVIDIA GPU drivers**. See [NVIDIA driver installation](https://www.nvidia.com/download/index.aspx). 3. **Install NVIDIA Container Toolkit**. Follow the [installation guide](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html). -## Quick Start +## Automated Quick Start + +This is an optimistic overview. Use the commands below for an in depth version. **Build the Docker image:** ```bash +cd docker/navigation ./build.sh ``` @@ -62,6 +65,31 @@ Note that the build will take over 10 minutes and build an image over 30GiB. ./start.sh --simulation ``` +## Manual build + +Go to the docker dir and clone the ROS navigation stack. + +```bash +cd docker/navigation +git clone -b jazzy git@github.com:dimensionalOS/ros-navigation-autonomy-stack.git +``` + +Download a [Unity environment model for the Mecanum wheel platform](https://drive.google.com/drive/folders/1G1JYkccvoSlxyySuTlPfvmrWoJUO8oSs?usp=sharing) and unzip the files to `unity_models`. + +Alternativelly, extract `office_building_1` from LFS: + +```bash +tar -xf ../../data/.lfs/office_building_1.tar.gz +mv office_building_1 unity_models +``` + +Then, go back to the root and build the docker image: + +```bash +cd ../.. +docker compose -f docker/navigation/docker-compose.yml build +``` + ## On Real Hardware ### Configure the WiFi From 8a247a49017fcda7eef60ab799b132145093957c Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Fri, 7 Nov 2025 08:58:37 +0200 Subject: [PATCH 34/38] mark directory as safe --- docker/navigation/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/navigation/Dockerfile b/docker/navigation/Dockerfile index c8d49d706e..ad973940cb 100644 --- a/docker/navigation/Dockerfile +++ b/docker/navigation/Dockerfile @@ -129,6 +129,8 @@ RUN echo 'SUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", M RUN echo '#!/bin/bash\n\ set -e\n\ \n\ +git config --global --add safe.directory /workspace/dimos\n\ +\n\ # Source ROS setup\n\ source /opt/ros/${ROS_DISTRO}/setup.bash\n\ source ${WORKSPACE}/install/setup.bash\n\ From 7a6d4939b0ca474acae2f44fbb25b56699743250 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Fri, 7 Nov 2025 09:05:21 +0200 Subject: [PATCH 35/38] install git-lfs --- docker/navigation/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/docker/navigation/Dockerfile b/docker/navigation/Dockerfile index ad973940cb..84315d7687 100644 --- a/docker/navigation/Dockerfile +++ b/docker/navigation/Dockerfile @@ -13,6 +13,7 @@ RUN apt-get update && apt-get install -y \ ros-jazzy-pcl-ros \ # Development tools git \ + git-lfs \ cmake \ build-essential \ python3-colcon-common-extensions \ From 66d41b0d6173c2e26428c946eea4277a784b3a89 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Fri, 7 Nov 2025 09:07:42 +0200 Subject: [PATCH 36/38] increase timeout --- dimos/protocol/rpc/spec.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dimos/protocol/rpc/spec.py b/dimos/protocol/rpc/spec.py index 283b84f1dd..ee9f99e16b 100644 --- a/dimos/protocol/rpc/spec.py +++ b/dimos/protocol/rpc/spec.py @@ -44,7 +44,7 @@ def call(self, name: str, arguments: Args, cb: Callable | None) -> Callable[[], # we expect to crash if we don't get a return value after 10 seconds # but callers can override this timeout for extra long functions def call_sync( - self, name: str, arguments: Args, rpc_timeout: float | None = 30.0 + self, name: str, arguments: Args, rpc_timeout: float | None = 120.0 ) -> tuple[Any, Callable[[], None]]: event = threading.Event() From b269556cfcda39b6adf6f757f4d7cf84c7882199 Mon Sep 17 00:00:00 2001 From: Paul Nechifor Date: Fri, 7 Nov 2025 09:49:50 +0200 Subject: [PATCH 37/38] activate automatically --- docker/navigation/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker/navigation/Dockerfile b/docker/navigation/Dockerfile index 84315d7687..aceb3f1726 100644 --- a/docker/navigation/Dockerfile +++ b/docker/navigation/Dockerfile @@ -111,6 +111,9 @@ COPY . ${DIMOS_PATH}/ # The container will always use its own dependencies, independent of the host RUN python3 -m venv /opt/dimos-venv +# Activate Python virtual environment in interactive shells +RUN echo "source /opt/dimos-venv/bin/activate" >> ~/.bashrc + # Install Python dependencies for dimos WORKDIR ${DIMOS_PATH} RUN /bin/bash -c "source /opt/dimos-venv/bin/activate && \ From c42252bc6c58317a53d385052f3926cad2233fec Mon Sep 17 00:00:00 2001 From: stash Date: Sat, 8 Nov 2025 17:44:27 -0800 Subject: [PATCH 38/38] Added Unitree g1 EDU lidar IP addresses to the .env --- docker/navigation/.env.hardware | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docker/navigation/.env.hardware b/docker/navigation/.env.hardware index 4b6b41a03f..2d8866b179 100644 --- a/docker/navigation/.env.hardware +++ b/docker/navigation/.env.hardware @@ -25,14 +25,17 @@ LIDAR_INTERFACE=eth0 # Processing computer IP address on the lidar subnet # Must be on the same subnet as the lidar (e.g., 192.168.1.5) +# LIDAR_COMPUTER_IP=192.168.123.5 # FOR UNITREE G1 EDU LIDAR_COMPUTER_IP=192.168.1.5 # Gateway IP address for the lidar subnet +# LIDAR_GATEWAY=192.168.123.1 # FOR UNITREE G1 EDU LIDAR_GATEWAY=192.168.1.1 # Full IP address of your Mid-360 lidar # This should match the IP configured on your lidar device # Common patterns: 192.168.1.1XX or 192.168.123.1XX +# LIDAR_IP=192.168.123.120 # FOR UNITREE G1 EDU LIDAR_IP=192.168.1.116 # ============================================