ActionDescription.perform() calls validate_postcondition() immediately after execute() returns, assuming the action's effects are done. However, execute() submits motions via SequentialPlan.perform(), which only collects goals for giskard without blocking until they complete. Actual motion execution is deferred until the outer ExecutionEnvironment flushes. This means validate_postcondition() and all post_perform callbacks fire before any motion has run:
result = self.execute() # submits motions, returns immediately
for post_cb in ...:
post_cb(self) # world state unchanged
self.validate_postcondition(result) # world state still unchanged
Any postcondition that checks world state (object grasped, robot at target pose, etc.) will silently produce incorrect results.
ActionDescription.perform()callsvalidate_postcondition()immediately afterexecute()returns, assuming the action's effects are done. However,execute()submits motions viaSequentialPlan.perform(), which only collects goals for giskard without blocking until they complete. Actual motion execution is deferred until the outer ExecutionEnvironment flushes. This meansvalidate_postcondition()and all post_perform callbacks fire before any motion has run:Any postcondition that checks world state (object grasped, robot at target pose, etc.) will silently produce incorrect results.