The Olympe DSL is an asynchronous API so you can build complex expressions and wait for the expectations asynchronously. Doing the same thing with a traditional if clause would require the user to spread the program logic in multiple callbacks. It brings similar (but different) advantages/drawbacks as asynchronous coroutines.
I don’t understand what you mean by “look back callback mechanism” but I’ll try to shed some light on the Olympe DSL below.
The Olympe DSL defines a kind of program that you can execute later. You can choose to execute an Olympe DSL expression with or without waiting for the end of its execution, just call .wait()
on the expectation object to block the current thread until the expectation is done.
You can see an Olympe DSL expression as a succession of messages to be sent/received. For example
CmdA() >> EvtB() >> CmdC()
The above DSL expression is a program that will send CmdA then waits for EvtB and then sends CmdC.
To execute this DSL expression/program, you have to submit it to a Drone object.
drone(CmdA() >> EvtB() >> CmdC())
This will execute the expression. First, CmdA is sent to the drone, then Olympe waits for EvtB and then sends CmdC. If EvtB is not received, the execution stops and CmdC is not sent. This is all done asynchronously. So it means that in the following code, the print('Hello there!')
will most probably be executed while CmdA has not been sent yet :
drone(CmdA() >> EvtB() >> CmdC())
print('Hello there!')
If you want to wait for the expression to be executed, you have to .wait()
:
drone(CmdA() >> EvtB() >> CmdC()).wait(10)
print('Hello there!')
If you want to execute some code only if an expression has successfully been executed, you can test the expression with the .success()
expectation method :
if drone(CmdA() >> EvtB() >> CmdC()).wait(10).success():
print('Hello there!')
If you want to wait for two events in parallel, you can use the &
(AND) or |
(OR) operators. For example :
EvtA() & EvtB()
is an expression that expects an EvtA and an EvtB but without specifying a specific order i.e. either EvtA or EvtB may be received first but in the end EvtA and EvtB must be received for the entire expectation to be successful.
drone(EvtA() & EvtB()).wait(10).success() # is True only if EvtA and EvtB have been received with 10 seconds
Conversely:
drone(EvtA() | EvtB()).wait(10).success() # is True if either EvtA or EvtB (or both events) have been received within 10 seconds
Olympe evaluates a DSL expressions from left to right and try to evaluate any subexpression synchronously whenever possible. If a subexpression is synchronously evaluated, the next subexpression to the right might not be evaluated. For example :
drone(FlyingStateChanged(state="hovering") | TakeOff()).wait(10)
In the above example, if the drone is currently in hovering, the TakeOff
command is not sent and the whole expression is successful. If the drone is not in hovering, the TakeOff
command is sent and the whole expression is successful either if the drone eventually reaches the hovering state or if the TakeOff
command built-in expectations (flying state “motor_raming” and then “takingoff”) are successful.
This is not currently implemented and I definitely see the use case for this. This should not be too difficult to do, I just didn’t had time to implement this feature.