|
3 | 3 | Core Design and Architecture |
4 | 4 | ############################ |
5 | 5 |
|
6 | | -EasyNav is designed around **modularity**, **real-time performance**, and **extensibility**. Its architecture separates concerns clearly, making it both easy to adapt and efficient to run. |
| 6 | +**EasyNav** is designed with three core principles in mind: modularity, real-time performance, and extensibility. Its architecture separates concerns into well-defined components, making it both easy to adapt and efficient to execute. |
7 | 7 |
|
8 | | - |
9 | | - |
10 | | -.. figure:: ../images/easynav_simple_design.png |
11 | | - :align: center |
12 | | - :width: 90% |
13 | | - :alt: EasyNav Core Design |
14 | | - |
15 | | - Figure: Core architecture of EasyNav. |
16 | | - |
17 | | - |
18 | | - |
19 | | -.. figure:: ../images/easynav_cycle.png |
20 | | - :align: center |
21 | | - :width: 90% |
22 | | - :alt: EasyNav Cycles view |
23 | | - |
24 | | - Figure: Ral-Time and no real-Time cycle accesing to the NavState. |
25 | | - |
26 | | - |
27 | | - |
28 | | -.. figure:: ../images/easynav_design.png |
29 | | - :align: center |
30 | | - :width: 90% |
31 | | - :alt: EasyNav Core Design |
32 | | - |
33 | | - Figure: Core architecture of EasyNav with real-time and non-real-time flows. |
34 | | - |
35 | | - |
36 | | - |
37 | | -.. figure:: ../images/easynav_cycle.png |
| 8 | +.. image:: ../images/easynav_simple_design.png |
38 | 9 | :align: center |
39 | | - :width: 90% |
40 | | - :alt: EasyNav Cycles view |
41 | | - |
42 | | - Figure: Ral-Time and no real-Time cycle accesing to the NavState. |
43 | | - |
44 | | - |
45 | | -Main Concepts |
46 | | -************* |
| 10 | + :alt: EasyNav architecture diagram |
47 | 11 |
|
48 | | -At the heart of EasyNav lies a **EasyNav Node**, responsible for orchestrating the entire navigation process. It coordinates multiple subordinate nodes and delegates the actual implementation of functionality to plugins. |
| 12 | +The figure above illustrates the general architecture of EasyNav. |
49 | 13 |
|
50 | | -These subordinate modules include: |
| 14 | +EasyNav runs within a single process that hosts a ROS 2 **Lifecycle Node** called ``SystemNode``, which coordinates the entire navigation system. Through composition, ``SystemNode`` includes several other ROS 2 Lifecycle Nodes, each responsible for a specific function in the navigation pipeline: |
51 | 15 |
|
52 | | -- **Sensor Manager**: Acquires and integrates raw sensor data into the system. |
53 | | -- **Maps Manager**: Maintains maps. |
54 | | -- **Localizer**: Estimates the robot pose. |
55 | | -- **Planner**: Generates global paths. |
56 | | -- **Controller**: Translates paths into velocity commands. |
| 16 | +- **Sensors Node**: This node collects and preprocesses all sensory input used by the navigation system. It supports multiple types of sensors, grouped by modality (e.g., laser scans, point clouds). |
| 17 | + |
| 18 | +- **MapsManager Node**: Responsible for how the environment is represented. It supports multiple plugins that define the actual data structure for the map: costmaps, gridmaps, octomaps, pointclouds, and more. The plugin selection is configurable depending on the application or use case. |
57 | 19 |
|
58 | | -Each of these (except the Sensor Manager) is implemented as a **plugin** and loaded dynamically based on the configuration file. This enables the user to choose or create alternative implementations as needed. |
| 20 | +- **Localizer Node**: Estimates the robot's position within the map. It uses a localization plugin that must be compatible with the type of environment representation used by the MapsManager. |
59 | 21 |
|
60 | | -NavState |
61 | | -******** |
| 22 | +- **Planner Node**: Computes a path from the robot’s current position to its goal (as managed by the GoalManager). The selected plugin determines the planning algorithm used. |
62 | 23 |
|
63 | | -All modules operate over a central data structure called **NavState**, which contains the current state of the system: |
| 24 | +- **Controller Node**: Generates velocity commands to follow the planned path. Its functionality is encapsulated in a plugin, which outputs either ``Twist`` or ``TwistStamped`` messages depending on configuration. |
64 | 25 |
|
65 | | -- Sensor perceptions |
66 | | -- Robot pose |
67 | | -- Dynamic and static maps |
68 | | -- Planned path |
69 | | -- Velocity commands |
70 | 26 |
|
71 | | -Each plugin reads from the NavState **in read-only mode**. Only the main node is allowed to update it. This guarantees data consistency and avoids race conditions during concurrent execution. |
| 27 | +NavState: The Shared Blackboard |
| 28 | +------------------------------- |
72 | 29 |
|
73 | | -Execution Model |
74 | | -*************** |
| 30 | +A key architectural component of EasyNav is the **NavState**, a shared *blackboard* that holds all the internal state information required by the navigation system. |
75 | 31 |
|
76 | | -The execution model is built around two parallel loops: |
| 32 | +Each module in EasyNav—such as the Localizer, Planner, or Controller—reads its inputs from the NavState and writes its outputs back to it. This central structure replaces the need for internal ROS 2 communications between modules. |
77 | 33 |
|
78 | | -- **Real-time loop (RT)**: High-frequency operations, typically 10–100 Hz. Prioritizes minimal latency. |
79 | | -- **Non-real-time loop (NRT)**: Lower-frequency operations for background or heavy processing tasks. |
| 34 | +The motivation behind using a shared blackboard is to: |
80 | 35 |
|
81 | | -Each plugin specifies its desired execution frequencies for both loops. If invoked prematurely, it simply returns, ensuring no over-execution or priority inversion occurs. |
| 36 | +- **Avoid ROS 2 topic-based communication internally**, reducing unnecessary overhead and complexity. |
| 37 | +- **Improve real-time determinism**, as data access becomes local and predictable. |
| 38 | +- **Simplify integration and debugging**, by consolidating all system-relevant information in a single place. |
82 | 39 |
|
83 | | -Unlike typical ROS 2 systems, EasyNav **avoids using ROS timers** for execution. Instead, the main node directly calls each plugin, improving determinism and lowering latency. |
| 40 | +The NavState contains data such as: |
84 | 41 |
|
85 | | -In the RT loop, a plugin can **propagate an execution trigger** to the next module when new data is available. For example, when the maps manager updates a dynamic map, it can immediately notify the localizer to react, followed by the planner and controller. This reduces total response time from perception to action. |
| 42 | +- the robot's estimated pose, |
| 43 | +- the current navigation goal, |
| 44 | +- planned paths, |
| 45 | +- velocity commands, |
| 46 | +- perception data, |
| 47 | +- and diagnostic or meta-state information. |
86 | 48 |
|
| 49 | +By inspecting the NavState at runtime, developers gain full visibility into the internal state of EasyNav at any given moment. This approach not only improves transparency, but also enables advanced tooling for monitoring, introspection, and explainability. |
87 | 50 |
|
| 51 | +Future versions of EasyNav may include graphical or CLI-based tools to explore and trace the NavState over time. |
88 | 52 |
|
89 | | -Plugin Types |
90 | | -************ |
91 | 53 |
|
92 | | -Each subordinate module loads one or more plugins. These are implemented as classes derived from a common interface and declared via ROS 2 pluginlib. |
| 54 | +Real-Time Execution Model |
| 55 | +-------------------------- |
93 | 56 |
|
94 | | -The most common plugin types are: |
| 57 | +Another key feature of EasyNav is its emphasis on **real-time performance**. The navigation system is designed to react with strict timing constraints, minimizing latency from perception to action. |
95 | 58 |
|
96 | | -- `MapsManagerMethodBase` |
97 | | -- `LocalizerMethodBase` |
98 | | -- `PlannerMethodBase` |
99 | | -- `ControllerMethodBase` |
| 59 | +To achieve this, EasyNav separates execution into two distinct control loops: |
100 | 60 |
|
101 | | -Each plugin must implement: |
| 61 | +- **Real-Time Cycle** |
| 62 | + This loop is optimized for minimal end-to-end latency. Its goal is to process new sensor data and update the robot’s motion commands as quickly as possible. It includes: |
| 63 | + |
| 64 | + - perception input processing, |
| 65 | + - pose prediction via odometry, |
| 66 | + - and velocity command generation (e.g., ``Twist`` or ``TwistStamped``). |
102 | 67 |
|
103 | | -- `internal_update_rt()` – for fast real-time updates |
104 | | -- `internal_update()` – for slower, background updates |
105 | | -- Configuration parameters for frequency, QoS, and logic |
106 | | - |
107 | | -Refer to the source code or stack-specific documentation for implementation details. |
108 | | - |
109 | | -Summary |
110 | | -******* |
111 | | - |
112 | | -The EasyNav core: |
113 | | - |
114 | | -- Offers a **minimal and efficient** architecture for robot navigation. |
115 | | -- Enables **runtime modularity** through plugins. |
116 | | -- Is optimized for **real-time response** and **deterministic execution**. |
117 | | -- Provides a unified access point to all navigation data via `NavState`. |
118 | | - |
119 | | -For details on each plugin type and examples, see the :ref:`stacks <stacks>` section. |
| 68 | +- **Non-Real-Time Cycle** |
| 69 | + This loop handles operations where occasional execution delays are tolerable. Tasks in this loop include: |
| 70 | + |
| 71 | + - map updates, |
| 72 | + - localization corrections based on perception (e.g., particle filter resampling), |
| 73 | + - and path planning. |
120 | 74 |
|
| 75 | +.. image:: ../images/easynav_design.png |
| 76 | + :align: center |
| 77 | + :alt: EasyNav architecture diagram with the Real-Time and Non-Real-Time cycles. |
| 78 | + |
| 79 | + |
| 80 | +Each EasyNav module is configured with a frequency for both real-time and non-real-time cycles. These are specified in the parameters as `rt_freq` and `freq`, respectively. |
| 81 | + |
| 82 | +Additionally, when new perception data is received, the real-time cycle is **triggered immediately**, allowing the system to respond as fast as possible and minimize perception-to-action latency. |
| 83 | + |
| 84 | +This dual-cycle model balances **responsiveness** with **computational stability**, ensuring critical actions happen with deterministic timing while less urgent tasks are scheduled opportunistically. |
| 85 | + |
| 86 | + |
| 87 | +Plugin Configuration |
| 88 | +--------------------- |
| 89 | + |
| 90 | +Let us examine the parameter file used in the *Getting Started* section. Each node loads its corresponding plugin by name. The following example shows how plugins are declared for each module: |
| 91 | + |
| 92 | +.. code-block:: yaml |
| 93 | +
|
| 94 | + controller_node: |
| 95 | + ros__parameters: |
| 96 | + use_sim_time: true |
| 97 | + controller_types: [simple] |
| 98 | + simple: |
| 99 | + rt_freq: 30.0 |
| 100 | + plugin: easynav_simple_controller/SimpleController |
| 101 | + max_linear_speed: 0.6 |
| 102 | + max_angular_speed: 1.0 |
| 103 | + look_ahead_dist: 0.2 |
| 104 | + k_rot: 0.5 |
| 105 | +
|
| 106 | + localizer_node: |
| 107 | + ros__parameters: |
| 108 | + use_sim_time: true |
| 109 | + localizer_types: [simple] |
| 110 | + simple: |
| 111 | + rt_freq: 50.0 |
| 112 | + freq: 5.0 |
| 113 | + reseed_freq: 1.0 |
| 114 | + plugin: easynav_simple_localizer/AMCLLocalizer |
| 115 | + num_particles: 100 |
| 116 | + noise_translation: 0.05 |
| 117 | + noise_rotation: 0.1 |
| 118 | + noise_translation_to_rotation: 0.1 |
| 119 | + initial_pose: |
| 120 | + x: 0.0 |
| 121 | + y: 0.0 |
| 122 | + yaw: 0.0 |
| 123 | + std_dev_xy: 0.1 |
| 124 | + std_dev_yaw: 0.01 |
| 125 | +
|
| 126 | + maps_manager_node: |
| 127 | + ros__parameters: |
| 128 | + use_sim_time: true |
| 129 | + map_types: [simple] |
| 130 | + simple: |
| 131 | + freq: 10.0 |
| 132 | + plugin: easynav_simple_maps_manager/SimpleMapsManager |
| 133 | + package: easynav_indoor_testcase |
| 134 | + map_path_file: maps/home.map |
| 135 | +
|
| 136 | + planner_node: |
| 137 | + ros__parameters: |
| 138 | + use_sim_time: true |
| 139 | + planner_types: [simple] |
| 140 | + simple: |
| 141 | + freq: 0.5 |
| 142 | + plugin: easynav_simple_planner/SimplePlanner |
| 143 | + robot_radius: 0.3 |
| 144 | +
|
| 145 | + sensors_node: |
| 146 | + ros__parameters: |
| 147 | + use_sim_time: true |
| 148 | + forget_time: 0.5 |
| 149 | + sensors: [laser1] |
| 150 | + perception_default_frame: odom |
| 151 | + laser1: |
| 152 | + topic: /scan_raw |
| 153 | + type: sensor_msgs/msg/LaserScan |
| 154 | + group: points |
| 155 | +
|
| 156 | + system_node: |
| 157 | + ros__parameters: |
| 158 | + use_sim_time: true |
| 159 | + position_tolerance: 0.1 |
| 160 | + angle_tolerance: 0.05 |
| 161 | +
|
| 162 | +Each node declares one or more plugin types (e.g., `simple`) that can be dynamically selected. The plugin name (e.g., `easynav_simple_controller/SimpleController`) must match the name registered in the plugin system. |
| 163 | + |
| 164 | +This design allows for easy experimentation with different algorithms or system behaviors simply by modifying configuration files—without changing any source code. |
| 165 | + |
| 166 | + |
| 167 | +Some applications may not require a full navigation pipeline. For example, systems focused on teleoperation, behavior testing, or hardware validation might not need environment representation, localization, or path planning. |
| 168 | + |
| 169 | +To support such minimal setups, EasyNav provides a **Dummy plugin** for each core module. These plugins implement the required interfaces but do not perform any real computation. This allows the system to run with minimal overhead while remaining fully compatible with the rest of the EasyNav infrastructure. |
| 170 | + |
| 171 | +Below is an example configuration using dummy plugins for all components, effectively creating a **Dummy Navigation System**: |
| 172 | + |
| 173 | +.. code-block:: yaml |
| 174 | +
|
| 175 | + controller_node: |
| 176 | + ros__parameters: |
| 177 | + use_sim_time: true |
| 178 | + controller_types: [dummy] |
| 179 | + dummy: |
| 180 | + rt_freq: 30.0 |
| 181 | + plugin: easynav_controller/DummyController |
| 182 | + cycle_time_nort: 0.01 |
| 183 | + cycle_time_rt: 0.001 |
| 184 | +
|
| 185 | + localizer_node: |
| 186 | + ros__parameters: |
| 187 | + use_sim_time: true |
| 188 | + localizer_types: [dummy] |
| 189 | + dummy: |
| 190 | + rt_freq: 50.0 |
| 191 | + freq: 5.0 |
| 192 | + reseed_freq: 0.1 |
| 193 | + plugin: easynav_localizer/DummyLocalizer |
| 194 | + cycle_time_nort: 0.01 |
| 195 | + cycle_time_rt: 0.001 |
| 196 | +
|
| 197 | + maps_manager_node: |
| 198 | + ros__parameters: |
| 199 | + use_sim_time: true |
| 200 | + map_types: [dummy] |
| 201 | + dummy: |
| 202 | + freq: 10.0 |
| 203 | + plugin: easynav_maps_manager/DummyMapsManager |
| 204 | + cycle_time_nort: 0.1 |
| 205 | + cycle_time_rt: 0.001 |
| 206 | +
|
| 207 | + planner_node: |
| 208 | + ros__parameters: |
| 209 | + use_sim_time: true |
| 210 | + planner_types: [dummy] |
| 211 | + dummy: |
| 212 | + freq: 1.0 |
| 213 | + plugin: easynav_planner/DummyPlanner |
| 214 | + cycle_time_nort: 0.2 |
| 215 | + cycle_time_rt: 0.001 |
| 216 | +
|
| 217 | + sensors_node: |
| 218 | + ros__parameters: |
| 219 | + use_sim_time: true |
| 220 | + forget_time: 0.5 |
| 221 | +
|
| 222 | + system_node: |
| 223 | + ros__parameters: |
| 224 | + use_sim_time: true |
| 225 | + position_tolerance: 0.1 |
| 226 | + angle_tolerance: 0.05 |
| 227 | +
|
| 228 | +This configuration is especially useful for testing system integration, message flow, and user interfaces without requiring sensor data or a simulated robot. You can later replace dummy plugins with functional ones as needed. |
0 commit comments