35 #include <Eigen/Geometry>
37 #include <opencv2/core/eigen.hpp>
38 #include <opencv2/imgcodecs.hpp>
40 #include <Ice/Current.h>
42 #include <SimoxUtility/color/ColorMap.h>
43 #include <SimoxUtility/color/cmaps/colormaps.h>
44 #include <SimoxUtility/math/convert/rpy_to_mat3f.h>
45 #include <VirtualRobot/MathTools.h>
46 #include <VirtualRobot/Robot.h>
78 #include <armarx/navigation/client/ice/NavigatorInterface.h>
100 std::vector<core::Pose>
101 convert(
const std::vector<Eigen::Matrix4f>& wps)
103 std::vector<core::Pose> p;
104 p.reserve(wps.size());
107 std::back_inserter(p),
108 [](
const auto& p) { return core::Pose(p); });
129 addPlugin(laserScannerFeaturesReaderPlugin);
134 ¶meterizationReaderPlugin->get(), ¶meterizationWriterPlugin->get());
160 .costmapReader = &costmapReaderPlugin->get(),
161 .virtualRobotReader = &virtualRobotReaderPlugin->get(),
162 .humanReader = &humanReaderPlugin->get(),
163 .laserScannerFeaturesReader = &laserScannerFeaturesReaderPlugin->get(),
168 sceneProvider.emplace(srv, params.sceneCfg);
175 if (not params.disableExecutor)
183 .rtUnitDynamicallyLoadLibraries = params.rtUnitDynamicallyLoadLibraries});
194 navRemoteGui.emplace(remoteGui, *
this);
195 navRemoteGui->enable();
199 ARMARX_INFO <<
"Initialized. Will now respond to navigation requests.";
208 const bool isAnyNavigatorRunning = std::any_of(navigators.begin(),
210 [](
const auto& p) ->
bool
212 const server::Navigator& navigator =
215 return not navigator.isStopped();
219 if (isAnyNavigatorRunning)
222 <<
"A navigator was running when the component got disconnected. Will try to stop "
223 "as much as possible but expect something to be broken now.";
228 navRemoteGui->disable();
229 navRemoteGui.reset();
231 sceneProvider.reset();
233 introspector.reset();
262 const std::string& callerId,
267 ARMARX_INFO <<
"Creating config for caller '" << callerId <<
"'";
280 memoryIntrospectors.emplace_back(
281 std::make_unique<server::MemoryIntrospector>(resultsWriterPlugin->get(), callerId));
284 memoryPublishers.emplace(
286 std::make_unique<server::MemoryPublisher>(
287 &resultsWriterPlugin->get(), &eventsWriterPlugin->get(), callerId));
290 if (executor.has_value())
292 executorPtr = &executor.value();
296 navigators.erase(callerId);
298 std::piecewise_construct,
299 std::forward_as_tuple(callerId),
300 std::forward_as_tuple(
305 .publisher = memoryPublishers.at(callerId).get(),
306 .introspector = introspector.has_value() ? &(introspector.value()) :
nullptr,
309 sceneProvider.has_value() ? &sceneProvider.value() :
nullptr}));
314 const std::string& navigationMode,
315 const std::string& callerId,
320 ARMARX_INFO <<
"moveTo() requested by caller '" << callerId <<
"' with navigation mode `"
321 << navigationMode <<
"`.";
323 <<
"Navigator config for caller `" << callerId <<
"` not registered!";
327 navigators.at(callerId).moveTo(
convert(waypoints),
335 ARMARX_WARNING <<
"Failed to execute moveTo()." <<
"Movement will be paused.";
343 const std::string& navigationMode,
344 const std::string& callerId,
345 const Ice::Current& )
349 ARMARX_INFO <<
"updateMoveTo() requested by caller '" << callerId <<
"'";
351 <<
"Navigator config for caller `" << callerId <<
"` not registered!";
353 const auto checkIsActiveNavigator = [&](
const std::string& callerId)
356 if (not activeNavigatorCallerId.has_value())
362 return activeNavigatorCallerId == callerId;
366 <<
"The navigator with id `" << callerId <<
"` is not active!";
368 navigators.at(callerId).update(
convert(waypoints),
374 const std::string& navigationMode,
375 const std::string& callerId,
376 const Ice::Current&
c)
382 const std::vector<client::WaypointTarget> wps =
client::defrost(waypoints);
385 <<
"Navigator config for caller `" << callerId <<
"` not registered!";
392 const std::string& callerId,
393 const Ice::Current&
c)
396 ARMARX_INFO <<
"MoveToLocation `" << location <<
"` requested by caller '" << callerId
400 <<
"Navigator config for caller `" << callerId <<
"` not registered!";
402 navigators.at(callerId).moveToLocation(location);
407 const std::string& navigationMode,
408 const std::string& callerId,
413 ARMARX_INFO <<
"MoveTowards requested by caller '" << callerId <<
"'";
416 <<
"Navigator config for caller `" << callerId <<
"` not registered!";
418 navigators.at(callerId).moveTowards(direction,
426 <<
"Navigator config for caller `" << configId <<
"` not registered!";
427 navigators.at(configId).pause();
435 <<
"Navigator config for caller `" << configId <<
"` not registered!";
436 navigators.at(configId).resume();
445 <<
"Navigator config for caller `" << configId <<
"` not registered!";
446 navigators.at(configId).stop();
451 memoryPublishers.at(configId)->userAbortTriggered(event);
466 for (
auto& [_, navigator] : navigators)
473 ARMARX_INFO <<
"Trying to emit memory event `UserAbortTriggered`";
479 for (
auto& [callerId, memoryPublisher] : memoryPublishers)
481 memoryPublisher->userAbortTriggered(event);
491 <<
"Navigator config for caller `" << configId <<
"` not registered!";
492 return navigators.at(configId).isPaused();
499 return sceneProvider->scene();
507 <<
"Navigator config for caller `" << configId <<
"` not registered!";
508 return navigators.at(configId).isStopped();
525 def->component(remoteGui,
"RemoteGuiProvider");
530 def->optional(params.occupiedGridThreshold,
531 "p.occupancy_grid.occopied_threshold",
532 "Threshold for each cell to be considered occupied. Increase this value to "
535 def->optional(params.disableExecutor,
537 "If the executor is disabled, the navigator will only plan the trajectory "
538 "but won't execute it.");
540 def->required(params.sceneCfg.robotName,
"p.scene.robotName");
541 def->optional(params.sceneCfg.staticCostmapProviderName,
542 "p.scene.staticCostmapProviderName");
543 def->optional(params.sceneCfg.staticCostmapName,
"p.scene.staticCostmapName");
544 def->optional(params.sceneCfg.humanProviderName,
"p.scene.humanProviderName");
545 def->optional(params.sceneCfg.laserScannerFeaturesProviderName,
546 "p.scene.laserScannerFeaturesProviderName");
548 def->optional(params.rtUnitDynamicallyLoadLibraries,
549 "p.rtUnitDynamicallyLoadLibraries",
550 "If enabled, the controller library will automatically be loaded in the "
551 "RobotUnit. If disabled (desired), you have to make sure that the controller "
552 "library is listed in the RobotUnit's property `LoadLibraries`");
560 const auto cmap = simox::color::cmaps::viridis();
561 const float vmax = costmap.
getGrid().array().maxCoeff();
565 const auto color = cmap.at(
distance, 0.
F, vmax);
566 return {color.a, color.r, color.g, color.b};
569 auto layer = arviz.
layer(
"costmap_" + name);
571 const std::int64_t cols = costmap.
getGrid().cols();
572 const std::int64_t rows = costmap.
getGrid().rows();
576 std::vector<std::vector<Eigen::Vector3f>> vertices;
577 std::vector<std::vector<viz::data::Color>> colors;
579 for (
int r = 0; r < rows; r++)
581 auto& verticesRow = vertices.emplace_back(cols);
582 auto& colorsRow = colors.emplace_back(cols);
584 for (
int c = 0;
c < cols;
c++)
587 colorsRow.at(
c) = asColor(costmap.
getGrid()(r,
c));
591 mesh.grid2D(vertices, colors);
603 if (not navigatorId.has_value())
608 return &navigators.at(navigatorId.value());
611 std::optional<std::string>
616 const auto isActive = [](
const auto& nameNavPair) ->
bool
618 const auto& [name, navigator] = nameNavPair;
619 return not navigator.isPaused();
622 const auto it = std::find_if(navigators.begin(), navigators.end(), isActive);
625 if (it == navigators.end())