382 lines
13 KiB
Markdown
382 lines
13 KiB
Markdown
# H??ng d?n s? d?ng RobotStateMachineExecute
|
|
|
|
## Gi?i thi?u
|
|
|
|
`RobotStateMachineExecute` là class ch?a t?t c? các implementation methods cho Entry/Exit actions c?a State Machine. Class này ???c inject vào `RobotStateMachine` và t? ??ng ???c g?i khi state transitions x?y ra.
|
|
|
|
## Ki?n trúc
|
|
|
|
```
|
|
RobotStateMachine (Qu?n lý state transitions)
|
|
? s? d?ng
|
|
RobotStateMachineExecute (Implementation c?a Entry/Exit actions)
|
|
? s? d?ng
|
|
IServiceProvider (?? inject các services khác khi c?n)
|
|
```
|
|
|
|
## Danh sách các Entry/Exit Methods ?ã tri?n khai
|
|
|
|
### 1. System States
|
|
|
|
| State | Entry Method | Exit Method | Mô t? |
|
|
|-------|-------------|-------------|-------|
|
|
| **Initializing** | `EntryInitializing()` / `EntryInitializingAsync()` | - | Kh?i t?o các component c?a robot |
|
|
| **Standby** | `EntryStandby()` | - | Robot s?n sàng ho?t ??ng |
|
|
| **Shutting_Down** | `EntryShuttingDown()` / `EntryShuttingDownAsync()` | `ExitShuttingDown()` | T?t máy an toàn |
|
|
|
|
### 2. Auto Mode States
|
|
|
|
| State | Entry Method | Exit Method | Mô t? |
|
|
|-------|-------------|-------------|-------|
|
|
| **Idle** | `EntryIdle()` | - | S?n sàng nh?n nhi?m v? m?i |
|
|
| **Executing** | `EntryExecuting()` | `ExitExecuting()` | ?ang th?c hi?n nhi?m v? |
|
|
| **Paused** | `EntryPaused()` | `ExitPaused()` | T?m d?ng nhi?m v? |
|
|
| **Canceling** | `EntryCanceling()` | `ExitCanceling()` | ?ang h?y nhi?m v? |
|
|
| **Recovering** | `EntryRecovering()` / `EntryRecoveringAsync()` | - | Khôi ph?c t? l?i |
|
|
| **Remote_Override** | `EntryRemoteOverride()` | `ExitRemoteOverride()` | ?i?u khi?n t? xa |
|
|
|
|
### 3. Moving Sub-States
|
|
|
|
| State | Entry Method | Exit Method | Mô t? |
|
|
|-------|-------------|-------------|-------|
|
|
| **Moving** | `EntryMoving()` | `ExitMoving()` | B?t ??u di chuy?n |
|
|
| **Navigation** | `EntryNavigation()` | - | Navigation bình th??ng |
|
|
| **Avoidance** | `EntryAvoidance()` | `ExitAvoidance()` | Tránh ch??ng ng?i v?t |
|
|
| **Approach** | `EntryApproach()` | - | Ti?p c?n m?c tiêu |
|
|
| **Tracking** | `EntryTracking()` | - | Theo dõi m?c tiêu ??ng |
|
|
| **Repositioning** | `EntryRepositioning()` | - | ?i?u ch?nh v? trí |
|
|
|
|
### 4. ACT Sub-States
|
|
|
|
| State | Entry Method | Exit Method | Mô t? |
|
|
|-------|-------------|-------------|-------|
|
|
| **ACT** | `EntryACT()` | `ExitACT()` | B?t ??u action |
|
|
| **Docking** | `EntryDocking()` / `EntryDockingAsync()` | - | ?ang docking |
|
|
| **Docked** | `EntryDocked()` | - | ?ã docked |
|
|
| **Charging** | `EntryCharging()` / `EntryChargingAsync()` | `ExitCharging()` | ?ang s?c pin |
|
|
| **Undocking** | `EntryUndocking()` / `EntryUndockingAsync()` | - | ?ang undocking |
|
|
| **Loading** | `EntryLoading()` / `EntryLoadingAsync()` | - | ?ang t?i hàng |
|
|
| **Unloading** | `EntryUnloading()` / `EntryUnloadingAsync()` | - | ?ang d? hàng |
|
|
| **TechAction** | `EntryTechAction()` / `EntryTechActionAsync()` | - | Action k? thu?t |
|
|
|
|
### 5. Mode States
|
|
|
|
| State | Entry Method | Exit Method | Mô t? |
|
|
|-------|-------------|-------------|-------|
|
|
| **Manual** | `EntryManual()` | `ExitManual()` | Ch? ?? th? công |
|
|
| **Service** | `EntryService()` | `ExitService()` | Ch? ?? b?o trì |
|
|
| **Stop** | `EntryStop()` | `ExitStop()` | Tr?ng thái d?ng |
|
|
| **Fault** | `EntryFault()` | `ExitFault()` | Tr?ng thái l?i |
|
|
|
|
## Cách tùy ch?nh và m? r?ng
|
|
|
|
### 1. Inject thêm services
|
|
|
|
```csharp
|
|
public class RobotStateMachineExecute
|
|
{
|
|
private readonly IServiceProvider _serviceProvider;
|
|
private readonly Logger<RobotStateMachineExecute> _logger;
|
|
|
|
public void EntryDocking()
|
|
{
|
|
_logger.Info("==> Entry Docking State");
|
|
|
|
// L?y service t? IServiceProvider
|
|
var driver = _serviceProvider.GetService<IDriver>();
|
|
var sensors = _serviceProvider.GetService<ISensorService>();
|
|
var dockingController = _serviceProvider.GetService<IDockingController>();
|
|
|
|
if (dockingController != null)
|
|
{
|
|
// Th?c hi?n docking
|
|
dockingController.StartDocking();
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### 2. Thêm business logic c? th?
|
|
|
|
```csharp
|
|
public void EntryCharging()
|
|
{
|
|
_logger.Info("==> Entry Charging State");
|
|
|
|
var batteryService = _serviceProvider.GetService<IBatteryService>();
|
|
|
|
if (batteryService != null)
|
|
{
|
|
// B?t ??u monitoring charging
|
|
batteryService.StartCharging();
|
|
|
|
// Subscribe vào charging events
|
|
batteryService.OnChargingProgress += (sender, progress) =>
|
|
{
|
|
_logger.Info($"Charging progress: {progress}%");
|
|
};
|
|
|
|
batteryService.OnChargingCompleted += (sender, e) =>
|
|
{
|
|
_logger.Info("Charging completed!");
|
|
// Có th? t? ??ng fire event ?? chuy?n state
|
|
};
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3. X? lý async operations
|
|
|
|
M?t s? methods ?ã ???c tri?n khai v?i c? sync và async versions:
|
|
|
|
```csharp
|
|
// Async version - recommended
|
|
public async Task EntryDockingAsync()
|
|
{
|
|
_logger.Info("==> Entry Docking State");
|
|
|
|
var dockingController = _serviceProvider.GetService<IDockingController>();
|
|
|
|
if (dockingController != null)
|
|
{
|
|
await dockingController.AlignWithDockAsync();
|
|
await dockingController.ApproachDockAsync();
|
|
await dockingController.ConnectToDockAsync();
|
|
}
|
|
}
|
|
|
|
// Sync version - wrapper
|
|
public void EntryDocking() => EntryDockingAsync().GetAwaiter().GetResult();
|
|
```
|
|
|
|
### 4. Thêm error handling
|
|
|
|
```csharp
|
|
public void EntryExecuting()
|
|
{
|
|
_logger.Info("==> Entry Executing State");
|
|
|
|
try
|
|
{
|
|
var missionService = _serviceProvider.GetService<IMissionService>();
|
|
|
|
if (missionService != null)
|
|
{
|
|
var currentMission = missionService.GetCurrentMission();
|
|
|
|
if (currentMission == null)
|
|
{
|
|
_logger.Warning("No mission available");
|
|
// Fire event to go back to Idle
|
|
var stateMachine = _serviceProvider.GetService<RobotStateMachine>();
|
|
stateMachine?.Fire(RobotEventType.CompleteExecution);
|
|
return;
|
|
}
|
|
|
|
// Start executing mission
|
|
missionService.StartExecution(currentMission);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Error($"Error in EntryExecuting: {ex.Message}");
|
|
|
|
// Fire event to enter Fault state
|
|
var stateMachine = _serviceProvider.GetService<RobotStateMachine>();
|
|
stateMachine?.Fire(RobotEventType.EnterFault);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Ví d? th?c t?: Lu?ng Docking & Charging
|
|
|
|
```csharp
|
|
public async Task EntryDockingAsync()
|
|
{
|
|
_logger.Info("==> Entry Docking State");
|
|
|
|
try
|
|
{
|
|
var driver = _serviceProvider.GetService<IDriver>();
|
|
var sensors = _serviceProvider.GetService<ISensorService>();
|
|
var dockingService = _serviceProvider.GetService<IDockingService>();
|
|
|
|
if (dockingService == null)
|
|
{
|
|
_logger.Error("Docking service not available");
|
|
throw new InvalidOperationException("Docking service not available");
|
|
}
|
|
|
|
// 1. Tìm dock station
|
|
_logger.Info("Searching for dock station...");
|
|
var dockPosition = await dockingService.FindDockStationAsync();
|
|
|
|
if (dockPosition == null)
|
|
{
|
|
_logger.Error("Dock station not found");
|
|
throw new InvalidOperationException("Dock station not found");
|
|
}
|
|
|
|
// 2. Di chuy?n ??n v? trí dock
|
|
_logger.Info("Moving to dock position...");
|
|
await dockingService.MoveToDockPositionAsync(dockPosition);
|
|
|
|
// 3. Align v?i dock
|
|
_logger.Info("Aligning with dock...");
|
|
await dockingService.AlignWithDockAsync();
|
|
|
|
// 4. Di chuy?n vào dock ch?m rãi
|
|
_logger.Info("Approaching dock...");
|
|
await dockingService.SlowApproachAsync();
|
|
|
|
// 5. K?t n?i v?i dock
|
|
_logger.Info("Connecting to dock...");
|
|
var connected = await dockingService.ConnectToDockAsync();
|
|
|
|
if (!connected)
|
|
{
|
|
_logger.Error("Failed to connect to dock");
|
|
throw new InvalidOperationException("Failed to connect to dock");
|
|
}
|
|
|
|
_logger.Info("Docking completed successfully!");
|
|
|
|
// T? ??ng chuy?n sang state Docked
|
|
var stateMachine = _serviceProvider.GetService<RobotStateMachine>();
|
|
await stateMachine!.FireAsync(RobotEventType.CompleteDocking);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Error($"Docking failed: {ex.Message}");
|
|
|
|
// Chuy?n sang fault state
|
|
var stateMachine = _serviceProvider.GetService<RobotStateMachine>();
|
|
await stateMachine!.FireAsync(RobotEventType.EnterFault);
|
|
}
|
|
}
|
|
|
|
public async Task EntryChargingAsync()
|
|
{
|
|
_logger.Info("==> Entry Charging State");
|
|
|
|
try
|
|
{
|
|
var batteryService = _serviceProvider.GetService<IBatteryService>();
|
|
var dockingService = _serviceProvider.GetService<IDockingService>();
|
|
|
|
if (batteryService == null || dockingService == null)
|
|
{
|
|
_logger.Error("Required services not available");
|
|
return;
|
|
}
|
|
|
|
// 1. Ki?m tra k?t n?i dock
|
|
if (!dockingService.IsConnectedToDock())
|
|
{
|
|
_logger.Error("Not connected to dock");
|
|
return;
|
|
}
|
|
|
|
// 2. B?t ??u s?c
|
|
_logger.Info("Starting charging...");
|
|
await batteryService.StartChargingAsync();
|
|
|
|
// 3. Monitor charging progress
|
|
batteryService.OnChargingProgress += (sender, progress) =>
|
|
{
|
|
_logger.Info($"Battery level: {progress.CurrentLevel}% (Target: {progress.TargetLevel}%)");
|
|
|
|
// N?u ?ã ??t target level, hoàn thành charging
|
|
if (progress.CurrentLevel >= progress.TargetLevel)
|
|
{
|
|
_logger.Info("Target battery level reached!");
|
|
|
|
var stateMachine = _serviceProvider.GetService<RobotStateMachine>();
|
|
stateMachine?.Fire(RobotEventType.CompleteCharging);
|
|
}
|
|
};
|
|
|
|
// 4. Subscribe charging error events
|
|
batteryService.OnChargingError += (sender, error) =>
|
|
{
|
|
_logger.Error($"Charging error: {error.Message}");
|
|
|
|
var stateMachine = _serviceProvider.GetService<RobotStateMachine>();
|
|
stateMachine?.Fire(RobotEventType.EnterFault);
|
|
};
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.Error($"Failed to start charging: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
public void ExitCharging()
|
|
{
|
|
_logger.Info("<== Exit Charging State");
|
|
|
|
var batteryService = _serviceProvider.GetService<IBatteryService>();
|
|
|
|
if (batteryService != null)
|
|
{
|
|
// D?ng charging
|
|
batteryService.StopCharging();
|
|
|
|
// Unsubscribe events
|
|
batteryService.OnChargingProgress = null;
|
|
batteryService.OnChargingError = null;
|
|
|
|
// Log final battery level
|
|
var batteryLevel = batteryService.GetCurrentLevel();
|
|
_logger.Info($"Charging stopped. Final battery level: {batteryLevel}%");
|
|
}
|
|
}
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
1. **Luôn log chi ti?t** trong m?i Entry/Exit method ?? d? debug
|
|
2. **S? d?ng try-catch** ?? x? lý l?i và chuy?n sang Fault state n?u c?n
|
|
3. **S? d?ng async/await** cho các operations t?n th?i gian
|
|
4. **Cleanup resources** trong Exit methods
|
|
5. **Inject services qua IServiceProvider** thay vì hard-code dependencies
|
|
6. **Fire events** ?? t? ??ng chuy?n state khi hoàn thành action
|
|
7. **Validate preconditions** tr??c khi th?c hi?n action
|
|
8. **Update VDA5050 state** ?? ??ng b? v?i Fleet Manager
|
|
|
|
## Tích h?p v?i VDA5050
|
|
|
|
```csharp
|
|
public void EntryExecuting()
|
|
{
|
|
_logger.Info("==> Entry Executing State");
|
|
|
|
var vda5050Service = _serviceProvider.GetService<IVDA5050Service>();
|
|
|
|
if (vda5050Service != null)
|
|
{
|
|
// C?p nh?t VDA5050 state
|
|
vda5050Service.UpdateState(new StateMessage
|
|
{
|
|
OperatingMode = "AUTOMATIC",
|
|
ActionStates = new List<ActionState>
|
|
{
|
|
new() { ActionStatus = "RUNNING" }
|
|
}
|
|
});
|
|
}
|
|
|
|
// ... rest of implementation
|
|
}
|
|
```
|
|
|
|
## K?t lu?n
|
|
|
|
`RobotStateMachineExecute` cung c?p m?t cách t? ch?c code rõ ràng và d? maintain cho t?t c? các state behaviors c?a robot. B?n có th? d? dàng:
|
|
|
|
- Thêm logic m?i vào các state
|
|
- Inject và s? d?ng các services khác
|
|
- X? lý async operations
|
|
- Error handling và recovery
|
|
- Testing t?ng state behavior ??c l?p
|