Component / Module: openTCS kernel (org.opentcs.kernel.vehicles)
Background
When a transport order assigned to a vehicle is withdrawn, the kernel removes the order from the vehicle and clears the adapter's command queue (DefaultVehicleController#abortTransportOrder / dispatcherService.withdrawByVehicle). However, the kernel does not actively inform the VehicleCommAdapter that the order has been withdrawn. As a result, the adapter (which represents the real vehicle) has no standard way to learn that its current task was cancelled, and therefore cannot, e.g., send a cancel command to the physical vehicle (HTTP request, MQTT message, etc.).
Current situation
DefaultVehicleController only clears commands and releases resources; there is no adapter callback on withdrawal.
- Integrators must work around this, e.g. by listening for
TCSObjectEvent of type OBJECT_MODIFIED on the Vehicle, detecting the transition transportOrder != null -> null, and then invoking a custom method on a custom adapter base class (notifyOrderWithdrawn()). This workaround is project-specific, brittle (relies on event timing and a custom adapter type) and has to be re-implemented in every integration project.
Proposed feature
Add a standardized hook in the kernel's vehicle controller so that, after a transport order is regularly withdrawn (smooth withdrawal, i.e. withdrawByVehicle(vehicle, false) / non-immediate abort), the kernel invokes a callback on the VehicleCommAdapter, e.g.:
// In VehicleCommAdapter (or a new interface)
default void onTransportOrderWithdrawn(TransportOrder order) {
// no-op by default
}
and the kernel calls it from DefaultVehicleController once the withdrawal is applied (distinguishing a regular withdrawal from an immediate/forced abort, since immediate abort already clears the queue and may not need the same notification semantics).
Acceptance Criteria
- The adapter is notified when a non-immediate (regular) withdrawal completes.
- The default implementation is a no-op so existing adapters are unaffected.
- Immediate/forced aborts are handled consistently (either also notified, or explicitly excluded with documented semantics).
- Notification is sent without holding the kernel
globalSyncObject / commAdapter lock, to avoid deadlocks (integrators typically forward to their own thread pool).
Reference implementation (integration project workaround)
A custom VehicleController#onEvent detects Vehicle OBJECT_MODIFIED with transportOrder going from non-null to null, then calls a custom adapter base class method notifyOrderWithdrawn(). This proves the demand is real but should ideally be a kernel-level feature.
Component / Module: openTCS kernel (
org.opentcs.kernel.vehicles)Background
When a transport order assigned to a vehicle is withdrawn, the kernel removes the order from the vehicle and clears the adapter's command queue (
DefaultVehicleController#abortTransportOrder/dispatcherService.withdrawByVehicle). However, the kernel does not actively inform theVehicleCommAdapterthat the order has been withdrawn. As a result, the adapter (which represents the real vehicle) has no standard way to learn that its current task was cancelled, and therefore cannot, e.g., send a cancel command to the physical vehicle (HTTP request, MQTT message, etc.).Current situation
DefaultVehicleControlleronly clears commands and releases resources; there is no adapter callback on withdrawal.TCSObjectEventof typeOBJECT_MODIFIEDon theVehicle, detecting the transitiontransportOrder != null -> null, and then invoking a custom method on a custom adapter base class (notifyOrderWithdrawn()). This workaround is project-specific, brittle (relies on event timing and a custom adapter type) and has to be re-implemented in every integration project.Proposed feature
Add a standardized hook in the kernel's vehicle controller so that, after a transport order is regularly withdrawn (smooth withdrawal, i.e.
withdrawByVehicle(vehicle, false)/ non-immediate abort), the kernel invokes a callback on theVehicleCommAdapter, e.g.:and the kernel calls it from
DefaultVehicleControlleronce the withdrawal is applied (distinguishing a regular withdrawal from an immediate/forced abort, since immediate abort already clears the queue and may not need the same notification semantics).Acceptance Criteria
globalSyncObject/commAdapterlock, to avoid deadlocks (integrators typically forward to their own thread pool).Reference implementation (integration project workaround)
A custom
VehicleController#onEventdetectsVehicleOBJECT_MODIFIEDwithtransportOrdergoing from non-null to null, then calls a custom adapter base class methodnotifyOrderWithdrawn(). This proves the demand is real but should ideally be a kernel-level feature.