Forking the discussion from ROSbot GoPi5Go-Dave Architecture because I was hijacking the thread:
@cyclicalobsessive, Here’s my idea:
- Four main modes of action:
- Do something. (“Chase the Cat” or whatever)
- Avoid. (Am I too close to something?)
- Escape. (Did I just hit something?)
- Emergency stop. (Sudden, unexplained, massive failure.)
- Proposed implementation:
-
Five software objects: (in priority order)
-
Emergency Stop
The Emergency Stop is an “Oh, !!” exception handling routine that, ideally, will never be needed. If activated, it assumes total control, stops the robot, and kills the entire process stack by throwing a non-maskable exception, stopping everything. -
The arbiter
The arbiter is responsible for deciding which of the other three software objects has control, permitting control, withholding permission and/or revoking permission to control. This would essentially implement a “cooperative multi-tasking system” - sort-of. -
Escape
Escape is responsible for monitoring the bumper sensor. If the bumper sensor is activated, it requests permission to run from the arbiter and once granted performs a movement to escape from the obstacle - such as a back-up and rotate maneuver. -
Avoid
Avoid is responsible for monitoring the distance sensor. If the distance sensor registers the presence of an obstacle within “X” cm, it requests permission to run from the arbiter and once granted performs a movement to avoid the obstacle - such as a change of direction until the obstacle is no longer detected. -
“Do something”
“Do something” is the “main” functionality routine for the robot. It is responsible for making the robot do what I want it to do at that point in time.
-
-
Inter-process communication model:
-
Each process, (except for the arbiter), has access to an individual set of status and control flags:
-
Alive:
This flag serves as a “heartbeat” flag. Every arbiter cycle this flag is cleared for each process and is set when the process runs it’s next polling cycle. The arbiter checks to see if the flag is set before clearing it and the process checks to see that the arbiter cleared it. -
Request_to_run:
This flag is set by the process to indicate to the arbiter that it wants to run. -
Allowed_to_run:
This flag is set by the arbiter granting permission to the process to run. The process is responsible for checking the status of this flag every polling cycle and, if cleared, the process must stop as rapidly as possible. -
Running:
This is set by the process to indicate that it has control of the robot. This flag is cleared when either it has finished what it was doing, or immediately after stopping when the allowed_to_run is cleared. -
Mutex:
This “flag” - is implemented as a mutex to arbitrate access between the arbiter and a particular processes flags to guarantee atomic access.
-
-
Basic process flow:
-
Arbiter starts, establishes all the flags and establishes the mutex.
-
Arbiter starts the three processes and verifies via the “alive” flag that the processes are running.
-
The main (Do Something) process immediately raises it’s request_to_run flag.
-
If none of the other two processes want to run, the main process is allowed to run and the main process raises its “running” flag.
-
If one of the other two processes raises its request_to_run flag, the arbiter clears the main processes allowed_to_run flag, waits for the “running” flag to clear, and then allows the requesting process to run.
-
If both processes raise their request_to_run flag, the Escape process is allowed control before the Avoid process.
-
Once neither the Escape nor the Avoid process want to run, control is returned to the main program.
-
-
-
Heartbeat process integrity control
- Process failure is monitored by the three “Alive” flags.
-
Every time the arbiter runs, and after it processes a particular processes state, it clears that processes “Alive” flag.
-
The arbiter will eventually clear all three “Alive” flags after it completes one polling cycle. If a particular processes alive flag is not reset active after “X” polling cycles, the arbiter records a “X” process died event, signals all processes to stop, and transfers control to the emergency routine. (If the arbiter has control over the other three processes state, it kills the processes before it continues.)
-
Each process, as it begins its processing loop, first checks to see if the “Alive” flag has been cleared. If it has, it resets it to active and continues with it’s normal processing. If the Alive flag hasn’t been cleared after “X” number of polling loops, it stops everything it’s doing, records an “Arbiter Died” event, and immediately transfers control to the Emergency routine.
-
- Process failure is monitored by the three “Alive” flags.
- Process flow control
-
The main process, (“Do Something”), gets control by default and begins running by requesting permission to run, being granted permission, setting its “Running” flag, and begins running the code.
-
Each of the other exception processes, (escape and avoid), checks to see if the thing(s) it’s responsible for need attention. If it does, the routine raises its associated request_to_run flag and waits for its specific allowed_to_run flag to be set. . Once that flag it set, it clears the request_to_run flag and sets the running flag. It then begins doing its specific task.
- If, while waiting for permission to run, the event that triggered the particular request to run is resolved, the routine clears the request_to_run flag. (i.e. The bumper records an impact event and the distance sensor records an “object too close” event at the same time.)
Since the escape, (bumper) routine is allowed to run first, it will back away and change direction. Because the Escape routine changed the robot’s position, the distance sensor may not be too close to something anymore - therefor the “Avoid” process also clears its request_to_run flag.
- If, while waiting for permission to run, the event that triggered the particular request to run is resolved, the routine clears the request_to_run flag. (i.e. The bumper records an impact event and the distance sensor records an “object too close” event at the same time.)
-
Each process continues to check the allowed_to_run flag. If set, it continues. If cleared, it immediately halts its activity and clears the running flag.
-
Each process sets the alive flag every polling loop.
This interaction between the arbiter, (clearing the flag), and each process, (setting the flag), provides a method for each process to notify the arbiter if it dies and notify itself if the arbiter dies.
- Process flow summary:
-
Assume the main program is running.
- Its “Running” flag is set
- Its “Allowed_to_run” flag is set
- Its “Request_to_run” flag is cleared.
- Its “Alive” flag should be toggling at a speed governed by the speed of the routines controlling it.
-
Assume that an “event” occurs. (either a bumper impact or a distance sensor event.)
-
The process responsible for that event raises its “Request_to_run” flag.
-
On the next arbiter run cycle, it recognizes the raised flag as an event that takes priority over the main program. If it were not a higher priority process, it would be forced to wait until the higher priority task(s) had ended.
-
It clears the main program’s “Allowed_to_run” flag, revoking permission to run and waits for the “Running” flag to clear.
-
It sets the requesting processes “Allowed_to_run” flag.
-
-
The requesting process then releases the “Request_to_run” flag and sets its “Running” flag.
-
The arbiter sees the “Running” flag for that process asserted and continues polling.
-
The running process continues to run until:
-
The process is complete, where it releases its “Running” flag, which allows the arbiter to restart any pending, lower priority tasks.
- In the case of the main task, it continues to run until it’s either interrupted again or ends.
- In the case of the main task, it continues to run until it’s either interrupted again or ends.
-
It is interrupted by a higher priority process.
-
An “Emergency” event occurs which kills everything.
-
-
I’m sure there’s more to think about but this is my first pass at fleshing out an “architecture”.