We need to distinguish two cases for how the interface of a nested serial container is determined:
1. from its children
2. from its (outer) context
As long as the interface is not fully resolved, requiredInterface() returns UNKNOWN.
After pruning, the first/last child's interface is remembered and reported instead.
If PropagatingEitherWay's interface is not met in *both* directions (but only one),
in BOTHWAY mode, issue a warning. Otherwise handle both, AUTO and BOTHWAY mode,
in the same fashion when resolving interfaces.
TODO: move validateConnectivity() in StagePrivate.
default action = default action from ContainerBase.
PropagatingEitherWay: issue warning for case above
These branches only work together:
- MoveTo / MoveRelative: common handling of "goal" property
- properties: required changes to allow for multiple inheritance
- generalize SimpleGrasp / GenerateGraspPose
- solutions_, failures_ as SolutionBaseConstPtrs in StagePrivate
- replace processSolutions() / processFailures() by direct const-access to storage containers
- generic sendForward(), sendBackward(), spawn(), connect() methods in StagePrivate
- reuse StagePrivate's sendForward(), sendBackward(), spawn() in containers
- store created InterfaceStates in StagePrivate::states_
- Interface: ordered<InterfaceState*> (only store pointers)
allows for common handling of states of valid and failure solutions
- remove additional state+solution storages
- containers: internal->external state mapping as InterfaceState* -> InterfaceState*
- remove bool return value
- always create a solution trajectory, also in case of failures
- success/failure determined from solution.isFailure()
minor adjustments during cherry-pick
- postpone pruning / interface auto-detection to top task-level
only the task state knows for sure, that it requires its wrapped child to push to both ends
- perform connectivity validation only after pruning
only then, we the interfaces are completely determined