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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions demos/turtlebot3_integration/config/medkit_params_debounce.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# ros2_medkit gateway configuration for TurtleBot3 demo
# ARTICLE 3 - DEBOUNCE VERSION
# Differences from default:
# confirmation_threshold: -3 (was 0) — requires 3 sustained FAILED events
# healing_enabled: true (was false) — auto-heal after PASSED events
#
# Node runs under /diagnostics namespace, so we need to match that here
diagnostics:
ros2_medkit_gateway:
ros__parameters:
server:
# Bind to all interfaces for Docker networking
host: "0.0.0.0"
port: 8080

refresh_interval_ms: 10000 # 10 seconds (default), reduces log spam

cors:
allowed_origins: ["*"]
allowed_methods: ["GET", "PUT", "POST", "DELETE", "OPTIONS"]
allowed_headers: ["Content-Type", "Accept"]
allow_credentials: false
max_age_seconds: 86400

max_parallel_topic_samples: 10

# Discovery configuration
discovery_mode: "hybrid" # runtime_only, manifest_only, or hybrid
manifest_path: "" # Will be set via launch argument
manifest_strict_validation: true

discovery:
runtime:
create_synthetic_components: false # Manifest defines components

# Fault Manager configuration (runs in root namespace)
fault_manager:
ros__parameters:
# Storage configuration
storage_type: "sqlite"
database_path: "/var/lib/ros2_medkit/faults.db"

# === DEBOUNCE CONFIGURATION (Article 3) ===
confirmation_threshold: -3 # Need 3 sustained FAILED events to confirm
healing_enabled: true # Auto-heal when problem resolves
healing_threshold: 3 # Need 3 PASSED events to heal
auto_confirm_after_sec: 0.0 # Disabled

# Snapshot configuration (freeze frames)
snapshots:
enabled: true
background_capture: true # Non-blocking capture
timeout_sec: 2.0
max_message_size: 131072 # 128KB max per message

# Topics to capture for all faults
default_topics:
- /odom
- /amcl_pose
- /scan
- /tf
- /navigate_to_pose/_action/status

# Rosbag recording configuration
rosbag:
enabled: true
duration_sec: 10.0 # Record 10 seconds before fault confirmation
duration_after_sec: 2.0 # Record 2 seconds after confirmation
lazy_start: false # Always recording (ring buffer)
format: "mcap" # MCAP format (recommended for cross-platform)
storage_path: "/var/lib/ros2_medkit/rosbags"
max_bag_size_mb: 100 # Max size per rosbag file
max_total_storage_mb: 1000 # 1GB total storage limit
auto_cleanup: true # Cleanup rosbags on fault clear

# Topics to record (use 'config' or 'all')
topics: "config" # Use include/exclude lists below
include_topics:
- /odom
- /amcl_pose
- /scan
- /cmd_vel
- /tf
- /tf_static
- /navigate_to_pose/_action/status
- /navigate_to_pose/_action/feedback
- /local_costmap/costmap
- /global_costmap/costmap
- /plan
- /diagnostics
exclude_topics:
- /rosout
- /parameter_events
21 changes: 21 additions & 0 deletions demos/turtlebot3_integration/docker-compose.debounce.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Docker Compose override for debounce mode
#
# Usage:
# STORM (no debounce, default config):
# docker compose --profile cpu up -d
#
# DEBOUNCE (with filtering):
# docker compose --profile cpu -f docker-compose.yml -f docker-compose.debounce.yml up -d
#
# The override mounts the debounce config over the default one inside the container.
# colcon build --symlink-install means the installed config points to the source,
# so mounting over the source path works.

services:
turtlebot3-demo:
volumes:
- ./config/medkit_params_debounce.yaml:/root/demo_ws/src/turtlebot3_medkit_demo/config/medkit_params.yaml:ro

turtlebot3-demo-nvidia:
volumes:
- ./config/medkit_params_debounce.yaml:/root/demo_ws/src/turtlebot3_medkit_demo/config/medkit_params.yaml:ro
111 changes: 111 additions & 0 deletions demos/turtlebot3_integration/run-demo-debounce.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/bin/bash
# TurtleBot3 + ros2_medkit Demo Runner - DEBOUNCE MODE
#
# Same as run-demo.sh but uses debounce config:
# confirmation_threshold: -3 (requires sustained failure)
# healing_enabled: true (auto-heal on recovery)
#
# Compare with:
# ./run-demo.sh → STORM (no debounce, threshold 0)
# ./run-demo-debounce.sh → CALM (debounce, threshold -3)

set -eu

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

echo "🛡️ TurtleBot3 + ros2_medkit — DEBOUNCE MODE"
echo "=============================================="
echo " confirmation_threshold: -3 (need 3 sustained FAILED events)"
echo " healing_enabled: true (auto-heal after 3 PASSED events)"
echo ""

# Set TurtleBot3 environment variables
export TURTLEBOT3_MODEL=${TURTLEBOT3_MODEL:-burger}
export GAZEBO_MODEL_PATH=${GAZEBO_MODEL_PATH:-}:/opt/ros/jazzy/share/turtlebot3_gazebo/models

# Check for Docker
if ! command -v docker &> /dev/null; then
echo "Error: Docker is not installed"
exit 1
fi

# Setup X11 forwarding for GUI (Gazebo)
echo "Setting up X11 forwarding..."
xhost +local:docker 2>/dev/null || {
echo " Warning: xhost failed. GUI may not work."
}

# Cleanup function
cleanup() {
echo ""
echo "Cleaning up..."
xhost -local:docker 2>/dev/null || true
echo "Done!"
}
trap cleanup EXIT

# Parse arguments
HEADLESS_MODE="false"
DETACH_MODE="true"
PROFILE="cpu"

while [[ $# -gt 0 ]]; do
case "$1" in
--nvidia) PROFILE="nvidia" ;;
--headless) HEADLESS_MODE="true" ;;
--attached) DETACH_MODE="false" ;;
*) echo "Unknown option: $1"; exit 1 ;;
esac
shift
done

export HEADLESS=$HEADLESS_MODE

DETACH_FLAG=""
if [[ "$DETACH_MODE" == "true" ]]; then
DETACH_FLAG="-d"
fi

echo "Building and starting demo (debounce mode)..."
echo ""
echo "🌐 REST API: http://localhost:8080/api/v1/"
echo "🌐 Web UI: http://localhost:3000/"
echo ""

# Use docker-compose override to mount debounce config
if docker compose version &> /dev/null; then
docker compose --profile "$PROFILE" \
-f docker-compose.yml \
-f docker-compose.debounce.yml \
build && \
docker compose --profile "$PROFILE" \
-f docker-compose.yml \
-f docker-compose.debounce.yml \
up ${DETACH_FLAG}
else
docker-compose --profile "$PROFILE" \
-f docker-compose.yml \
-f docker-compose.debounce.yml \
build && \
docker-compose --profile "$PROFILE" \
-f docker-compose.yml \
-f docker-compose.debounce.yml \
up ${DETACH_FLAG}
fi

if [[ "$DETACH_MODE" == "true" ]]; then
if [[ "$PROFILE" == "nvidia" ]]; then
CONTAINER="turtlebot3_medkit_demo_nvidia"
else
CONTAINER="turtlebot3_medkit_demo"
fi
echo ""
echo "✅ Demo started in DEBOUNCE mode!"
echo ""
echo "Fire fault storm to see debounce in action:"
echo " docker exec $CONTAINER bash -c \\"
echo " 'source /opt/ros/jazzy/setup.bash && source /root/demo_ws/install/setup.bash && python3 /root/demo_ws/src/turtlebot3_medkit_demo/scripts/fault_storm.py'"
echo ""
echo "🛑 To stop: ./stop-demo.sh"
fi
Loading