using System.Threading;
using RobotNet10.RobotApp.Interfaces;
using RobotNet10.RobotApp.Motion;
using RobotNet10.RobotApp.Services.Robot;
using RobotNet10.Shared.Geometry;
namespace RobotNet10.RobotApp.Services.State;
///
/// Class chứa các implementation methods cho Entry/Exit actions của State Machine
/// Sử dụng IServiceProvider để có thể inject các services khác khi cần
///
public class RobotStateMachineExecute(IServiceScopeFactory ServiceScopeFactory, IPlcController PlcController, Logger Logger)
{
// ===========================
// SYSTEM STATE HANDLERS
// ===========================
///
/// Entry: System -> Initializing
/// Thực hiện khởi tạo các component của robot
///
public async Task EntryInitializingAsync()
{
Logger.Info("==> Entry Initializing State");
try
{
// TODO: Khởi tạo các services
// - Kiểm tra kết nối phần cứng
// - Khởi tạo Driver
// - Khởi tạo Sensors
// - Load cấu hình
using var scope = ServiceScopeFactory.CreateAsyncScope();
var robotController = scope.ServiceProvider.GetRequiredService();
await robotController.ModuleInitializeAsync();
}
catch (Exception ex)
{
Logger.Error($"Initialization error: {ex.Message}");
throw;
}
}
public void EntryInitializing() => EntryInitializingAsync().GetAwaiter().GetResult();
///
/// Entry: System -> Standby
/// Robot đã sẵn sàng hoạt động
///
public void EntryStandby()
{
Logger.Info("==> Entry Standby State");
PlcController.SetSystemState(SystemState.IDLE);
using var scope = ServiceScopeFactory.CreateAsyncScope();
var stateService = scope.ServiceProvider.GetRequiredService();
var visualizationService = scope.ServiceProvider.GetRequiredService();
stateService.Start();
visualizationService.Start();
}
///
/// Entry: System -> Shutting_Down
/// Bắt đầu quá trình tắt máy
///
public async Task EntryShuttingDownAsync()
{
Logger.Info("==> Entry Shutting Down State");
try
{
// TODO:
// - Lưu trạng thái hiện tại
// - Dừng tất cả các task đang chạy
// - Ngắt kết nối an toàn
using var scope = ServiceScopeFactory.CreateAsyncScope();
var robotController = scope.ServiceProvider.GetRequiredService();
robotController.StopHandler();
Logger.Info("Shutdown completed");
}
catch (Exception ex)
{
Logger.Error($"Shutdown error: {ex.Message}");
}
}
public void EntryShuttingDown() => EntryShuttingDownAsync().GetAwaiter().GetResult();
///
/// Exit: System -> Shutting_Down
///
public void ExitShuttingDown()
{
Logger.Info("<== Exit Shutting Down State");
}
// ===========================
// AUTO MODE STATE HANDLERS
// ===========================
///
/// Entry: Auto -> Idle
/// Robot sẵn sàng nhận nhiệm vụ mới
///
public void EntryIdle()
{
Logger.Info("==> Entry Idle State");
PlcController.SetSystemState(SystemState.IDLE);
}
///
/// Entry: Auto -> Executing
/// Bắt đầu thực hiện nhiệm vụ
///
public void EntryExecuting()
{
Logger.Info("==> Entry Executing State");
using var scope = ServiceScopeFactory.CreateAsyncScope();
var PlcController = scope.ServiceProvider.GetRequiredService();
PlcController.SetOperationState(OperationState.Move);
// TODO:
// - Lấy nhiệm vụ từ queue
// - Khởi tạo execution context
// - Bắt đầu timer theo dõi
// - Cập nhật VDA5050 state = "EXECUTING"
}
///
/// Exit: Auto -> Executing
///
public void ExitExecuting()
{
Logger.Info("<== Exit Executing State");
using var scope = ServiceScopeFactory.CreateAsyncScope();
var PlcController = scope.ServiceProvider.GetRequiredService();
PlcController.SetOperationState(OperationState.None);
// TODO:
// - Cleanup execution context
// - Dừng timer
}
///
/// Entry: Auto -> Paused
/// Tạm dừng thực hiện nhiệm vụ
///
public void EntryPaused()
{
Logger.Info("==> Entry Paused State");
// TODO:
// - Lưu trạng thái hiện tại
// - Dừng robot
// - Cập nhật VDA5050 state = "PAUSED"
// Dừng robot
StopRobot();
}
///
/// Exit: Auto -> Paused
/// Resume từ trạng thái pause
///
public void ExitPaused()
{
Logger.Info("<== Exit Paused State");
// TODO:
// - Khôi phục trạng thái
// - Chuẩn bị tiếp tục thực hiện
}
///
/// Entry: Auto -> Canceling
/// Đang hủy nhiệm vụ
///
public void EntryCanceling()
{
Logger.Info("==> Entry Canceling State");
// TODO:
// - Dừng robot ngay lập tức
// - Hủy tất cả các task con
// - Cleanup resources
StopRobot();
}
///
/// Exit: Auto -> Canceling
/// Hoàn tất việc hủy
///
public void ExitCanceling()
{
Logger.Info("<== Exit Canceling State");
// TODO:
// - Gửi thông báo nhiệm vụ đã hủy
// - Reset execution context
// - Cập nhật VDA5050 với error/cancelled
}
///
/// Entry: Auto -> Recovering
/// Đang khôi phục từ lỗi
///
public async Task EntryRecoveringAsync()
{
Logger.Info("==> Entry Recovering State");
try
{
// TODO:
// - Phân tích lỗi
// - Thực hiện recovery procedure
// - Kiểm tra trạng thái hệ thống
Logger.Info("Analyzing error...");
await Task.Delay(100);
Logger.Info("Recovering system...");
await Task.Delay(500);
Logger.Info("Recovery succeeded");
}
catch (Exception ex)
{
Logger.Error($"Recovery error: {ex.Message}");
}
}
public void EntryRecovering() => EntryRecoveringAsync().GetAwaiter().GetResult();
///
/// Entry: Auto -> Remote_Override (OVERRIDE)
/// Chuyển sang chế độ điều khiển từ xa - cho phép override tất cả safety
///
public void EntryRemoteOverride()
{
Logger.Info("==> Entry Remote Override State (OVERRIDE)");
PlcController.SetSystemState(SystemState.OVERRIDE);
StopRobot();
// Set ManualControlService state to Override - cho phép điều khiển với full override
try
{
using var scope = ServiceScopeFactory.CreateScope();
var manualControlService = scope.ServiceProvider.GetRequiredService();
manualControlService.SetState(ManualControlState.Override);
Logger.Info("ManualControlService set to Override state");
}
catch (Exception ex)
{
Logger.Error($"Error setting ManualControlService to Override: {ex.Message}");
}
}
///
/// Exit: Auto -> Remote_Override (OVERRIDE)
///
public void ExitRemoteOverride()
{
Logger.Info("<== Exit Remote Override State (OVERRIDE)");
// Clear ManualControlService external state
try
{
using var scope = ServiceScopeFactory.CreateScope();
var manualControlService = scope.ServiceProvider.GetRequiredService();
manualControlService.ClearExternalState();
Logger.Info("ManualControlService external state cleared");
}
catch (Exception ex)
{
Logger.Error($"Error clearing ManualControlService external state: {ex.Message}");
}
}
// ===========================
// EXECUTING - MOVING STATE HANDLERS
// ===========================
///
/// Entry: Executing -> Moving
/// Bắt đầu di chuyển
///
public void EntryMoving()
{
Logger.Info("==> Entry Moving State");
PlcController.SetSystemState(SystemState.PROCCESSING);
}
///
/// Exit: Executing -> Moving
///
public void ExitMoving()
{
Logger.Info("<== Exit Moving State");
// TODO:
// - Dừng robot
// - Lưu vị trí cuối cùng
StopRobot();
}
///
/// Entry: Moving -> Navigation
/// Chế độ navigation bình thường
///
public void EntryNavigation()
{
Logger.Info("==> Entry Navigation State");
// TODO:
// - Load path từ planner
// - Bắt đầu path following
// - Monitor obstacles
}
///
/// Entry: Moving -> Avoidance
/// Đang tránh chướng ngại vật
///
public void EntryAvoidance()
{
Logger.Info("==> Entry Avoidance State");
// TODO:
// - Giảm tốc độ
// - Tính toán đường tránh
// - Theo dõi obstacle
}
///
/// Exit: Moving -> Avoidance
///
public void ExitAvoidance()
{
Logger.Info("<== Exit Avoidance State");
// TODO:
// - Quay lại tốc độ bình thường
// - Resume path chính
}
///
/// Entry: Moving -> Approach
/// Tiếp cận mục tiêu (precision mode)
///
public void EntryApproach()
{
Logger.Info("==> Entry Approach State");
// TODO:
// - Chuyển sang precision mode
// - Giảm tốc độ tối đa
// - Sử dụng sensors chính xác cao
}
///
/// Entry: Moving -> Tracking
/// Theo dõi mục tiêu động
///
public void EntryTracking()
{
Logger.Info("==> Entry Tracking State");
// TODO:
// - Bật target tracking
// - Theo dõi vị trí mục tiêu
// - Điều chỉnh trajectory theo realtime
}
///
/// Entry: Moving -> Repositioning
/// Điều chỉnh lại vị trí
///
public void EntryRepositioning()
{
Logger.Info("==> Entry Repositioning State");
// TODO:
// - Tính toán vị trí mong muốn
// - Di chuyển điều chỉnh nhỏ
// - Kiểm tra orientation
}
// ===========================
// EXECUTING - ACT STATE HANDLERS
// ===========================
///
/// Entry: Executing -> ACT
/// Bắt đầu thực hiện action
///
public void EntryACT()
{
Logger.Info("==> Entry ACT State");
// TODO:
// - Dừng robot hoàn toàn
// - Chuẩn bị thực hiện action
// - Kiểm tra vị trí chính xác
StopRobot();
}
///
/// Exit: Executing -> ACT
///
public void ExitACT()
{
Logger.Info("<== Exit ACT State");
// TODO:
// - Cleanup action resources
// - Kiểm tra kết quả action
}
///
/// Entry: ACT -> Docking
/// Đang thực hiện docking
///
public async Task EntryDockingAsync()
{
Logger.Info("==> Entry Docking State");
PlcController.SetSystemState(SystemState.DOCKING);
try
{
// TODO:
// - Tìm vị trí dock station
// - Align với dock
// - Di chuyển vào dock từ từ
Logger.Info("Searching for dock station...");
await Task.Delay(200);
Logger.Info("Aligning with dock...");
await Task.Delay(300);
Logger.Info("Moving into dock...");
await Task.Delay(500);
Logger.Info("Docking succeeded");
}
catch (Exception ex)
{
Logger.Error($"Docking error: {ex.Message}");
throw;
}
}
public void EntryDocking() => EntryDockingAsync().GetAwaiter().GetResult();
///
/// Entry: ACT -> Docked
/// Đã docked thành công
///
public void EntryDocked()
{
Logger.Info("==> Entry Docked State");
PlcController.SetSystemState(SystemState.DOCKING);
}
///
/// Entry: ACT -> Charging
/// Đang sạc pin
///
public async Task EntryChargingAsync()
{
Logger.Info("==> Entry Charging State");
PlcController.SetSystemState(SystemState.CHARGING);
try
{
// TODO:
// - Bắt đầu charging
// - Monitor battery level
// - Monitor charging current/voltage
Logger.Info("Connecting charging power...");
await Task.Delay(100);
Logger.Info("Starting battery charging...");
// Charging loop sẽ được xử lý bởi battery service
}
catch (Exception ex)
{
Logger.Error($"Charging error: {ex.Message}");
throw;
}
}
public void EntryCharging() => EntryChargingAsync().GetAwaiter().GetResult();
///
/// Exit: ACT -> Charging
///
public void ExitCharging()
{
Logger.Info("<== Exit Charging State");
// TODO:
// - Dừng charging
// - Ngắt kết nối nguồn an toàn
// - Log battery level
}
///
/// Entry: ACT -> Undocking
/// Đang rời khỏi dock
///
public async Task EntryUndockingAsync()
{
Logger.Info("==> Entry Undocking State");
PlcController.SetSystemState(SystemState.DOCKING);
try
{
// TODO:
// - Kiểm tra an toàn
// - Ngắt kết nối với dock
// - Di chuyển ra khỏi dock
Logger.Info("Checking safety...");
await Task.Delay(100);
Logger.Info("Disconnecting dock...");
await Task.Delay(200);
Logger.Info("Moving out of dock...");
await Task.Delay(500);
Logger.Info("Undocking succeeded");
}
catch (Exception ex)
{
Logger.Error($"Undocking error: {ex.Message}");
throw;
}
}
public void EntryUndocking() => EntryUndockingAsync().GetAwaiter().GetResult();
///
/// Entry: ACT -> Loading
/// Đang tải hàng
///
public async Task EntryLoadingAsync()
{
Logger.Info("==> Entry Loading State");
PlcController.SetSystemState(SystemState.PROCCESSING);
try
{
// TODO:
// - Kiểm tra payload capacity
// - Điều khiển loading mechanism
// - Xác nhận hàng đã được tải
Logger.Info("Preparing loading...");
await Task.Delay(200);
Logger.Info("Loading cargo...");
await Task.Delay(1000);
Logger.Info("Loading completed");
}
catch (Exception ex)
{
Logger.Error($"Loading error: {ex.Message}");
throw;
}
}
public void EntryLoading() => EntryLoadingAsync().GetAwaiter().GetResult();
///
/// Entry: ACT -> Unloading
/// Đang dỡ hàng
///
public async Task EntryUnloadingAsync()
{
Logger.Info("==> Entry Unloading State");
PlcController.SetSystemState(SystemState.PROCCESSING);
try
{
// TODO:
// - Kiểm tra vị trí unload
// - Điều khiển unloading mechanism
// - Xác nhận hàng đã được dỡ
Logger.Info("Preparing unloading...");
await Task.Delay(200);
Logger.Info("Unloading cargo...");
await Task.Delay(1000);
Logger.Info("Unloading completed");
}
catch (Exception ex)
{
Logger.Error($"Unloading error: {ex.Message}");
throw;
}
}
public void EntryUnloading() => EntryUnloadingAsync().GetAwaiter().GetResult();
///
/// Entry: ACT -> TechAction
/// Thực hiện các action kỹ thuật đặc biệt
///
public async Task EntryTechActionAsync()
{
Logger.Info("==> Entry Tech Action State");
PlcController.SetSystemState(SystemState.PROCCESSING);
try
{
// TODO:
// - Xác định loại tech action
// - Thực hiện action tương ứng
// - Log kết quả
Logger.Info("Executing tech action...");
await Task.Delay(500);
Logger.Info("Tech action completed");
}
catch (Exception ex)
{
Logger.Error($"Tech action error: {ex.Message}");
throw;
}
}
public void EntryTechAction() => EntryTechActionAsync().GetAwaiter().GetResult();
// ===========================
// MODE TRANSITION HANDLERS
// ===========================
///
/// Entry: Manual Mode
/// Chuyển sang chế độ thủ công
///
public void EntryManual()
{
Logger.Info("==> Entry Manual Mode");
PlcController.SetSystemState(SystemState.MANUAL);
StopRobot();
}
///
/// Exit: Manual Mode
///
public void ExitManual()
{
Logger.Info("<== Exit Manual Mode");
// TODO:
// - Kiểm tra an toàn
// - Tắt manual control
// - Bật lại autonomous control
}
///
/// Entry: Service Mode (MAINTENANCE)
/// Chuyển sang chế độ bảo trì - cho phép điều khiển robot từ RF Handle
///
public void EntryService()
{
Logger.Info("==> Entry Service Mode (MAINTENANCE)");
PlcController.SetSystemState(SystemState.MAINTENANCE);
StopRobot();
// Set ManualControlService state to Maintenance - cho phép điều khiển từ RF Handle
try
{
using var scope = ServiceScopeFactory.CreateScope();
var manualControlService = scope.ServiceProvider.GetRequiredService();
manualControlService.SetState(ManualControlState.Maintenance);
Logger.Info("ManualControlService set to Maintenance state");
}
catch (Exception ex)
{
Logger.Error($"Error setting ManualControlService to Maintenance: {ex.Message}");
}
}
///
/// Exit: Service Mode (MAINTENANCE)
///
public void ExitService()
{
Logger.Info("<== Exit Service Mode (MAINTENANCE)");
// Clear ManualControlService external state
try
{
using var scope = ServiceScopeFactory.CreateScope();
var manualControlService = scope.ServiceProvider.GetRequiredService();
manualControlService.ClearExternalState();
Logger.Info("ManualControlService external state cleared");
}
catch (Exception ex)
{
Logger.Error($"Error clearing ManualControlService external state: {ex.Message}");
}
}
///
/// Entry: Stop State
/// Robot bị dừng (Emergency, Bumper, etc.)
///
public void EntryStop()
{
Logger.Warning("==> Entry STOP State");
PlcController.SetSystemState(SystemState.PAUSED);
EmergencyStop();
}
///
/// Exit: Stop State
/// Giải phóng stop
///
public void ExitStop()
{
Logger.Info("<== Exit Stop State");
// Giống Lock (SERVICE) → Auto/Manual: M815 pulse + fault reset + EnableAsync (RobotController.ApplyResetFromPlc).
ApplyAlarmResetAndEnableMotorsLikeLock();
}
///
/// Entry: Fault State
/// Robot gặp lỗi nghiêm trọng
///
public void EntryFault()
{
Logger.Error("==> Entry FAULT State");
PlcController.SetSystemState(SystemState.ERROR);
EmergencyStop();
}
///
/// Exit: Fault State
/// Đã khắc phục lỗi
///
public void ExitFault()
{
Logger.Info("<== Exit Fault State");
// 1. Clear remaining fatal errors
try
{
using var scope = ServiceScopeFactory.CreateScope();
var errorManager = scope.ServiceProvider.GetRequiredService();
errorManager.ClearFatalErrors();
}
catch (Exception ex) { Logger.Error($"ExitFault: Error clearing errors: {ex.Message}"); }
// 2. PLC alarm reset + servo: cùng chuỗi như thoát Lock / ApplyResetFromPlc
ApplyAlarmResetAndEnableMotorsLikeLock();
}
///
/// Pulse M815 (alarm reset trên PLC), sau đó FaultReset + chờ + EnableAsync — khớp RobotController.ApplyResetFromPlc (không gọi TryClearFault).
///
private void ApplyAlarmResetAndEnableMotorsLikeLock()
{
Logger.Info("ApplyAlarmResetAndEnableMotorsLikeLock: M815 + fault reset + enable (như Lock → Auto/Manual)");
try { PlcController.WriteAlarmResetM815(); }
catch (Exception ex) { Logger.Warning($"WriteAlarmResetM815: {ex.Message}"); }
try
{
using var scope = ServiceScopeFactory.CreateScope();
var ik = scope.ServiceProvider.GetService();
if (ik == null)
{
Logger.Warning("ApplyAlarmResetAndEnableMotorsLikeLock: IInverseKinematics không có");
return;
}
ik.FaultReset();
Thread.Sleep(1500);
ik.FaultReset();
Thread.Sleep(800);
ik.EnableAsync(CancellationToken.None).GetAwaiter().GetResult();
if (ik.IsOperationEnabled)
Logger.Info("ApplyAlarmResetAndEnableMotorsLikeLock: động cơ OperationEnabled");
else
Logger.Warning("ApplyAlarmResetAndEnableMotorsLikeLock: chưa OperationEnabled sau EnableAsync");
}
catch (Exception ex)
{
Logger.Warning($"ApplyAlarmResetAndEnableMotorsLikeLock: FaultReset/Enable — {ex.Message}");
}
}
// ===========================
// HELPER METHODS
// ===========================
///
/// Dừng robot bình thường - gửi zero velocity đến IInverseKinematics
///
private void StopRobot()
{
try
{
using var scope = ServiceScopeFactory.CreateScope();
var inverseKinematics = scope.ServiceProvider.GetService();
if (inverseKinematics == null)
{
Logger.Warning("IInverseKinematics not available, cannot stop robot");
return;
}
// Send zero velocity to stop the robot
// SetVelocity not available - commented out
// var zeroTwist = new Twist();
// inverseKinematics.SetVelocity(zeroTwist);
Logger.Info("Robot stopped (zero velocity intended)");
}
catch (AggregateException ex)
{
Logger.Error($"Stop robot error: {ex.InnerException?.Message ?? ex.Message}");
}
catch (Exception ex)
{
Logger.Error($"Stop robot error: {ex.Message}");
}
}
///
/// Dừng khẩn cấp robot - gửi zero velocity và disable IInverseKinematics
///
private void EmergencyStop()
{
try
{
using var scope = ServiceScopeFactory.CreateScope();
var inverseKinematics = scope.ServiceProvider.GetService();
if (inverseKinematics == null)
{
Logger.Warning("IInverseKinematics not available, cannot emergency stop robot");
return;
}
// Send zero velocity first
// SetVelocity not available - commented out
// var zeroTwist = new Twist();
// inverseKinematics.SetVelocity(zeroTwist);
// Disable the drive (if supported)
try
{
inverseKinematics.Disable();
}
catch (Exception disableEx)
{
Logger.Warning($"Could not disable IInverseKinematics: {disableEx.Message}");
}
Logger.Warning("EMERGENCY STOP! Robot stopped and disabled");
}
catch (AggregateException ex)
{
Logger.Error($"Emergency stop error: {ex.InnerException?.Message ?? ex.Message}");
}
catch (Exception ex)
{
Logger.Error($"Emergency stop error: {ex.Message}");
}
}
}