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,
422 <<
"Navigator config for caller `" << configId <<
"` not registered!";
423 navigators.at(configId).pause();
431 <<
"Navigator config for caller `" << configId <<
"` not registered!";
432 navigators.at(configId).resume();
441 <<
"Navigator config for caller `" << configId <<
"` not registered!";
442 navigators.at(configId).stop();
447 memoryPublishers.at(configId)->userAbortTriggered(event);
462 for (
auto& [_, navigator] : navigators)
469 ARMARX_INFO <<
"Trying to emit memory event `UserAbortTriggered`";
475 for (
auto& [callerId, memoryPublisher] : memoryPublishers)
477 memoryPublisher->userAbortTriggered(event);
487 <<
"Navigator config for caller `" << configId <<
"` not registered!";
488 return navigators.at(configId).isPaused();
495 return sceneProvider->scene();
503 <<
"Navigator config for caller `" << configId <<
"` not registered!";
504 return navigators.at(configId).isStopped();
521 def->component(remoteGui,
"RemoteGuiProvider");
526 def->optional(params.occupiedGridThreshold,
527 "p.occupancy_grid.occopied_threshold",
528 "Threshold for each cell to be considered occupied. Increase this value to "
531 def->optional(params.disableExecutor,
533 "If the executor is disabled, the navigator will only plan the trajectory "
534 "but won't execute it.");
536 def->required(params.sceneCfg.robotName,
"p.scene.robotName");
537 def->optional(params.sceneCfg.staticCostmapProviderName,
538 "p.scene.staticCostmapProviderName");
539 def->optional(params.sceneCfg.staticCostmapName,
"p.scene.staticCostmapName");
540 def->optional(params.sceneCfg.humanProviderName,
"p.scene.humanProviderName");
541 def->optional(params.sceneCfg.laserScannerFeaturesProviderName,
542 "p.scene.laserScannerFeaturesProviderName");
544 def->optional(params.rtUnitDynamicallyLoadLibraries,
545 "p.rtUnitDynamicallyLoadLibraries",
546 "If enabled, the controller library will automatically be loaded in the "
547 "RobotUnit. If disabled (desired), you have to make sure that the controller "
548 "library is listed in the RobotUnit's property `LoadLibraries`");
551 def->optional(params.navigatorGeneralConfig.tasks.replanningUpdatePeriod,
552 "p.navigator.general.replanningPeriod");
554 def->optional(params.navigatorGoalReachedConfig.posTh,
"p.navigator.goalReached.posTh");
555 def->optional(params.navigatorGoalReachedConfig.oriTh,
"p.navigator.goalReached.oriTh");
556 def->optional(params.navigatorGoalReachedConfig.linearVelTh,
557 "p.navigator.goalReached.linearVelTh");
558 def->optional(params.navigatorGoalReachedConfig.angularVelTh,
559 "p.navigator.goalReached.angularVelTh");
560 def->optional(params.navigatorGoalReachedConfig.filterCount,
561 "p.navigator.goalReached.filterCount");
569 const auto cmap = simox::color::cmaps::viridis();
570 const float vmax = costmap.
getGrid().array().maxCoeff();
574 const auto color = cmap.at(
distance, 0.
F, vmax);
575 return {color.a, color.r, color.g, color.b};
578 auto layer = arviz.
layer(
"costmap_" + name);
580 const std::int64_t cols = costmap.
getGrid().cols();
581 const std::int64_t rows = costmap.
getGrid().rows();
585 std::vector<std::vector<Eigen::Vector3f>> vertices;
586 std::vector<std::vector<viz::data::Color>> colors;
588 for (
int r = 0; r < rows; r++)
590 auto& verticesRow = vertices.emplace_back(cols);
591 auto& colorsRow = colors.emplace_back(cols);
593 for (
int c = 0;
c < cols;
c++)
596 colorsRow.at(
c) = asColor(costmap.
getGrid()(r,
c));
600 mesh.grid2D(vertices, colors);
612 if (not navigatorId.has_value())
617 return &navigators.at(navigatorId.value());
620 std::optional<std::string>
625 const auto isActive = [](
const auto& nameNavPair) ->
bool
627 const auto& [name, navigator] = nameNavPair;
628 return not navigator.isPaused();
631 const auto it = std::find_if(navigators.begin(), navigators.end(), isActive);
634 if (it == navigators.end())