mirror of
https://github.com/AtsushiSakai/PythonRobotics.git
synced 2026-01-12 23:58:04 -05:00
* add state machine state_machine test state_machine_update * add state machine test/doc * state machine update * state machine generate_plantuml() can show diagram by using https://www.plantuml.com/plantuml/
112 lines
3.2 KiB
Python
112 lines
3.2 KiB
Python
"""
|
|
A case study of robot behavior using state machine
|
|
|
|
author: Wang Zheng (@Aglargil)
|
|
"""
|
|
|
|
from state_machine import StateMachine
|
|
|
|
|
|
class Robot:
|
|
def __init__(self):
|
|
self.battery = 100
|
|
self.task_progress = 0
|
|
|
|
# Initialize state machine
|
|
self.machine = StateMachine("robot_sm", self)
|
|
|
|
# Add state transition rules
|
|
self.machine.add_transition(
|
|
src_state="patrolling",
|
|
event="detect_task",
|
|
dst_state="executing_task",
|
|
guard=None,
|
|
action=None,
|
|
)
|
|
|
|
self.machine.add_transition(
|
|
src_state="executing_task",
|
|
event="task_complete",
|
|
dst_state="patrolling",
|
|
guard=None,
|
|
action="reset_task",
|
|
)
|
|
|
|
self.machine.add_transition(
|
|
src_state="executing_task",
|
|
event="low_battery",
|
|
dst_state="returning_to_base",
|
|
guard="is_battery_low",
|
|
)
|
|
|
|
self.machine.add_transition(
|
|
src_state="returning_to_base",
|
|
event="reach_base",
|
|
dst_state="charging",
|
|
guard=None,
|
|
action=None,
|
|
)
|
|
|
|
self.machine.add_transition(
|
|
src_state="charging",
|
|
event="charge_complete",
|
|
dst_state="patrolling",
|
|
guard=None,
|
|
action="battery_full",
|
|
)
|
|
|
|
# Set initial state
|
|
self.machine.set_current_state("patrolling")
|
|
|
|
def is_battery_low(self):
|
|
"""Battery level check condition"""
|
|
return self.battery < 30
|
|
|
|
def reset_task(self):
|
|
"""Reset task progress"""
|
|
self.task_progress = 0
|
|
print("[Action] Task progress has been reset")
|
|
|
|
# Modify state entry callback naming convention (add state_ prefix)
|
|
def on_enter_executing_task(self):
|
|
print("\n------ Start Executing Task ------")
|
|
print(f"Current battery: {self.battery}%")
|
|
while self.machine.get_current_state().name == "executing_task":
|
|
self.task_progress += 10
|
|
self.battery -= 25
|
|
print(
|
|
f"Task progress: {self.task_progress}%, Remaining battery: {self.battery}%"
|
|
)
|
|
|
|
if self.task_progress >= 100:
|
|
self.machine.process("task_complete")
|
|
break
|
|
elif self.is_battery_low():
|
|
self.machine.process("low_battery")
|
|
break
|
|
|
|
def on_enter_returning_to_base(self):
|
|
print("\nLow battery, returning to charging station...")
|
|
self.machine.process("reach_base")
|
|
|
|
def on_enter_charging(self):
|
|
print("\n------ Charging ------")
|
|
self.battery = 100
|
|
print("Charging complete!")
|
|
self.machine.process("charge_complete")
|
|
|
|
|
|
# Keep the test section structure the same, only modify the trigger method
|
|
if __name__ == "__main__":
|
|
robot = Robot()
|
|
print(robot.machine.generate_plantuml())
|
|
|
|
print(f"Initial state: {robot.machine.get_current_state().name}")
|
|
print("------------")
|
|
|
|
# Trigger task detection event
|
|
robot.machine.process("detect_task")
|
|
|
|
print("\n------------")
|
|
print(f"Final state: {robot.machine.get_current_state().name}")
|