Skip to content

This textbook is in beta – content is actively being refined. Report issues or suggestions

9.2 Autonomous control features

Why it matters

Autonomous control is everywhere in modern mechatronic systems. From cruise control in cars to robotic vacuum cleaners, these systems can make decisions and take actions without constant human input. Understanding autonomy levels and safety systems is crucial for building reliable mechatronic devices.

When you design autonomous features, you need to balance independence with safety. The system should be smart enough to handle routine tasks on its own, but also wise enough to ask for help or shut down safely when something unexpected happens.

Concepts

Autonomy levels

Autonomy refers to how much a system can operate independently without human intervention. Different systems have different levels of autonomy, from simple automated responses to complex decision-making.

Here are the common levels of autonomy in mechatronic systems:

Level 0: No Autonomy (Manual Control)

  • Human controls everything directly

  • System only responds to immediate commands

  • Example: Remote-controlled robot arm

Level 1: Basic Assistance

  • System can perform simple, repetitive tasks

  • Human monitors and can override at any time

  • Example: Automatic door that opens when motion is detected

Level 2: Partial Autonomy

  • System can handle routine operations independently

  • Human supervises and intervenes when needed

  • Example: Robotic lawn mower that follows a programmed pattern

Level 3: Conditional Autonomy

  • System can make decisions based on sensor data

  • Human must be ready to take control when requested

  • Example: Self-parking car that handles the parking but asks driver to take over if something unexpected happens

Level 4: High Autonomy

  • System handles most situations independently

  • Human intervention only needed for complex edge cases

  • Example: Industrial robot that can adapt to different part sizes and orientations

Level 5: Full Autonomy

  • System operates completely independently

  • No human intervention required under normal conditions

  • Example: Fully autonomous spacecraft navigation systems

Let’s see how this works in code:

class AutonomousSystem:
    def __init__(self, autonomy_level):
        self.autonomy_level = autonomy_level
        self.human_override = False
        self.system_status = "operational"
        self.sensor_data = {}

    def process_sensor_input(self, sensor_type, value):
        """Process incoming sensor data"""
        self.sensor_data[sensor_type] = value
        print(f"Sensor update: {sensor_type} = {value}")

    def make_decision(self, situation):
        """Make decisions based on autonomy level"""
        if self.human_override:
            return "waiting_for_human"

        if self.autonomy_level == 0:
            return "request_human_input"

        elif self.autonomy_level == 1:
            # Basic assistance - only handle simple cases
            if situation == "routine_task":
                return "execute_automatically"
            else:
                return "request_human_input"

        elif self.autonomy_level >= 2:
            # Partial autonomy and above - handle more situations
            if situation in ["routine_task", "minor_obstacle", "pattern_deviation"]:
                return "execute_automatically"
            else:
                return "request_human_assistance"

        elif self.autonomy_level >= 4:
            # High autonomy - handle most situations
            if situation == "critical_failure":
                return "emergency_shutdown"
            else:
                return "execute_automatically"

    def demonstrate_autonomy_levels(self):
        """Show how different autonomy levels respond to situations"""
        situations = ["routine_task", "minor_obstacle", "unexpected_object", "critical_failure"]

        for level in range(0, 6):
            print(f"\n--- Autonomy Level {level} ---")
            self.autonomy_level = level

            for situation in situations:
                decision = self.make_decision(situation)
                print(f"Situation: {situation:20} → Decision: {decision}")

# Demonstrate different autonomy levels
system = AutonomousSystem(autonomy_level=2)
system.demonstrate_autonomy_levels()

Safety interlocks and fallbacks

Safety interlocks are automatic systems that prevent dangerous operations. They act like safety nets that catch problems before they cause harm.

Fallback systems are backup plans that kick in when the main system fails or encounters something it can’t handle.

Think of these as the “safety equipment” of autonomous systems:

class SafeAutonomousSystem:
    def __init__(self):
        self.emergency_stop_active = False
        self.safety_interlocks = {
            "temperature": {"max": 80, "current": 25},
            "pressure": {"max": 100, "current": 45},
            "speed": {"max": 50, "current": 0},
            "position": {"safe_zone": (0, 100), "current": 50}
        }
        self.fallback_actions = []

    def check_safety_interlocks(self):
        """Check all safety conditions before allowing operation"""
        violations = []

        # Temperature check
        temp = self.safety_interlocks["temperature"]
        if temp["current"] > temp["max"]:
            violations.append(f"Temperature too high: {temp['current']}°C > {temp['max']}°C")

        # Pressure check
        pressure = self.safety_interlocks["pressure"]
        if pressure["current"] > pressure["max"]:
            violations.append(f"Pressure too high: {pressure['current']} > {pressure['max']}")

        # Speed check
        speed = self.safety_interlocks["speed"]
        if speed["current"] > speed["max"]:
            violations.append(f"Speed too high: {speed['current']} > {speed['max']}")

        # Position check
        pos = self.safety_interlocks["position"]
        safe_min, safe_max = pos["safe_zone"]
        if not (safe_min <= pos["current"] <= safe_max):
            violations.append(f"Position unsafe: {pos['current']} not in range {safe_min}-{safe_max}")

        return violations

    def execute_emergency_stop(self, reason):
        """Immediate shutdown for safety"""
        self.emergency_stop_active = True
        print(f"🚨 EMERGENCY STOP: {reason}")
        print("- All motion stopped")
        print("- Power reduced to safe levels")
        print("- Human operator notified")

    def try_fallback_action(self, primary_action):
        """Attempt fallback when primary action fails"""
        print(f"Primary action '{primary_action}' failed. Trying fallbacks...")

        fallback_plans = {
            "move_forward": ["reduce_speed", "find_alternate_path", "stop_and_wait"],
            "pick_up_object": ["adjust_grip", "change_approach_angle", "request_human_help"],
            "navigate_to_target": ["recalculate_route", "use_backup_sensors", "return_to_safe_position"]
        }

        if primary_action in fallback_plans:
            for fallback in fallback_plans[primary_action]:
                print(f"  Trying fallback: {fallback}")
                if self.attempt_action(fallback):
                    print(f"  ✅ Fallback '{fallback}' succeeded!")
                    return True
                else:
                    print(f"  ❌ Fallback '{fallback}' failed.")

        print("  All fallbacks exhausted. Requesting human assistance.")
        return False

    def attempt_action(self, action):
        """Simulate attempting an action (simplified for demo)"""
        # Simulate success/failure for different actions
        success_rates = {
            "reduce_speed": 0.9,
            "find_alternate_path": 0.7,
            "stop_and_wait": 1.0,  # Always succeeds
            "adjust_grip": 0.6,
            "change_approach_angle": 0.8,
            "request_human_help": 1.0,  # Always succeeds
            "recalculate_route": 0.8,
            "use_backup_sensors": 0.7,
            "return_to_safe_position": 0.95
        }

        import random
        return random.random() < success_rates.get(action, 0.5)

    def safe_operation_cycle(self, requested_action):
        """Perform an action safely with all checks"""
        print(f"\n🔍 Safety check for action: {requested_action}")

        # Step 1: Check safety interlocks
        violations = self.check_safety_interlocks()
        if violations:
            print("❌ Safety violations detected:")
            for violation in violations:
                print(f"   - {violation}")
            self.execute_emergency_stop("Safety interlock violation")
            return False

        # Step 2: Check if emergency stop is active
        if self.emergency_stop_active:
            print("❌ Emergency stop is active. Cannot proceed.")
            return False

        # Step 3: Attempt the action
        print("✅ Safety checks passed. Attempting action...")
        if self.attempt_action(requested_action):
            print(f"✅ Action '{requested_action}' completed successfully!")
            return True
        else:
            print(f"❌ Action '{requested_action}' failed.")
            # Step 4: Try fallback actions
            return self.try_fallback_action(requested_action)

# Demonstrate safety system
safe_system = SafeAutonomousSystem()

# Simulate some operations
print("=== Safe Operation Demonstration ===")
safe_system.safe_operation_cycle("move_forward")

# Simulate a safety violation
print("\n=== Safety Violation Simulation ===")
safe_system.safety_interlocks["temperature"]["current"] = 95  # Exceed safe temperature
safe_system.safe_operation_cycle("pick_up_object")

# Reset and try again
print("\n=== After Safety Reset ===")
safe_system.safety_interlocks["temperature"]["current"] = 25  # Back to safe temperature
safe_system.emergency_stop_active = False  # Reset emergency stop
safe_system.safe_operation_cycle("navigate_to_target")

Guided example

Let’s build a comprehensive autonomous cleaning robot that demonstrates different autonomy levels and safety features:

import random
import time

class AutonomousCleaningRobot:
    def __init__(self, autonomy_level=2):
        # Robot state
        self.autonomy_level = autonomy_level
        self.position = [50, 50]  # x, y coordinates
        self.battery_level = 100
        self.dirt_collected = 0
        self.cleaning_pattern = "random"

        # Safety systems
        self.emergency_stop = False
        self.stuck_counter = 0
        self.max_stuck_attempts = 3

        # Autonomous features
        self.cleaning_mode = "auto"
        self.home_position = [0, 0]
        self.cleaning_schedule = {"enabled": False, "time": "09:00"}

        # Environmental awareness
        self.room_map = self.generate_room_map()
        self.obstacles = [(30, 40), (70, 20), (10, 80)]  # Known obstacles

    def generate_room_map(self):
        """Create a simple room map (100x100 grid)"""
        return {
            "width": 100,
            "height": 100,
            "cleaned_areas": set(),
            "dirty_areas": {(x, y) for x in range(20, 80) for y in range(20, 80) if random.random() < 0.3}
        }

    def detect_obstacle(self):
        """Simulate obstacle detection"""
        current_pos = tuple(self.position)
        return current_pos in self.obstacles or random.random() < 0.1  # 10% chance of random obstacle

    def autonomous_decision_making(self):
        """Make decisions based on autonomy level"""
        print(f"\n🤖 Robot thinking (Autonomy Level {self.autonomy_level})...")

        # Level 0: No autonomy - wait for commands
        if self.autonomy_level == 0:
            print("   Waiting for human command...")
            return "wait_for_command"

        # Check critical conditions first (all levels)
        if self.battery_level < 20:
            if self.autonomy_level >= 2:
                print("   Low battery detected. Returning to charging station.")
                return "return_to_charge"
            else:
                print("   Low battery. Requesting human assistance.")
                return "request_help"

        # Level 1: Basic assistance
        if self.autonomy_level == 1:
            if self.detect_obstacle():
                print("   Obstacle detected. Stopping and requesting help.")
                return "request_help"
            else:
                print("   Continuing basic cleaning pattern.")
                return "clean_forward"

        # Level 2+: Partial autonomy and above
        if self.autonomy_level >= 2:
            if self.detect_obstacle():
                if self.stuck_counter < self.max_stuck_attempts:
                    print("   Obstacle detected. Trying to navigate around it.")
                    return "navigate_around_obstacle"
                else:
                    print("   Stuck too many times. Requesting human help.")
                    return "request_help"

            # Check if cleaning is complete
            if len(self.room_map["dirty_areas"]) == 0:
                print("   Room appears clean. Returning home.")
                return "return_home"

            # Continue autonomous cleaning
            print("   Continuing autonomous cleaning pattern.")
            return "autonomous_clean"

        # Level 4+: High autonomy
        if self.autonomy_level >= 4:
            # Advanced features like scheduling
            if self.cleaning_schedule["enabled"]:
                current_time = "09:00"  # Simplified time check
                if current_time == self.cleaning_schedule["time"]:
                    print("   Scheduled cleaning time. Starting automatic session.")
                    return "start_scheduled_clean"

        return "autonomous_clean"

    def execute_action(self, action):
        """Execute the decided action with safety checks"""
        print(f"   Executing: {action}")

        # Safety interlock: Emergency stop check
        if self.emergency_stop:
            print("   ❌ Emergency stop active. All actions halted.")
            return False

        # Safety interlock: Battery check
        if self.battery_level < 5:
            print("   ❌ Critical battery level. Emergency shutdown.")
            self.emergency_stop = True
            return False

        # Execute specific actions
        if action == "clean_forward":
            self.move_and_clean([self.position[0] + 5, self.position[1]])

        elif action == "navigate_around_obstacle":
            # Try different directions
            directions = [[0, 5], [5, 0], [0, -5], [-5, 0]]
            for direction in directions:
                new_pos = [self.position[0] + direction[0], self.position[1] + direction[1]]
                if not self.would_hit_obstacle(new_pos):
                    self.move_and_clean(new_pos)
                    self.stuck_counter = 0  # Reset stuck counter
                    return True

            self.stuck_counter += 1
            print(f"   Still stuck (attempt {self.stuck_counter})")
            return False

        elif action == "autonomous_clean":
            # Smart cleaning pattern
            target = self.find_nearest_dirty_spot()
            if target:
                self.move_and_clean(target)
            else:
                print("   No more dirty spots found.")

        elif action == "return_to_charge":
            print("   Navigating to charging station...")
            self.position = [0, 0]  # Simplified - instant return
            self.battery_level = 100
            print("   ✅ Charging complete!")

        elif action == "return_home":
            print("   Returning to home position...")
            self.position = self.home_position.copy()

        elif action == "request_help":
            print("   📱 Notifying human operator for assistance...")
            print("   Robot status sent to mobile app.")

        elif action == "wait_for_command":
            print("   Idle - waiting for manual control...")

        # Update battery (cleaning uses energy)
        if action in ["clean_forward", "navigate_around_obstacle", "autonomous_clean"]:
            self.battery_level -= random.randint(1, 3)

        return True

    def move_and_clean(self, new_position):
        """Move to new position and clean if there's dirt"""
        self.position = new_position
        pos_tuple = tuple(new_position)

        if pos_tuple in self.room_map["dirty_areas"]:
            self.room_map["dirty_areas"].remove(pos_tuple)
            self.room_map["cleaned_areas"].add(pos_tuple)
            self.dirt_collected += 1
            print(f"   🧹 Cleaned dirt at {new_position}. Total dirt collected: {self.dirt_collected}")

        print(f"   Moved to position {new_position}")

    def find_nearest_dirty_spot(self):
        """Find the closest dirty area to clean"""
        if not self.room_map["dirty_areas"]:
            return None

        min_distance = float('inf')
        nearest_spot = None

        for dirty_spot in self.room_map["dirty_areas"]:
            distance = abs(dirty_spot[0] - self.position[0]) + abs(dirty_spot[1] - self.position[1])
            if distance < min_distance:
                min_distance = distance
                nearest_spot = list(dirty_spot)

        return nearest_spot

    def would_hit_obstacle(self, position):
        """Check if a position would hit an obstacle"""
        return tuple(position) in self.obstacles

    def run_cleaning_cycle(self, steps=5):
        """Run an autonomous cleaning cycle"""
        print(f"🏠 Starting cleaning cycle (Autonomy Level {self.autonomy_level})")
        print(f"   Initial status: Battery {self.battery_level}%, Position {self.position}")
        print(f"   Dirty areas remaining: {len(self.room_map['dirty_areas'])}")

        for step in range(steps):
            print(f"\n--- Step {step + 1} ---")

            # Make autonomous decision
            action = self.autonomous_decision_making()

            # Execute with safety checks
            success = self.execute_action(action)

            if not success and action == "request_help":
                print("   Human intervention required. Pausing autonomous operation.")
                break

            if self.emergency_stop:
                print("   Emergency stop activated. Cleaning cycle halted.")
                break

            # Show current status
            print(f"   Status: Battery {self.battery_level}%, Position {self.position}, Dirt collected: {self.dirt_collected}")

            # Brief pause for readability
            time.sleep(0.5)

        print(f"\n🏁 Cleaning cycle complete!")
        print(f"   Final status: Battery {self.battery_level}%, Dirt collected: {self.dirt_collected}")
        print(f"   Dirty areas remaining: {len(self.room_map['dirty_areas'])}")

# Demonstrate different autonomy levels
print("=== Autonomy Level Comparison ===")

for level in [1, 2, 4]:
    print(f"\n{'='*50}")
    print(f"Testing Autonomy Level {level}")
    print(f"{'='*50}")

    robot = AutonomousCleaningRobot(autonomy_level=level)
    robot.run_cleaning_cycle(steps=3)

Try it

Exercise 1: Design autonomy levels for different systems

Consider how autonomy levels might work for different mechatronic systems:

def design_autonomy_system(system_type):
    """Design appropriate autonomy levels for different systems"""

    autonomy_designs = {
        "smart_thermostat": {
            "level_1": "Respond to manual temperature changes",
            "level_2": "Learn daily patterns and adjust automatically", 
            "level_3": "Optimize for energy efficiency and comfort",
            "level_4": "Coordinate with other smart home devices",
            "safety_features": ["Temperature limits", "Frost protection", "Equipment monitoring"]
        },

        "automated_greenhouse": {
            "level_1": "Monitor sensors and alert on issues",
            "level_2": "Automatic watering based on soil moisture",
            "level_3": "Climate control with weather forecast integration", 
            "level_4": "Full crop management with growth optimization",
            "safety_features": ["Water flow limits", "Temperature boundaries", "Chemical safety locks"]
        },

        "delivery_drone": {
            "level_1": "Remote pilot control with automated stability",
            "level_2": "Waypoint navigation with obstacle avoidance",
            "level_3": "Route planning with weather adaptation",
            "level_4": "Fleet coordination and dynamic rerouting", 
            "safety_features": ["Geofencing", "Emergency landing", "Battery monitoring", "Collision avoidance"]
        }
    }

    if system_type in autonomy_designs:
        design = autonomy_designs[system_type]
        print(f"\n🎯 Autonomy Design for {system_type.replace('_', ' ').title()}:")
        print("   Autonomy Levels:")
        for level in range(1, 5):
            key = f"level_{level}"
            if key in design:
                print(f"   Level {level}: {design[key]}")

        print("   Safety Features:")
        for safety_feature in design["safety_features"]:
            print(f"   • {safety_feature}")
    else:
        print(f"Design not available for {system_type}")

# Try different systems
design_autonomy_system("smart_thermostat")
design_autonomy_system("automated_greenhouse") 
design_autonomy_system("delivery_drone")

Exercise 2: Build a safety interlock system

Create a comprehensive safety system for an industrial robot:

class IndustrialRobotSafety:
    def __init__(self):
        self.safety_zones = {
            "red_zone": {"description": "No humans allowed during operation", "violation_response": "immediate_stop"},
            "yellow_zone": {"description": "Reduced speed when humans present", "violation_response": "slow_operation"},
            "green_zone": {"description": "Safe for human interaction", "violation_response": "normal_operation"}
        }

        self.safety_sensors = {
            "light_curtain": {"status": "clear", "critical": True},
            "pressure_mat": {"status": "clear", "critical": True}, 
            "motion_detector": {"status": "clear", "critical": False},
            "emergency_button": {"status": "normal", "critical": True}
        }

        self.operational_limits = {
            "max_speed": 100,  # cm/second
            "max_force": 50,   # Newtons
            "max_reach": 200,  # cm from base
            "temperature_limit": 70  # Celsius
        }

        self.current_state = {
            "speed": 0,
            "force": 0, 
            "position": 0,
            "temperature": 25
        }

    def check_safety_zones(self, detected_humans):
        """Check if humans are in safe zones"""
        violations = []

        for location, zone_type in detected_humans.items():
            zone_info = self.safety_zones.get(zone_type, {})

            if zone_type == "red_zone":
                violations.append(f"Human detected in red zone at {location} - CRITICAL")
            elif zone_type == "yellow_zone":
                violations.append(f"Human detected in yellow zone at {location} - CAUTION")

        return violations

    def check_sensor_status(self):
        """Check all safety sensor status"""
        violations = []

        for sensor, info in self.safety_sensors.items():
            if info["status"] != "clear" and info["status"] != "normal":
                severity = "CRITICAL" if info["critical"] else "WARNING"
                violations.append(f"{sensor}: {info['status']} - {severity}")

        return violations

    def check_operational_limits(self):
        """Check if robot is operating within safe limits"""
        violations = []

        if self.current_state["speed"] > self.operational_limits["max_speed"]:
            violations.append(f"Speed exceeded: {self.current_state['speed']} > {self.operational_limits['max_speed']}")

        if self.current_state["force"] > self.operational_limits["max_force"]:
            violations.append(f"Force exceeded: {self.current_state['force']} > {self.operational_limits['max_force']}")

        if self.current_state["position"] > self.operational_limits["max_reach"]:
            violations.append(f"Reach exceeded: {self.current_state['position']} > {self.operational_limits['max_reach']}")

        if self.current_state["temperature"] > self.operational_limits["temperature_limit"]:
            violations.append(f"Temperature exceeded: {self.current_state['temperature']} > {self.operational_limits['temperature_limit']}")

        return violations

    def comprehensive_safety_check(self, detected_humans=None):
        """Perform complete safety assessment"""
        if detected_humans is None:
            detected_humans = {}

        print("🔒 Comprehensive Safety Check")
        print("-" * 40)

        all_violations = []

        # Check each safety system
        zone_violations = self.check_safety_zones(detected_humans)
        sensor_violations = self.check_sensor_status()
        limit_violations = self.check_operational_limits()

        all_violations.extend(zone_violations)
        all_violations.extend(sensor_violations) 
        all_violations.extend(limit_violations)

        # Report results
        if not all_violations:
            print("✅ All safety checks passed - Operation authorized")
            return "safe_to_operate"
        else:
            print("❌ Safety violations detected:")
            critical_violations = [v for v in all_violations if "CRITICAL" in v]
            warning_violations = [v for v in all_violations if "WARNING" in v or "CAUTION" in v]

            for violation in critical_violations:
                print(f"   🚨 {violation}")
            for violation in warning_violations:
                print(f"   ⚠️  {violation}")

            if critical_violations:
                return "emergency_stop"
            else:
                return "restricted_operation"

# Test the safety system
safety_system = IndustrialRobotSafety()

# Test 1: Normal operation
print("=== Test 1: Normal Operation ===")
result = safety_system.comprehensive_safety_check()
print(f"Result: {result}\n")

# Test 2: Human in yellow zone
print("=== Test 2: Human in Caution Zone ===")
result = safety_system.comprehensive_safety_check({"area_B": "yellow_zone"})
print(f"Result: {result}\n")

# Test 3: Critical violations
print("=== Test 3: Critical Safety Violation ===")
safety_system.safety_sensors["emergency_button"]["status"] = "pressed"
safety_system.current_state["speed"] = 150  # Exceed speed limit
result = safety_system.comprehensive_safety_check({"area_A": "red_zone"})
print(f"Result: {result}")

Recap

In this section, you learned about autonomous control features in mechatronic systems:

Key concepts:

  • Autonomy levels: From Level 0 (manual control) to Level 5 (full autonomy), each level defines how much the system can operate independently.

  • Safety interlocks: Automatic safety systems that prevent dangerous operations by checking conditions before allowing actions.

  • Fallback systems: Backup plans that activate when primary systems fail, ensuring graceful degradation rather than complete failure.

  • Decision-making frameworks: Structured approaches for autonomous systems to evaluate situations and choose appropriate actions.

Why this matters for mechatronics:

  • Autonomous features reduce the need for constant human supervision

  • Safety systems prevent accidents and protect both equipment and people

  • Fallback mechanisms ensure systems remain operational even when components fail

  • Understanding autonomy levels helps you design systems appropriate for their intended use

Design principles:

  • Start with lower autonomy levels and gradually increase capability

  • Always include multiple layers of safety protection

  • Plan for failure modes and provide graceful degradation

  • Keep humans in the loop for critical decisions

  • Test autonomous features extensively before deployment

In the next section, we’ll explore algorithmic patterns that implement these autonomous control features.