29 #include <experimental/memory>
38 #include <Eigen/Geometry>
40 #include <opencv2/core/eigen.hpp>
42 #include <Ice/Current.h>
44 #include <SimoxUtility/color/ColorMap.h>
45 #include <SimoxUtility/color/cmaps/colormaps.h>
59 #include <RobotAPI/interface/ArViz/Elements.h>
60 #include <RobotAPI/interface/aron/Aron.h>
64 #include <armarx/navigation/client/ice/NavigatorInterface.h>
91 std::vector<core::Pose>
92 convert(
const std::vector<Eigen::Matrix4f>& wps)
94 std::vector<core::Pose> p;
95 p.reserve(wps.size());
98 std::back_inserter(p),
99 [](
const auto& p) { return core::Pose(p); });
120 addPlugin(laserScannerFeaturesReaderPlugin);
125 ¶meterizationReaderPlugin->get(), ¶meterizationWriterPlugin->get());
151 .costmapReader = &costmapReaderPlugin->get(),
152 .virtualRobotReader = &virtualRobotReaderPlugin->get(),
153 .humanReader = &humanReaderPlugin->get(),
154 .laserScannerFeaturesReader = &laserScannerFeaturesReaderPlugin->get(),
159 sceneProvider.emplace(srv, params.sceneCfg);
166 if (not params.disableExecutor)
174 .rtUnitDynamicallyLoadLibraries = params.rtUnitDynamicallyLoadLibraries});
185 navRemoteGui.emplace(remoteGui, *
this);
186 navRemoteGui->enable();
190 ARMARX_INFO <<
"Initialized. Will now respond to navigation requests.";
199 const bool isAnyNavigatorRunning = std::any_of(navigators.begin(),
201 [](
const auto& p) ->
bool
203 const server::Navigator& navigator =
206 return not navigator.isStopped();
210 if (isAnyNavigatorRunning)
213 <<
"A navigator was running when the component got disconnected. Will try to stop "
214 "as much as possible but expect something to be broken now.";
219 navRemoteGui->disable();
220 navRemoteGui.reset();
222 sceneProvider.reset();
224 introspector.reset();
253 const std::string& callerId,
258 ARMARX_INFO <<
"Creating config for caller '" << callerId <<
"'";
264 sceneProvider->scene(),
274 memoryIntrospectors.emplace_back(
275 std::make_unique<server::MemoryIntrospector>(resultsWriterPlugin->get(), callerId));
278 memoryPublishers.emplace(
280 std::make_unique<server::MemoryPublisher>(
281 &resultsWriterPlugin->get(), &eventsWriterPlugin->get(), callerId));
284 if (executor.has_value())
286 executorPtr = &executor.value();
290 navigators.erase(callerId);
292 std::piecewise_construct,
293 std::forward_as_tuple(callerId),
294 std::forward_as_tuple(
296 .general = params.navigatorGeneralConfig,
297 .goalReachedConfig = params.navigatorGoalReachedConfig},
300 .publisher = memoryPublishers.at(callerId).get(),
301 .introspector = introspector.has_value() ? &(introspector.value()) :
nullptr,
304 sceneProvider.has_value() ? &sceneProvider.value() :
nullptr}));
309 const std::string& navigationMode,
310 const std::string& callerId,
315 ARMARX_INFO <<
"moveTo() requested by caller '" << callerId <<
"' with navigation mode `"
316 << navigationMode <<
"`.";
318 <<
"Navigator config for caller `" << callerId <<
"` not registered!";
322 navigators.at(callerId).moveTo(
convert(waypoints),
331 <<
"Movement will be paused.";
339 const std::string& navigationMode,
340 const std::string& callerId,
341 const Ice::Current& )
345 ARMARX_INFO <<
"updateMoveTo() requested by caller '" << callerId <<
"'";
347 <<
"Navigator config for caller `" << callerId <<
"` not registered!";
349 const auto checkIsActiveNavigator = [&](
const std::string& callerId)
352 if (not activeNavigatorCallerId.has_value())
358 return activeNavigatorCallerId == callerId;
362 <<
"The navigator with id `" << callerId <<
"` is not active!";
364 navigators.at(callerId).update(
convert(waypoints),
370 const std::string& navigationMode,
371 const std::string& callerId,
372 const Ice::Current&
c)
378 const std::vector<client::WaypointTarget> wps =
client::defrost(waypoints);
381 <<
"Navigator config for caller `" << callerId <<
"` not registered!";
388 const std::string& callerId,
389 const Ice::Current&
c)
392 ARMARX_INFO <<
"MoveToLocation `" << location <<
"` requested by caller '" << callerId
396 <<
"Navigator config for caller `" << callerId <<
"` not registered!";
398 navigators.at(callerId).moveToLocation(location);
403 const std::string& navigationMode,
404 const std::string& callerId,
409 ARMARX_INFO <<
"MoveTowards requested by caller '" << callerId <<
"'";
412 <<
"Navigator config for caller `" << callerId <<
"` not registered!";
414 navigators.at(callerId).moveTowards(direction,
419 const std::string& callerId,
424 <<
"Navigator config for caller `" << callerId <<
"` not registered!";
425 navigators.at(callerId).setVelocityFactor(velocityFactor);
432 <<
"Navigator config for caller `" << configId <<
"` not registered!";
433 navigators.at(configId).pause();
441 <<
"Navigator config for caller `" << configId <<
"` not registered!";
442 navigators.at(configId).resume();
451 <<
"Navigator config for caller `" << configId <<
"` not registered!";
452 navigators.at(configId).stop();
457 memoryPublishers.at(configId)->userAbortTriggered(event);
472 for (
auto& [_, navigator] : navigators)
479 ARMARX_INFO <<
"Trying to emit memory event `UserAbortTriggered`";
485 for (
auto& [callerId, memoryPublisher] : memoryPublishers)
487 memoryPublisher->userAbortTriggered(event);
497 <<
"Navigator config for caller `" << configId <<
"` not registered!";
498 return navigators.at(configId).isPaused();
505 return sceneProvider->scene();
513 <<
"Navigator config for caller `" << configId <<
"` not registered!";
514 return navigators.at(configId).isStopped();
531 def->component(remoteGui,
"RemoteGuiProvider");
536 def->optional(params.occupiedGridThreshold,
537 "p.occupancy_grid.occopied_threshold",
538 "Threshold for each cell to be considered occupied. Increase this value to "
541 def->optional(params.disableExecutor,
543 "If the executor is disabled, the navigator will only plan the trajectory "
544 "but won't execute it.");
546 def->required(params.sceneCfg.robotName,
"p.scene.robotName");
547 def->optional(params.sceneCfg.staticCostmapProviderName,
548 "p.scene.staticCostmapProviderName");
549 def->optional(params.sceneCfg.staticCostmapName,
"p.scene.staticCostmapName");
550 def->optional(params.sceneCfg.humanProviderName,
"p.scene.humanProviderName");
551 def->optional(params.sceneCfg.laserScannerFeaturesProviderName,
552 "p.scene.laserScannerFeaturesProviderName");
554 def->optional(params.rtUnitDynamicallyLoadLibraries,
555 "p.rtUnitDynamicallyLoadLibraries",
556 "If enabled, the controller library will automatically be loaded in the "
557 "RobotUnit. If disabled (desired), you have to make sure that the controller "
558 "library is listed in the RobotUnit's property `LoadLibraries`");
561 def->optional(params.navigatorGeneralConfig.tasks.replanningUpdatePeriod,
562 "p.navigator.general.replanningPeriod");
564 def->optional(params.navigatorGoalReachedConfig.posTh,
"p.navigator.goalReached.posTh");
565 def->optional(params.navigatorGoalReachedConfig.oriTh,
"p.navigator.goalReached.oriTh");
566 def->optional(params.navigatorGoalReachedConfig.linearVelTh,
567 "p.navigator.goalReached.linearVelTh");
568 def->optional(params.navigatorGoalReachedConfig.angularVelTh,
569 "p.navigator.goalReached.angularVelTh");
570 def->optional(params.navigatorGoalReachedConfig.filterCount,
571 "p.navigator.goalReached.filterCount");
579 const auto cmap = simox::color::cmaps::viridis();
580 const float vmax = costmap.
getGrid().array().maxCoeff();
584 const auto color = cmap.at(
distance, 0.
F, vmax);
585 return {color.a, color.r, color.g, color.b};
588 auto layer = arviz.
layer(
"costmap_" + name);
590 const std::int64_t cols = costmap.
getGrid().cols();
591 const std::int64_t rows = costmap.
getGrid().rows();
595 std::vector<std::vector<Eigen::Vector3f>> vertices;
596 std::vector<std::vector<viz::data::Color>> colors;
598 for (
int r = 0; r < rows; r++)
600 auto& verticesRow = vertices.emplace_back(cols);
601 auto& colorsRow = colors.emplace_back(cols);
603 for (
int c = 0;
c < cols;
c++)
606 colorsRow.at(
c) = asColor(costmap.
getGrid()(r,
c));
610 mesh.grid2D(vertices, colors);
622 if (not navigatorId.has_value())
627 return &navigators.at(navigatorId.value());
630 std::optional<std::string>
635 const auto isActive = [](
const auto& nameNavPair) ->
bool
637 const auto& [name, navigator] = nameNavPair;
638 return not navigator.isPaused();
641 const auto it = std::find_if(navigators.begin(), navigators.end(), isActive);
644 if (it == navigators.end())