I have “SLAM!!” implemented on both my robots too.
But only if I forget to implement the bumpers!
P.S.
Is there a way to make “bumper hit” a going process thing such that:
If the robot isn’t moving it either does nothing or makes a noise/flashes a light.
If the robot is moving, take avoidance action. (Stop? Backup and turn?)
Include the distance sensor?
Should it be a service?
What happens if the robot is already doing something, (moving under the control of a different program), when it happens? How do I make them interact peacefully?
I don’t expect you to write the code, but hints and suggestions would be appreciated.
Subsumption architecture is a control architecture
that organizes robot behaviors into a hierarchy of layers
to achieve rapid responses. It's a way of decomposing complex behaviors
into simpler modules, which are then organized into layers.
Each layer has a specific goal, and higher layers can subsume lower levels
to create more comprehensive behaviors.
An example for an autonomous wall or line following robot with bumpers:
So the robot having no sensors yelling at it will “cruise”
until a sensor triggers a higher priority behavior
until another sensor triggers an even higher priority behavior
or until the triggering sensor clears and the triggered behavior completes
It gets complicated quick when you try to keep it all straight in your programming because the simplest implementation uses multi-tasking and needs inter-task-communication (global variables is simplest)
tasks:
escape() finite state machine based on bumpers and a timer issues escape values for [translate,rotate]
avoid() finite state machine based on distance sensors issues avoid values for [translate,rotate]
follow() Issues follow values when wall/line are detected - [translate,rotate]
cruise() Issues cruise values for [translate, rotate]
arbitrate() Decides which behavior’s [translate,rotate] commands to pass to motors task
motors() combines translate and rotation commands to drive motors
report() Writes active behavior and resultant motor commands to display
a main() task that starts and can kill all the other tasks
inter-task communication:
cruise_trans, cruise_rotate, cruise_active
follow_trans, follow_rotate, follow_active
avoid_trans, avoid_rotate, avoid_active
escape_trans, escape_rotate, escape_active
motor_trans, motor_rotate
If you are serious about using the subsumption architecture for your robot, you can study my implementation in “Interactive C”. It is only four pages…
It sounds like a loop with a callback function would be simpler, (), like I did with the joystick controlled robot’s JavaScript to poll for joystick events.
In purely hardware terms I would program an interrupt handler that would be triggered when any sensor “fires” and would poll to discover which sensor was triggered.
In the case of your robots, Carl in particular, you seem to implement something like this, where the battery monitor can interrupt other functions.
(An old robot vacuum we have kicking around that needs a battery.)
Maybe I should convert this into a robot? It even has a dock!
Yeah, and I need a new head too. . . .
At this stage of the game, I’m not sure I know enough about the robot per se to even think about an architecture.
I’m not even sure what the present architecture is. To me, it’s more like washing clothes: You crumble everything up, toss it into the machine, add soap, turn the machine on, and hope things get clean without the color from your jeans getting on everything else.
[Shakes head, wondering what to do.]
Since I don’t know what the current architecture is,[1] I have no idea how to modify it to become the architecture I want.
No it did not. It assumes the layers are doing their thing all the time, and posting what they want on the “global bulletin board”, and one layer is arbitrating which layer’s wishes to pass on to the motor layer.
The arbiter layer is a timed loop, not an interrupt handler
If the action is very quick and does not require much processing.
Better to have a class with a timed loop main method that implements a state machine where each state performs some function and checks for event flags that should cause a transition to a new state.
Hardware interrupt callbacks set a class event flag and return immediately. The main state machine will see the hardware event flags and prioritize them based on the current state.
This way both hardware and software can set/reset event flags.
Is it possible to have “avoid” and “escape” running as a service so that anything can use it, or is it better to make it a shared library?
I’m assuming that various things, like “escape” and “avoid” should use mutexes to prevent them from stepping on each other. Right?
Either that or a set of shared global variables/flags that can be monitored like a programmatic “semaphore” to indicate what the current state is.
In this model, a process that wants to enter a particular state would set a state request flag and wait for a state acknowledge response which gives it permission to enter that state.
It then sets a running state flag and clears the state request flag.
While running, it monitors it’s state acknowledge flag and if reset, stops. If the situation changes, the routine can clear its own running or request flags.
The main arbitration routine would be responsible for responding to the state request flags by granting or withholding permission.
If state “x” is active and a higher state needs to run, the arbiter can revoke permission by clearing the state’s acknowledge flag. The state responds by stopping and clearing its running flag. Once that flag is cleared, the arbiter can start the next needed process.
There would need to be a way to kill and restart a process that gets stuck and doesn’t clear its flags within a reasonable amount of time.
I could implement “flags” by creating variables that increment by orders of magnitude:
1 = request
10 = acknowledge
100 = running.
Adding or subtracting the appropriate number sets or clears the flag.
Or, I could create a True|False variable for each state for each process. (Which might be easier to work with and would be easier to understand while running.)
I could also implement an “Emergency” flag which would halt everything.
If I wanted to get fancy, the arbiter could also manage a display showing the current state and the value of all the flags.
No, each behavior layer (cruise, avoid, escape) is running without concern for the other, so one, two, or all of them will be “active” (“think” it is controlling the motors),
but the arbiter implements the layer priority and passes motor commands from the highest priority layer, that is “active”.
The arbiter could have “disable layer” flags that top level behaviors could use to temporarily remap a sensor input such as a “wait for bump” layer that disables the escape and cruise layers’ motor commands until bumped, then resets the disable flag for escape and cruise.