Navigator.h
Go to the documentation of this file.
1/**
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @author Fabian Reister ( fabian dot reister at kit dot edu )
17 * @author Christian R. G. Dreher ( c dot dreher at kit dot edu )
18 * @date 2021
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#pragma once
24
25#include <atomic>
26#include <mutex>
27#include <optional>
28#include <string>
29#include <vector>
30
31#include <Eigen/Core>
32
36
55
57#include <SemanticObjectRelations/Shapes/Shape.h>
58
60{
61
63 {
65 }
66
67 // Allow global path to be subdivided into segments that are executed independently
68 // each segment can be executed by the global or local planner
70 {
71 // A segment from index [s,t)
73 {
74 std::size_t s;
75 std::size_t t;
77 };
78
80 std::vector<Subdivision> subdivision;
81 std::size_t currentSegment;
83
84 bool useLocalPlanner(bool hasLocalPlanner);
87
89 };
90
91 class Navigator : virtual public core::NavigatorInterface
92 {
93
94 public:
95 struct Config
96 {
97 struct General
98 {
99 struct
100 {
101 int replanningUpdatePeriod{100}; // [ms]
103
104 // Whether to subdivide the global trajectory into segments that are executed independently.
105 // Requires local planner
106
107 // The global plan is divided into segments that can be executed by the local planner and those
108 // where the global planner should be used:
109 // - a part of the trajectory is ineligible for the local planner if the corresponding costmap
110 // entry has a value less than the localPlannerCostmapThreshold parameter
111 // Then, each segment of continuous trajectory points where the global planner should be used is expanded
112 // by globalPlanExpansionDistance into both directions.
113 // Then, each segment of continuous trajectory points where the local planner should be used that is less
114 // than minSegmentDistance long will be remove and joined with the neighboring globalPlanner segments.
115 struct
116 {
117 bool enable{false};
118 // the minimum distance in the costmap to enable the local planner [mm]
120 float globalPlanExpansionDistance = 300; // [mm]
121 float minSegmentDistance = 500; // [mm]
123
124 // numer of seconds to wait before replanning alternatives after all
125 // alternatives where impossible [s]
127
128 // If the safety guard limits the platform velocity close to zero for a
129 // sustained period, the robot is considered blocked (e.g. by an obstacle
130 // that the global plan does not account for) and the global planner is run
131 // again towards the current goal.
132 struct
133 {
134 bool enabled = true;
135 // limits below which the respective axis counts as blocked
136 float linearLimit = 1.F; // [mm/s]
137 float angularLimit = 0.01F; // [rad/s]
138 // how long the robot has to stay blocked before replanning [s]
141
142 // Which platform's drive parameters the TOPP-RA parametrization uses: the
143 // suffix selecting `config/platform/PlatformDynamics<Platform>.json` inside the
144 // `armarx_navigation` package, resolved by `algorithms::DriveParamsPath`. Same
145 // convention as the analysis application's `--robot`, so a platform is named
146 // once and the navigator, the analysis tool and the benchmark all agree.
147 //
148 // Spelled as the rest of the codebase does: `Armar7`, `Armar6`, `ArmarDE`.
149 // Set `platformDynamicsEnabled` to false to disable TOPP-RA entirely.
150 std::string platform{"Armar7"};
151
152 // Whether to read drive parameters at all. False means TOPP-RA is unavailable
153 // and the stack falls back to ramping -- the escape hatch for a platform that
154 // has no config file yet.
156
157 // Write a record of every parametrized navigation request, for offline
158 // analysis with `plot-navigation-request`. Off by default -- this is a
159 // debugging aid and it writes a file per request.
162 "/tmp/navigation-request-parametrization.json"};
163 };
164
167
169 };
170
182
183 Navigator(const Config& config, const InjectedServices& services);
184
185 void moveTo(const std::vector<core::Pose>& waypoints,
186 core::NavigationFrame navigationFrame) override;
187
188 void moveToAlternatives(const std::vector<core::TargetAlternative>& targets,
189 core::NavigationFrame navigationFrame) override;
190
191 void update(const std::vector<core::Pose>& waypoints,
192 core::NavigationFrame navigationFrame) override;
193
194
195 void moveTo(const std::vector<client::WaypointTarget>& targets,
196 core::NavigationFrame navigationFrame) override;
197
198 void moveTowards(const core::Direction& direction,
199 core::NavigationFrame navigationFrame) override;
200
201 void moveToLocation(const std::string& location,
202 const std::optional<std::string>& providerName) override;
203
204 void setVelocityFactor(float velocityFactor) override;
205
206 void pause() override;
207
208 void resume() override;
209
210 bool isPaused() const noexcept override;
211
212 void stop() override;
213
214 bool isStopped() const noexcept override;
215
216 // Non-API
217 public:
218 Navigator(Navigator&& other) noexcept;
219
220 ~Navigator() override;
221
222 private:
223 using GraphPath = std::vector<semrel::ShapeID>;
224
225 void moveToAbsolute(const std::vector<core::Pose>& waypoints, bool = true);
226 void moveTowardsAbsolute(const core::Direction& direction);
227
228 void updateAbsolute(const std::vector<core::Pose>& waypoints);
229
230 void moveToAbsoluteAlternatives(const std::vector<core::TargetAlternative>& targets);
231 bool setupTargetAlternatives();
232
233 void setupGlobalPlanSubvidision();
234
235 // return true iff globalPath was already executed fully
236 bool startGlobalPathSegment(bool incrementSegment, bool rampFromCurrentVelocity);
237
238 void run();
239
240 void updateScene(bool fullUpdate = false);
241
242 void checkGlobalPathAlternatives();
243 bool verifyGlobalPathPossible(const core::GlobalTrajectory& plan);
244
245 // monitors the safety guard limits and re-runs the global planner if the robot
246 // has been blocked (limits near zero) for a sustained period
247 void checkRobotBlocked(const safety_guard::SafetyGuardResult& result);
248
249 std::optional<local_planning::LocalPlannerResult> updateLocalPlanner();
250 void updateExecutor(const std::optional<local_planning::LocalPlannerResult>& localPlan);
251 void updateExecutor(const core::GlobalTrajectory& globalTrajectory);
252 void updateIntrospector(const std::optional<local_planning::LocalPlannerResult>& localPlan);
253
254 void updateMonitor();
255
256 safety_guard::SafetyGuardResult updateSafetyGuard();
257
258 // const core::Trajectory& currentTrajectory() const;
259 // bool isStackResultValid() const noexcept;
260
261 void stopAllThreads();
262
263 void startStack();
264
265 // helper methods
266 void setGraphEdgeCosts(core::Graph& graph) const;
267 GraphBuilder convertToGraph(const std::vector<client::WaypointTarget>& targets) const;
268
269 core::GlobalTrajectory convertToTrajectory(const GraphPath& shortestPath,
270 const core::Graph& graph) const;
271
272 core::Pose resolveGraphVertex(const core::Graph::ConstVertex& vertex) const;
273
274 /// Parametrize `trajectory` in place, degrading to ramping rather than failing.
275 ///
276 /// Also emits the per-request record when `general.parametrizationDump` is set.
277 void applyParametrization(core::GlobalTrajectory& trajectory, float startVelocity);
278
279 /**
280 * @brief Re-anchor the running trajectory at the robot's pose after an emergency stop.
281 *
282 * A `GlobalTrajectory` assigns a velocity to a *position*. The robot stands still where
283 * the profile it was executing assigns cruise speed, so resuming on that trajectory
284 * steps the commanded twist from zero and the device ramp answers at its own maximum --
285 * far above the acceleration the path was parametrized for. Parametrizing the remainder
286 * *from here* puts the profile's `boundaryVelocity` floor at the robot instead, and it
287 * ramps up under the planned bound.
288 *
289 * Leaves `globalPlan` untouched: only the trajectory handed to the executor is replaced,
290 * so segment bookkeeping and the goal monitor keep referring to the original plan.
291 */
292 void resumeAfterEmergencyStop();
293
294 bool hasLocalPlanner() const noexcept;
295 bool hasSafetyGuard() const;
296
297 Config config;
298
300
301 /**
302 * @brief Assigns the velocities along a freshly started path segment.
303 *
304 * Which variant this is comes from `GeneralConfig::parametrization`; the default,
305 * `Ramping`, is what this class used to do inline.
306 */
307 /// The drive parameters TOPP-RA was built from, when it could be built at all.
308 /// Kept so the per-request record can report the bounds that shaped the profile.
309 /// Declared first: the initialisers below read it.
310 std::optional<algorithms::Toppra::DriveParams> driveParams;
311
312 /// What the parametrization actually is, which is not always what was configured:
313 /// TOPP-RA degrades to ramping when it is unavailable or cannot be initialised.
314 /// Declared before `parametrization` so it is written by its initialiser.
315 core::TrajectoryParametrization parametrizationMode{
317
319
320 /// Always available, for the per-request fallback when a solve fails.
322
323 std::atomic_bool executorEnabled = true;
324 std::atomic_bool shouldRun = false;
325
326 PeriodicTask<Navigator>::pointer_type runningTask = nullptr;
327
328 std::optional<GoalReachedMonitor> goalReachedMonitor;
329
330 std::vector<core::TargetAlternative> targetAlternatives;
331 std::optional<armarx::DateTime> lastAllAlternativesImpossible;
332
333 // timestamp since when the robot is continuously blocked by the safety guard
334 // (nullopt while the robot is able to move)
335 std::optional<armarx::DateTime> blockedSince;
336
337 std::optional<GlobalPathSubdivision> globalPlan;
338 std::optional<local_planning::LocalPlannerResult> localPlan;
339
340 using Waypoints = std::vector<core::Pose>;
341
342 std::mutex globalPlanningRequestMtx;
343 std::optional<Waypoints> globalPlanningRequest;
344
345 std::atomic<float> velocityFactor = 1.F;
346
347 std::mutex updateLocalPlannerMtx;
348
349 std::mutex runMtx;
350
351 std::mutex runningTaskMtx;
352 };
353
354} // namespace armarx::navigation::server
Brief description of class DebugObserverHelper.
IceUtil::Handle< PeriodicTask< T > > pointer_type
Shared pointer type for convenience.
The Pose class.
Definition Pose.h:243
Navigator interface for PointGoal navigation (with waypoints) and relative movement.
A publisher the server navigator will use to notify others about events.
An executer the server navigator will use to send its control commands to.
void moveToAlternatives(const std::vector< core::TargetAlternative > &targets, core::NavigationFrame navigationFrame) override
void moveTowards(const core::Direction &direction, core::NavigationFrame navigationFrame) override
void update(const std::vector< core::Pose > &waypoints, core::NavigationFrame navigationFrame) override
Navigator(const Config &config, const InjectedServices &services)
void setVelocityFactor(float velocityFactor) override
void moveToLocation(const std::string &location, const std::optional< std::string > &providerName) override
bool isPaused() const noexcept override
void moveTo(const std::vector< core::Pose > &waypoints, core::NavigationFrame navigationFrame) override
bool isStopped() const noexcept override
Brief description of class targets.
Definition targets.h:39
This file is part of ArmarX.
std::shared_ptr< TrajectoryParametrization > TrajectoryParametrizationPtr
This file is part of ArmarX.
This file is part of ArmarX.
Eigen::Vector3f Direction
Definition basic_types.h:39
@ Ramping
Ramp down at the start, the goal and every corner. The stack's historical behaviour.
This file is part of ArmarX.
Definition Visu.h:48
This file is part of ArmarX.
Definition fwd.h:36
This file is part of ArmarX.
Definition constants.cpp:4
This file is part of ArmarX.
Definition fwd.h:55
This file is part of ArmarX.
core::GoalReachedConfig GoalReachedMonitorConfig
boost::subgraph< CloudGraph > Graph
Definition Common.h:58
This file is part of ArmarX.
GlobalPathSubdivision(const global_planning::GlobalPlannerResult &globalPlan)
Definition Navigator.cpp:72
global_planning::GlobalPlannerResult plan
Definition Navigator.h:79
const core::GlobalTrajectory & currentGlobalSegment() const
Definition Navigator.cpp:94
struct armarx::navigation::server::Navigator::Config::General::@344222376127045226032312110301072212057201156307 subdivision
struct armarx::navigation::server::Navigator::Config::General::@011375156264107156015013016164051115143104037154 blockedReplanning
struct armarx::navigation::server::Navigator::Config::General::@344207070160307005105315017266073311106207125254 tasks
GoalReachedMonitorConfig goalReachedConfig
Definition Navigator.h:168
scene_provider::SceneProviderInterface * sceneProvider
Definition Navigator.h:180