Recover from being blocked by a static obstacle during fieldwork#1287
Recover from being blocked by a static obstacle during fieldwork#1287helgehelge123 wants to merge 1 commit into
Conversation
The ProximityController stops the vehicle in front of any obstacle and already fires onBlockingObject/onBlockingVehicle after a few seconds, but no listener was registered while working, so a vehicle blocked by a tree, a pole or a parked vehicle simply stood there forever with the BLOCKED_BY_OBJECT info text. AIDriveStrategyFieldWorkCourse now registers both listeners. When blocked in the WORKING state it raises the implements, backs up 10m (new REVERSING_AFTER_BLOCKED state) and then uses the existing startPathfindingToNextWaypoint() to find a way around the obstacle, resuming the course at the first waypoint at least 20m away (the strip the obstacle occupies cannot be worked anyway). Blocking vehicles are only treated like a static obstacle when they are stationary; moving vehicles are still waited for, and the combine strategy keeps its own blocking-vehicle handling. Since AITurn unregisters the blocking object listener at the end of each turn, the listener is re-registered while working. After 3 failed attempts in the same area the job is stopped with AIMessageErrorBlockedByObject instead of looping forever. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
||
| --- First waypoint of the fieldwork course that is far enough from the vehicle so that resuming there | ||
| --- clears the obstacle (the strip the obstacle occupies can't be worked anyway) | ||
| function AIDriveStrategyFieldWorkCourse:getWaypointToContinueBeyondObstacle() |
There was a problem hiding this comment.
Should use the existing Course:getNextWaypointIxWithinDistance() instead.
| -- instead of standing in front of a static obstacle forever, try to recover | ||
| -- (subclasses like the combine strategy may overwrite the vehicle listener with their own) | ||
| self.proximityController:registerBlockingObjectListener(self, AIDriveStrategyFieldWorkCourse.onBlockedByObject) | ||
| self.proximityController:registerBlockingVehicleListener(self, AIDriveStrategyFieldWorkCourse.onBlockedByVehicle) |
There was a problem hiding this comment.
This will be overwritten in AIDriveStrategyCombineCourse for combines.
| self.fieldWorkerProximityController = FieldWorkerProximityController(self.vehicle, self.workWidth) | ||
| -- instead of standing in front of a static obstacle forever, try to recover | ||
| -- (subclasses like the combine strategy may overwrite the vehicle listener with their own) | ||
| self.proximityController:registerBlockingObjectListener(self, AIDriveStrategyFieldWorkCourse.onBlockedByObject) |
There was a problem hiding this comment.
This sets the listener in all modes, such as DRIVING_TO_WORK_START_WAYPOINT, and incorrectly result in starting to work (lower implements) after driving around the obstacle. Would be cleaner to only register in the WORKING state.
| self:onBlockedByObject(isBack) | ||
| end | ||
|
|
||
| --- First waypoint of the fieldwork course that is far enough from the vehicle so that resuming there |
There was a problem hiding this comment.
This could lead to all kinds of colorful scenarios whenever there is a special waypoint within the skip distance, such as a turn, or a connecting path transition.
| -- turns and the other states have their own blocked handling | ||
| return | ||
| end | ||
| -- limit the number of attempts in the same area so we do not bounce between obstacles forever |
There was a problem hiding this comment.
With 50 meters, what happens when we meet the same object in the following up/down rows?
Problem
The ProximityController stops the vehicle in front of any obstacle and already fires
onBlockingObject/onBlockingVehicleafter ~5/7 seconds of blockade - but during normal fieldwork no listener is registered (onlyAITurnregisters one during turns). A vehicle blocked mid-course by a tree, a pole or a parked vehicle stands there forever, showing BLOCKED_BY_OBJECT.Solution
AIDriveStrategyFieldWorkCoursenow registers both blocking listeners and recovers, reusing existing building blocks (Course.createStraightReverseCourse,startPathfindingToNextWaypoint):REVERSING_AFTER_BLOCKEDstate, added to the implement controllers' default disabled states),AIMessageErrorBlockedByObjectinstead of looping.Notes:
onBlockingVehiclehandling, as it registers its listener after this one.AITurnunregisters the blocking object listener at the end of every turn (single-slot registration), so the listener is re-registered in the WORKING branch ofgetDriveData.blockedRecoveryReverseDistance,blockedRecoverySkipDistance,blockedRecoveryMaxAttempts).Testing
Tested in singleplayer with obstacles placed mid-row and on headlands. Feedback on edge cases (convoys, vine fields) is very welcome.
🤖 Generated with Claude Code