private IEnumerable <Event> Main() { while (true) { Priority = _pendingPrio; Mode = _pendingMode; switch (Mode) { case CraneAgentMode.Idle: State = CraneAgentState.Waiting; Utilization?.UpdateTo(0); _interruptible = true; yield return(new Event(_world.Environment)); _world.Environment.ActiveProcess.HandleFault(); continue; case CraneAgentMode.Dodge: State = CraneAgentState.Moving; Utilization?.UpdateTo(1); _interruptible = true; var moveProcess = _world.Environment.Process(MoveCrane(_dodgePosition, _dodgePosition)); yield return(moveProcess); if (_world.Environment.ActiveProcess.HandleFault()) { moveProcess.Interrupt(); _interruptible = false; yield return(moveProcess); continue; } _pendingMode = CraneAgentMode.Work; _pendingPrio = null; break; case CraneAgentMode.Work: var workingProcess = _world.Environment.Process(Working()); _interruptible = true; yield return(workingProcess); if (_world.Environment.ActiveProcess.HandleFault()) { workingProcess.Interrupt(); _interruptible = false; yield return(workingProcess); continue; } break; default: throw new InvalidOperationException($"Error in CraneAgent, unknown mode: {_pendingMode}."); } } }
public void Cancel() { if (_pendingMode == CraneAgentMode.Idle) { return; } _pendingMode = CraneAgentMode.Idle; _pendingPrio = null; if (_interruptible) { _mainProcess.Interrupt(); // Cancel will even interrupt a current movement if possible } else { _world.Environment.Log($"INFO: Crane {Id} to cancel, but cannot be interrupted."); } }
public void Resume() { if (_pendingMode == CraneAgentMode.Work) { return; } _pendingMode = CraneAgentMode.Work; _pendingPrio = null; if (Mode == CraneAgentMode.Idle && _interruptible) { _mainProcess.Interrupt(); } else { _world.Environment.Log($"INFO: Crane {Id} to resume, but not currently idle."); } }
public void Dodge(double dodgePosition, double?othersPrio) { if (_pendingMode == CraneAgentMode.Dodge) { return; } _pendingMode = CraneAgentMode.Dodge; _pendingPrio = (othersPrio + Math.Ceiling((othersPrio ?? 0) + 1e-7)) / 2.0; // propagate priority _dodgePosition = dodgePosition; if (State == CraneAgentState.Waiting && _interruptible) { _mainProcess.Interrupt(); // Dodge will only interrupt main when it's not doing something else } else { _world.Environment.Log($"INFO: Crane {Id} to dodge, but not currently waiting."); } }
public CraneAgent(IStackingEnvironment world, ICrane crane, IDistribution <double> girderSpeed, IDistribution <double> hoistSpeed, IDistribution <double> manipulationTime) { _world = world; _crane = crane; GirderSpeed = girderSpeed; HoistSpeed = hoistSpeed; ManipulationTime = manipulationTime; _pendingMode = Mode = CraneAgentMode.Work; State = CraneAgentState.Waiting; GoalPosition1 = GoalPosition2 = _crane.GirderPosition; _targetGirderPosition = _crane.GirderPosition; _lastUpdate = world.Now; _mainProcess = world.Environment.Process(Main()); WhenPickupOrDropoffQueue = new List <Event>(); }