324 lines
9.7 KiB
Markdown
324 lines
9.7 KiB
Markdown
# State Inheritance trong RobotStateMachine
|
|
|
|
## Tóm t?t
|
|
|
|
? **SUB-STATES T? ??NG K? TH?A CÁC EVENTS T? PARENT STATE** trong Hierarchical State Machine
|
|
|
|
## Ví d? chi ti?t
|
|
|
|
### Hierarchy trong RobotStateMachine
|
|
|
|
```
|
|
System (Root)
|
|
??? Initializing
|
|
??? Standby
|
|
??? Shutting_Down
|
|
|
|
Auto (Root)
|
|
??? Idle
|
|
??? Executing
|
|
? ??? Moving
|
|
? ? ??? Navigation
|
|
? ? ??? Avoidance
|
|
? ? ??? Approach
|
|
? ? ??? Tracking
|
|
? ? ??? Repositioning
|
|
? ??? ACT
|
|
? ??? Docking
|
|
? ??? Docked
|
|
? ??? Charging
|
|
? ??? Undocking
|
|
? ??? Loading
|
|
? ??? Unloading
|
|
? ??? TechAction
|
|
??? Paused
|
|
??? Canceling
|
|
??? Recovering
|
|
??? Remote_Override
|
|
```
|
|
|
|
## 1. Inheritance c? b?n
|
|
|
|
### Ví d? 1: Idle k? th?a t? Auto
|
|
|
|
```csharp
|
|
// Auto (parent) ??nh ngh?a các events
|
|
builder.In(RobotStateType.Auto)
|
|
.On(RobotEventType.EnterManual).Goto(RobotStateType.Manual)
|
|
.On(RobotEventType.EnterService).Goto(RobotStateType.Service)
|
|
.On(RobotEventType.EnterStop).Goto(RobotStateType.Stop)
|
|
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
|
|
|
|
// Idle (sub-state) ch? ??nh ngh?a event riêng c?a nó
|
|
builder.In(RobotStateType.Idle)
|
|
.On(RobotEventType.StartExecution).Goto(RobotStateType.Executing);
|
|
```
|
|
|
|
**K?t qu? khi ? state Idle:**
|
|
|
|
```csharp
|
|
var stateMachine = serviceProvider.GetService<RobotStateMachine>();
|
|
stateMachine.Initialize();
|
|
|
|
// Gi? s? ?ang ? Idle
|
|
await stateMachine.FireAsync(RobotEventType.EnterAuto);
|
|
|
|
// Query transitions
|
|
var transitions = stateMachine.GetPossibleTransitions(RobotStateType.Idle);
|
|
|
|
// K?t qu?:
|
|
// 1. StartExecution -> Executing (??nh ngh?a riêng)
|
|
// 2. EnterManual -> Manual (k? th?a t? Auto)
|
|
// 3. EnterService -> Service (k? th?a t? Auto)
|
|
// 4. EnterStop -> Stop (k? th?a t? Auto)
|
|
// 5. EnterFault -> Fault (k? th?a t? Auto)
|
|
|
|
Console.WriteLine($"Idle has {transitions.Count} possible transitions");
|
|
foreach (var t in transitions)
|
|
{
|
|
Console.WriteLine($" - {t.Event} -> {t.ToState}");
|
|
}
|
|
```
|
|
|
|
**Output:**
|
|
```
|
|
Idle has 5 possible transitions
|
|
- StartExecution -> Executing
|
|
- EnterManual -> Manual
|
|
- EnterService -> Service
|
|
- EnterStop -> Stop
|
|
- EnterFault -> Fault
|
|
```
|
|
|
|
## 2. Multi-level Inheritance
|
|
|
|
### Ví d? 2: Navigation k? th?a t? Moving và Executing
|
|
|
|
```csharp
|
|
// Executing (c?p 1) ??nh ngh?a
|
|
builder.In(RobotStateType.Executing)
|
|
.On(RobotEventType.PauseExecution).Goto(RobotStateType.Paused)
|
|
.On(RobotEventType.CancelExecution).Goto(RobotStateType.Canceling);
|
|
|
|
// Moving (c?p 2 - sub c?a Executing) ??nh ngh?a
|
|
builder.In(RobotStateType.Moving)
|
|
.On(RobotEventType.StartACT).Goto(RobotStateType.ACT);
|
|
|
|
// Navigation (c?p 3 - sub c?a Moving) ??nh ngh?a
|
|
builder.In(RobotStateType.Navigation)
|
|
.On(RobotEventType.StartAvoidance).Goto(RobotStateType.Avoidance);
|
|
```
|
|
|
|
**K?t qu? khi ? Navigation:**
|
|
|
|
```csharp
|
|
var transitions = stateMachine.GetPossibleTransitions(RobotStateType.Navigation);
|
|
|
|
// K?t qu? (k? th?a 3 c?p):
|
|
// 1. StartAvoidance -> Avoidance (??nh ngh?a ? Navigation)
|
|
// 2. StartACT -> ACT (k? th?a t? Moving)
|
|
// 3. PauseExecution -> Paused (k? th?a t? Executing)
|
|
// 4. CancelExecution -> Canceling (k? th?a t? Executing)
|
|
// 5. EnterManual -> Manual (k? th?a t? Auto - parent c?a Executing)
|
|
// 6. EnterService -> Service (k? th?a t? Auto)
|
|
// 7. EnterStop -> Stop (k? th?a t? Auto)
|
|
// 8. EnterFault -> Fault (k? th?a t? Auto)
|
|
```
|
|
|
|
## 3. S? d?ng các method m?i
|
|
|
|
### Query Hierarchy
|
|
|
|
```csharp
|
|
// L?y parent state
|
|
var parent = stateMachine.GetParentState(RobotStateType.Navigation);
|
|
Console.WriteLine($"Parent of Navigation: {parent}"); // Moving
|
|
|
|
// L?y toàn b? hierarchy chain
|
|
var chain = stateMachine.GetStateHierarchyChain(RobotStateType.Navigation);
|
|
Console.WriteLine("Hierarchy chain:");
|
|
foreach (var state in chain)
|
|
{
|
|
Console.WriteLine($" - {state}");
|
|
}
|
|
// Output:
|
|
// - Navigation
|
|
// - Moving
|
|
// - Executing
|
|
// - Auto
|
|
|
|
// Ki?m tra sub-state relationship
|
|
bool isSubState = stateMachine.IsSubStateOf(
|
|
RobotStateType.Navigation,
|
|
RobotStateType.Auto
|
|
);
|
|
Console.WriteLine($"Navigation is sub-state of Auto: {isSubState}"); // true
|
|
|
|
isSubState = stateMachine.IsSubStateOf(
|
|
RobotStateType.Navigation,
|
|
RobotStateType.Manual
|
|
);
|
|
Console.WriteLine($"Navigation is sub-state of Manual: {isSubState}"); // false
|
|
```
|
|
|
|
### Check transitions v?i inheritance
|
|
|
|
```csharp
|
|
// Khi ? Navigation state
|
|
await stateMachine.FireAsync(RobotEventType.EnterAuto);
|
|
await stateMachine.FireAsync(RobotEventType.StartExecution);
|
|
|
|
// Bây gi? ?ang ? Navigation (sub-state c?a Moving, Executing, Auto)
|
|
|
|
// Ki?m tra có th? fire các events k? th?a
|
|
Console.WriteLine($"Can fire StartAvoidance: {stateMachine.CanFire(RobotEventType.StartAvoidance)}"); // true (riêng)
|
|
Console.WriteLine($"Can fire StartACT: {stateMachine.CanFire(RobotEventType.StartACT)}"); // true (t? Moving)
|
|
Console.WriteLine($"Can fire PauseExecution: {stateMachine.CanFire(RobotEventType.PauseExecution)}"); // true (t? Executing)
|
|
Console.WriteLine($"Can fire EnterManual: {stateMachine.CanFire(RobotEventType.EnterManual)}"); // true (t? Auto)
|
|
|
|
// Ki?m tra có th? chuy?n sang các states
|
|
Console.WriteLine($"Can go to Avoidance: {stateMachine.CanTransitionTo(RobotStateType.Avoidance)}"); // true
|
|
Console.WriteLine($"Can go to ACT: {stateMachine.CanTransitionTo(RobotStateType.ACT)}"); // true
|
|
Console.WriteLine($"Can go to Paused: {stateMachine.CanTransitionTo(RobotStateType.Paused)}"); // true
|
|
Console.WriteLine($"Can go to Manual: {stateMachine.CanTransitionTo(RobotStateType.Manual)}"); // true
|
|
|
|
// L?y event ?? chuy?n sang state ?ích
|
|
var evt = stateMachine.GetEventForTransition(RobotStateType.Manual);
|
|
Console.WriteLine($"Event to go to Manual: {evt}"); // EnterManual
|
|
```
|
|
|
|
## 4. Practical Use Cases
|
|
|
|
### Use Case 1: Emergency Stop t? b?t k? sub-state nào
|
|
|
|
```csharp
|
|
public class SafetyController
|
|
{
|
|
private readonly RobotStateMachine _stateMachine;
|
|
|
|
public async Task EmergencyStopAsync()
|
|
{
|
|
// Có th? g?i t? B?T K? sub-state nào c?a Auto
|
|
// vì EnterStop ???c ??nh ngh?a ? Auto (parent)
|
|
|
|
if (_stateMachine.CanFire(RobotEventType.EnterStop))
|
|
{
|
|
await _stateMachine.FireAsync(RobotEventType.EnterStop);
|
|
Console.WriteLine("Emergency stop activated!");
|
|
}
|
|
else
|
|
{
|
|
Console.WriteLine("Cannot emergency stop from current state");
|
|
}
|
|
}
|
|
}
|
|
|
|
// G?i t? Navigation (deep sub-state)
|
|
// ? V?n ho?t ??ng vì Navigation k? th?a EnterStop t? Auto
|
|
```
|
|
|
|
### Use Case 2: Fault Handling t? m?i n?i
|
|
|
|
```csharp
|
|
public class ErrorHandler
|
|
{
|
|
private readonly RobotStateMachine _stateMachine;
|
|
|
|
public async Task HandleErrorAsync(Exception error)
|
|
{
|
|
// EnterFault ???c ??nh ngh?a ? Auto
|
|
// Có th? g?i t? m?i sub-state c?a Auto
|
|
|
|
Console.WriteLine($"Error occurred: {error.Message}");
|
|
|
|
if (_stateMachine.IsSubStateOf(_stateMachine.CurrentState, RobotStateType.Auto))
|
|
{
|
|
// ?ang ? trong Auto hierarchy, có th? fire EnterFault
|
|
await _stateMachine.FireAsync(RobotEventType.EnterFault);
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Use Case 3: Dynamic UI buttons d?a trên available transitions
|
|
|
|
```razor
|
|
@* Blazor Component *@
|
|
@inject RobotStateMachine StateMachine
|
|
|
|
<div class="control-panel">
|
|
<h3>Current State: @StateMachine.CurrentState</h3>
|
|
|
|
<h4>Available Actions:</h4>
|
|
@foreach (var transition in StateMachine.GetPossibleTransitions())
|
|
{
|
|
<button @onclick="() => FireEvent(transition.Event)">
|
|
@transition.Event.ToString() ? @transition.ToState
|
|
</button>
|
|
}
|
|
</div>
|
|
|
|
@code {
|
|
private async Task FireEvent(RobotEventType eventType)
|
|
{
|
|
await StateMachine.FireAsync(eventType);
|
|
StateHasChanged();
|
|
}
|
|
}
|
|
```
|
|
|
|
**Khi ? Navigation state, UI s? hi?n th? T?T C? các buttons bao g?m:**
|
|
- StartAvoidance (riêng c?a Navigation)
|
|
- StartACT (k? th?a t? Moving)
|
|
- PauseExecution (k? th?a t? Executing)
|
|
- CancelExecution (k? th?a t? Executing)
|
|
- EnterManual (k? th?a t? Auto)
|
|
- EnterService (k? th?a t? Auto)
|
|
- EnterStop (k? th?a t? Auto)
|
|
- EnterFault (k? th?a t? Auto)
|
|
|
|
## 5. Best Practices
|
|
|
|
### ? DO: ??nh ngh?a common events ? parent state
|
|
|
|
```csharp
|
|
// Good: EnterFault ? Auto, t?t c? sub-states ??u có th? fault
|
|
builder.In(RobotStateType.Auto)
|
|
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
|
|
```
|
|
|
|
### ? DON'T: L?p l?i events ? m?i sub-state
|
|
|
|
```csharp
|
|
// Bad: Không c?n thi?t
|
|
builder.In(RobotStateType.Idle)
|
|
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
|
|
|
|
builder.In(RobotStateType.Executing)
|
|
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
|
|
|
|
builder.In(RobotStateType.Paused)
|
|
.On(RobotEventType.EnterFault).Goto(RobotStateType.Fault);
|
|
// ... l?p l?i cho t?t c? sub-states
|
|
```
|
|
|
|
### ? DO: Ki?m tra inherited transitions tr??c khi hi?n th? UI
|
|
|
|
```csharp
|
|
public List<RobotEventType> GetAvailableActionsForCurrentState()
|
|
{
|
|
var transitions = _stateMachine.GetPossibleTransitions();
|
|
return transitions.Select(t => t.Event).ToList();
|
|
}
|
|
```
|
|
|
|
## T?ng k?t
|
|
|
|
1. ? **Sub-states T? ??NG k? th?a** t?t c? events t? parent states
|
|
2. ? **Multi-level inheritance** ho?t ??ng (Navigation k? th?a t? Moving ? Executing ? Auto)
|
|
3. ? **GetPossibleTransitions()** ?ã ???c c?p nh?t ?? tr? v? c? inherited transitions
|
|
4. ? **CanFire()**, **CanTransitionTo()**, **GetEventForTransition()** ??u h? tr? inheritance
|
|
5. ? **Helper methods m?i**: GetParentState(), GetStateHierarchyChain(), IsSubStateOf()
|
|
|
|
?i?u này giúp code c?a b?n **DRY** (Don't Repeat Yourself) và d? maintain h?n!
|