Adaptive ROS 2 Node computations and hardware acceleration contributions

Thanks for taking a look @peci1.

The core idea of an adaptive Node is that it should allow to move computations across compute substrates in an adaptive manner and (by default) stateless manner (e.g. going from CPUs to the GPU for an optimized performance, or from the GPU to an FPGA for a more deterministic one, etc).

The approached followed for this first implementation is to create AdaptiveNode class as a container of Components (one for each compute substrate) with a single-threaded executor as an attribute that is used to provide compute cycles to the desired substrate (and only this one). Then, through ROS parameters, one can change which sub-Component gets added to the executor.

For now there’s no ROS Lifecycle capabilities implemented into AdaptiveNode (sub-components may or may not have it) but I’d like to explore that topic in the future (see my comment in here).

Thanks for the input, do you have a better name suggestion for the parameter?