Otherwise a new task will always setup the publisher,
even if introspection is disabled afterwards.
It is a good idea to keep introspection on, but there should be a way to initialize the C++ classes without ROS communication.
Validate interfaces during resolution. No need to separately validate interfaces.
Thus, validateConnectivity() is removed from Task::init().
Functions are kept (but simplified) for unit testing.
* Do not modify explicitly configured direction of Propagator
* Avoid code duplication in pruneInterface() and validateConnectivity()
Only implement pruneInterface() for stages that actually need to adapt their interface.
* Enforce at compile time that either input or output flags are considered.
* Use horizontal flow symbols (as in console output).
* Replace redundant direction(flags).
The PROPAGATE concept BOTH declared the stages *will* propagate solutions in
either direction. ANY, on the other hand, only means the propagation
direction is *not resolved yet* (but will be at planning time).
BOTH was originally described to support a more general control flow
than was eventually decided to support. The four exclusive Stage interfaces
CONNECT, PROPAGATE_FORWARDS, PROPAGATE_BACKWARDS, and GENERATOR
do not allow for BOTH as a valid setup anymore, unless you setup a very
convolved task like `Alternatives(GEN, PROP) - Alternatives(PROP, GEN)`
which would be very complex to inspect. The same functionality can still
be achieved more readable as `Alternatives(Seq(GEN, PROP), Seq(PROP, GEN))`.
The confusion between BOTH (propagator *will* send in both directions) and
ANY (propagator will send in *either* direction, decided during init) led
to a lot of confusion with users and was not fully accounted
throughout the pipeline.
Adjust tests.
Notice the difference between ANY (unresolved propagator) and UNKNOWN
(a container before introspecting its children). propagators still
report UNKNOWN as requiredInterface though to simplify control flow.
The simplification enables a much simpler linear inference of the connective
structure of a task, as the first interface direction is always given.
Additionally, unify the resource setup for static interfaces to run
in the constructor, and for dynamic initialization in `pruneInterface`,
getting rid of partial initializations in `init`.
I very much considered just removing the protected inheritance again,
but it would add unnecessary code duplication.
Take note, the overriding `insert` function bypasses the Wrapper and directly forwards to the wrapped container.
This is somewhat dirty and could be an issue for anyone inheriting from `Task`.
`add` falls back to `insert` for both structures,
but `add` throws exceptions and does not provide a return value.
`insert` provides standard STL container access.
So far, returning false from the processor function, just skipped further traversing the current child (depth-wise).
Now, traversal is completely aborted, even not traversing the remaining siblings of the current child.
Having a single boolean return value, we cannot distinguish both cases.
We need the new behaviour for 8061945c15bea22e8f8899c987bc28e3542885aa.