vault backup: 2025-02-03 08:29:48

This commit is contained in:
2025-02-03 08:29:48 +01:00
parent 7909836706
commit ad227f2d69
2018 changed files with 27268 additions and 46 deletions

View File

@@ -0,0 +1,31 @@
Also known as managed Nodes in [[ROS2]]. The [[ROS2 - NAV2 Library|NAV2]] library makes good use of it.
From [ROS2 Design](https://design.ros2.org/articles/node_lifecycle.html):
>A managed life cycle for nodes allows greater control over the state of ROS system. It will allow roslaunch to ensure that all components have been instantiated correctly before it allows any component to begin executing its behaviour. It will also allow nodes to be restarted or replaced on-line.
>The most important concept of this document is that a managed node presents a known interface, executes according to a known life cycle state machine, and otherwise can be considered a black box. This allows freedom to the node developer on how they provide the managed life cycle functionality, while also ensuring that any tools created for managing nodes can work with any compliant node.
There are 4 primary states: *unconfigured, inactive, active, finalized*
There are 7 transitions: *create, configure, cleanup, activate, deactivate, shutdown and destroy*
## States
All nodes start with the **unconfigured** state, which is kind of like an empty state where everything starts but it might also end there
More important is the **inactive** state. its purpose is to breath life into a node. It allows the user to read parameters, add subscriptions and publications and (re)configure it such that it can fulfill its job. This is done while the node is not running. While a node is in this state it will not receive any data from other processes.
## Transition Callbacks
The main functions to implement for a custom node in the lifecycle scheme are:
### onConfigure()
Here the things are implemented that are executed only once in the Node's lifetime, such as obtaining permanent memory buffers and setting up topic publications/subscriptions that do not change.
### onCleanup()
This is the transition function that is called when a Node is being taken out of service (essentially the oposite of *onConfigure()*. Essentially it leaves the node without a state, such that there is no difference between a node that got cleaned up and another that was just created.
### onActivate()
This callback is responsible to implement any final preparations before the node is executing its main purpose. Examples are acquiring resources needed for execution such as access to hardware (it should return fast without a lengthy hardware startup).
### onDeactivate()
This callback should undo anything that *onActivate()* did.
## Management Interface
This is a common interface to allow a managing node to manage the different lifecycle nodes accordingly.
## Managing Node
This is the node that loads the different lifecycle nodes and is responsible to bring them from one state into the next and handle any error they feed back.

View File

@@ -0,0 +1,83 @@
The Pluginlib is a library for [[ROS2]] that allows a very modular development. It is heavily used in the [[ROS2 - NAV2 Library|NAV2]] Library.
From the [pluginlib tutorial]():
>`pluginlib` is a C++ library for loading and unloading plugins from within a ROS package. Plugins are dynamically loadable classes that are loaded from a runtime library (i.e. shared object, dynamically linked library). With pluginlib, you do not have to explicitly link your application against the library containing the classes instead `pluginlib` can open a library containing exported classes at any point without the application having any prior awareness of the library or the header file containing the class definition. Plugins are useful for extending/modifying application behavior without needing the application source code.
Basically it allows to define an abstract base class that defines the interface of the plugin. It defines what functions (`virtual`) need to be overwritten and what variables are there. You can then derive multiple packages with different implementations of this plugin base class which is used by an executor function. Those plugins can then be loaded at runtime without prior knowledge about them because they follow the same structure.
Requirements:
1. Constructor without parameters -> use initialization function instead.
2. Make header available to other classes
1. Add the following snippet to `CMakeLists.txt`:
```cmake
install(
DIRECTORY include/
DESTINATION include
)
...
ament_export_include_directories(
include
)
```
3. In the c++ file where you define your plugins you need to add the following macro at the very end. This creates the plugin instances when the corresponding library is loaded.
```cpp
#include <pluginlib/class_list_macros.hpp>
PLUGINLIB_EXPORT_CLASS(polygon_plugins::Square, polygon_base::RegularPolygon)
PLUGINLIB_EXPORT_CLASS(polygon_plugins::Triangle, polygon_base::RegularPolygon)
```
4. The plugin loader needs some information to find the library and to know what to reference in the libary. Thus an xml-file needs to be written as well as an export line in the package.xml file. With those 2 additions ROS knows everything it needs to know in order to use the plugins. In the following snippets we have the two Plugins: Square and Triangle defined in a plugin.xml file.
```xml
<library path="polygon_plugins">
<class type="polygon_plugins::Square" base_class_type="polygon_base::RegularPolygon">
<description>This is a square plugin.</description>
</class>
<class type="polygon_plugins::Triangle" base_class_type="polygon_base::RegularPolygon">
<description>This is a triangle plugin.</description>
</class>
</library>
```
```cmake
# polygon_base: package with base class
# plugins.xml: relative path to plugin file defined above
pluginlib_export_plugin_description_file(polygon_base plugins.xml)
```
How to use the plugins
The plugins can be used in any package that you want
```cpp
#include <pluginlib/class_loader.hpp>
#include <polygon_base/regular_polygon.hpp>
int main(int argc, char** argv)
{
// To avoid unused parameter warnings
(void) argc;
(void) argv;
pluginlib::ClassLoader<polygon_base::RegularPolygon> poly_loader("polygon_base", "polygon_base::RegularPolygon");
try
{
std::shared_ptr<polygon_base::RegularPolygon> triangle = poly_loader.createSharedInstance("polygon_plugins::Triangle");
triangle->initialize(10.0);
std::shared_ptr<polygon_base::RegularPolygon> square = poly_loader.createSharedInstance("polygon_plugins::Square");
square->initialize(10.0);
printf("Triangle area: %.2f\n", triangle->area());
printf("Square area: %.2f\n", square->area());
}
catch(pluginlib::PluginlibException& ex)
{
printf("The plugin failed to load for some reason. Error: %s\n", ex.what());
}
return 0;
}
```
>Important note: the `polygon_base` package in which this node is defined does NOT depend on the `polygon_plugins` class. The plugins will be loaded dynamically without any dependency needing to be declared. Furthermore, were instantiating the classes with hardcoded plugin names, but you can also do so dynamically with parameters, etc.

View File

@@ -0,0 +1,6 @@
- [ ] #todo/b Write overview of what ros2 does in my own words. Advantages / disadvantages
# Build System
The ROS2 [build system](https://docs.ros.org/en/humble/Concepts/Advanced/About-Build-System.html)is a challenging part, because packages written in different languages such as [[C++]] or [[Python]] need to be built together in order to form a unit.
To achieve this ROS2 relies heavily on the [[Colcon]] build system, which under the hood uses [[CMake]] for C++ packages and setuptools for Python. In order to define dependencies across the different packages and languages, ROS2 packages always contain a `package.xml` file also known as manifest file that contains essential metadata about the package, such as dependencies and others.