29#include <experimental/memory>
38#include <Eigen/Geometry>
40#include <Ice/Current.h>
42#include <opencv2/core/eigen.hpp>
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>
92 std::vector<core::Pose>
93 convert(
const std::vector<Eigen::Matrix4f>& wps)
95 std::vector<core::Pose> p;
96 p.reserve(wps.size());
97 std::transform(wps.begin(),
99 std::back_inserter(p),
100 [](
const auto& p) { return core::Pose(p); });
122 addPlugin(laserScannerFeaturesReaderPlugin);
127 ¶meterizationReaderPlugin->get(), ¶meterizationWriterPlugin->get());
155 .graphReader = &graphReaderPlugin->get(),
156 .costmapReader = &costmapReaderPlugin->get(),
157 .costmap3dReader = &costmap3dReaderPlugin->get(),
158 .virtualRobotReader = &virtualRobotReaderPlugin->get(),
159 .humanReader = &humanReaderPlugin->get(),
160 .laserScannerFeaturesReader = &laserScannerFeaturesReaderPlugin->get(),
167 sceneProvider.reset();
169 sceneProvider.emplace(srv, params.sceneCfg);
176 if (not params.disableExecutor)
188 emergencyStop.reset();
189 if (not params.emergencyStopMasterName.empty())
193 emergencyStop.emplace(
196 <<
QUOTED(params.emergencyStopMasterName)
197 <<
" resolved. Controllers will not be activated while it is "
200 catch (
const std::exception& e)
203 <<
QUOTED(params.emergencyStopMasterName)
204 <<
" is not available: " << e.what()
205 <<
". Proceeding without an emergency stop check.";
212 .robotName = params.sceneCfg.robotName,
213 .rtUnitDynamicallyLoadLibraries = params.rtUnitDynamicallyLoadLibraries},
214 emergencyStop ? &emergencyStop.value() :
nullptr);
222 introspector.reset();
236 ARMARX_INFO <<
"Initialized. Will now respond to navigation requests.";
245 const bool isAnyNavigatorRunning = std::any_of(navigators.begin(),
247 [](
const auto& p) ->
bool
249 const server::Navigator& navigator =
252 return not navigator.isStopped();
256 if (isAnyNavigatorRunning)
259 <<
"A navigator was running when the component got disconnected. Will try to stop "
260 "as much as possible but expect something to be broken now.";
265 sceneProvider.reset();
267 introspector.reset();
296 const std::string& callerId,
307 sceneProvider->scene(),
318 memoryIntrospectors.emplace_back(
319 std::make_unique<server::MemoryIntrospector>(resultsWriterPlugin->get(), callerId));
322 memoryPublishers.emplace(
324 std::make_unique<server::MemoryPublisher>(
325 &resultsWriterPlugin->get(), &eventsWriterPlugin->get(), callerId));
328 if (executor.has_value())
330 executorPtr = &executor.value();
337 const std::string goalReachedKey =
341 auto goalReachedElement =
350 goalReachedCfg.
posTh = coreCfg.posTh;
351 goalReachedCfg.
oriTh = coreCfg.oriTh;
361 navigators.erase(callerId);
363 std::piecewise_construct,
364 std::forward_as_tuple(callerId),
365 std::forward_as_tuple(
367 .general = params.navigatorGeneralConfig,
368 .goalReachedConfig = goalReachedCfg},
370 .executor = executorPtr,
371 .publisher = memoryPublishers.at(callerId).get(),
372 .introspector = introspector.has_value() ? &(introspector.value()) :
nullptr,
373 .drawer = introspector.has_value() ? &(introspector.value()) :
nullptr,
376 sceneProvider.has_value() ? &sceneProvider.value() :
nullptr}));
382 navigators.erase(callerId);
383 memoryPublishers.erase(callerId);
388 const std::string& navigationMode,
389 const std::string& callerId,
395 <<
" with navigation mode `" << navigationMode <<
"`.";
397 <<
"Navigator config for caller " <<
QUOTED(callerId) <<
" not registered!";
401 navigators.at(callerId).moveTo(
convert(waypoints),
410 <<
"Movement will be paused.";
418 const std::string& navigationMode,
419 const std::string& callerId,
420 const Ice::Current& )
426 <<
"Navigator config for caller " <<
QUOTED(callerId) <<
" not registered!";
428 const auto checkIsActiveNavigator = [&](
const std::string& callerId)
431 if (not activeNavigatorCallerId.has_value())
437 return activeNavigatorCallerId == callerId;
441 <<
"The navigator with id " <<
QUOTED(callerId) <<
" is not active!";
443 navigators.at(callerId).update(
convert(waypoints),
449 const std::string& navigationMode,
450 const std::string& callerId,
451 const Ice::Current&
c)
457 const std::vector<client::WaypointTarget> wps =
client::defrost(waypoints);
460 <<
"Navigator config for caller " <<
QUOTED(callerId) <<
" not registered!";
467 const std::string& navigationMode,
468 const std::string& callerId,
469 const Ice::Current&
c)
474 <<
" with navigation mode `" << navigationMode <<
"`.";
476 <<
"Navigator config for caller " <<
QUOTED(callerId) <<
" not registered!";
482 navigators.at(callerId).moveToAlternatives(
491 <<
"Movement will be paused.";
499 const IceUtil::Optional<std::string>& providerNameIce,
500 const std::string& callerId,
501 const Ice::Current&
c)
508 <<
"Navigator config for caller " <<
QUOTED(callerId) <<
" not registered!";
510 std::optional<std::string> providerName;
513 providerName = providerNameIce.value();
516 navigators.at(callerId).moveToLocation(
location, providerName);
521 const std::string& navigationMode,
522 const std::string& callerId,
530 <<
"Navigator config for caller " <<
QUOTED(callerId) <<
" not registered!";
532 navigators.at(callerId).moveTowards(direction,
538 const std::string& callerId,
543 <<
"Navigator config for caller " <<
QUOTED(callerId) <<
" not registered!";
544 navigators.at(callerId).setVelocityFactor(velocityFactor);
551 <<
"Navigator config for caller " <<
QUOTED(configId) <<
" not registered!";
552 navigators.at(configId).pause();
560 <<
"Navigator config for caller " <<
QUOTED(configId) <<
" not registered!";
561 navigators.at(configId).resume();
570 <<
"Navigator config for caller " <<
QUOTED(configId) <<
" not registered!";
571 navigators.at(configId).stop();
576 memoryPublishers.at(configId)->userAbortTriggered(event);
598 ARMARX_INFO <<
"Trying to emit memory event `UserAbortTriggered`";
604 for (
auto& [callerId, memoryPublisher] : memoryPublishers)
606 memoryPublisher->userAbortTriggered(event);
616 <<
"Navigator config for caller " <<
QUOTED(configId) <<
" not registered!";
617 return navigators.at(configId).isPaused();
624 return sceneProvider->scene();
632 <<
"Navigator config for caller " <<
QUOTED(configId) <<
" not registered!";
633 return navigators.at(configId).isStopped();
653 def->optional(params.occupiedGridThreshold,
654 "p.occupancy_grid.occopied_threshold",
655 "Threshold for each cell to be considered occupied. Increase this value to "
658 def->optional(params.disableExecutor,
660 "If the executor is disabled, the navigator will only plan the trajectory "
661 "but won't execute it.");
663 def->required(params.sceneCfg.robotName,
"p.scene.robotName");
664 def->optional(params.sceneCfg.staticCostmapProviderName,
665 "p.scene.staticCostmapProviderName");
666 def->optional(params.sceneCfg.staticCostmapName,
"p.scene.staticCostmapName");
667 def->optional(params.sceneCfg.costmap3dProviderName,
"p.scene.costmap3dProviderName");
668 def->optional(params.sceneCfg.costmap3dName,
"p.scene.costmap3dName");
669 def->optional(params.sceneCfg.humanProviderName,
"p.scene.humanProviderName");
670 def->optional(params.sceneCfg.laserScannerFeaturesProviderName,
671 "p.scene.laserScannerFeaturesProviderName");
673 def->optional(params.rtUnitDynamicallyLoadLibraries,
674 "p.rtUnitDynamicallyLoadLibraries",
675 "If enabled, the controller library will automatically be loaded in the "
676 "RobotUnit. If disabled (desired), you have to make sure that the controller "
677 "library is listed in the RobotUnit's property `LoadLibraries`");
679 def->optional(params.emergencyStopMasterName,
680 "p.navigator.emergencyStopMasterName",
681 "Name of the emergency stop master. While it reports the emergency stop "
682 "engaged, the trajectory controllers are not (re-)activated. Empty disables "
683 "the check, as does an unresolvable name.");
686 def->optional(params.navigatorGeneralConfig.tasks.replanningUpdatePeriod,
687 "p.navigator.general.replanningPeriod");
689 def->optional(params.navigatorGeneralConfig.platform,
690 "p.navigator.general.platform",
691 "Which platform's drive parameters the TOPP-RA parametrization uses: the "
692 "suffix selecting config/platform/PlatformDynamics<Platform>.json in the "
693 "armarx_navigation package: Armar7, Armar6 or ArmarDE.");
694 def->optional(params.navigatorGeneralConfig.platformDynamicsEnabled,
695 "p.navigator.general.platformDynamicsEnabled",
696 "Whether to read drive parameters at all. False makes TOPP-RA unavailable, "
697 "so the stack falls back to ramping.");
699 def->optional(params.navigatorGeneralConfig.parametrizationDump,
700 "p.navigator.general.parametrizationDump",
701 "Write a record of every parametrized navigation request, for offline "
702 "analysis with `plot-navigation-request`.");
703 def->optional(params.navigatorGeneralConfig.parametrizationDumpPath,
704 "p.navigator.general.parametrizationDumpPath",
705 "Where that record is written. A timestamped copy is written alongside it.");
708 params.navigatorGeneralConfig.subdivision.enable,
709 "p.navigator.general.subdivision.enable",
710 "Whether to enable global path subdivision when local planner is enabled as well.");
711 def->optional(params.navigatorGeneralConfig.subdivision.localPlannerCostmapThreshold,
712 "p.navigator.general.subdivision.localPlannerCostmapThreshold",
713 "The minimum value in the costmap to enable local planning.");
715 params.navigatorGeneralConfig.subdivision.globalPlanExpansionDistance,
716 "p.navigator.general.subdivision.globalPlanExpansionDistance",
717 "The length by which global planner segments are expaned (in both directions).");
718 def->optional(params.navigatorGeneralConfig.subdivision.minSegmentDistance,
719 "p.navigator.general.subdivision.minSegmentDistance",
720 "The minimum length for a local planner segment (otherwise it is deleted and "
721 "joined with the neighboring global planner segments).");
723 def->optional(params.navigatorGeneralConfig.targetAlternativesFilterTimeSeconds,
724 "p.navigator.general.targetAlternativesFilterTimeSeconds",
725 "The number of seconds to wait before replanning alternatives after all "
726 "alternatives where impossible.");
728 def->optional(params.navigatorGoalReachedConfig.posTh,
"p.navigator.goalReached.posTh");
729 def->optional(params.navigatorGoalReachedConfig.oriTh,
"p.navigator.goalReached.oriTh");
730 def->optional(params.navigatorGoalReachedConfig.linearVelTh,
731 "p.navigator.goalReached.linearVelTh");
732 def->optional(params.navigatorGoalReachedConfig.angularVelTh,
733 "p.navigator.goalReached.angularVelTh");
734 def->optional(params.navigatorGoalReachedConfig.filterCount,
735 "p.navigator.goalReached.filterCount");
743 const auto cmap = simox::color::cmaps::viridis();
744 const float vmax = costmap.
getGrid().array().maxCoeff();
746 const auto asColor = [&cmap, &vmax](
const float distance) -> viz::data::Color
748 const auto color = cmap.at(
distance, 0.F, vmax);
749 return {color.a, color.r, color.g, color.b};
752 auto layer = arviz.
layer(
"costmap_" + name);
754 const std::int64_t cols = costmap.
getGrid().cols();
755 const std::int64_t rows = costmap.
getGrid().rows();
759 std::vector<std::vector<Eigen::Vector3f>> vertices;
760 std::vector<std::vector<viz::data::Color>> colors;
762 for (
int r = 0; r < rows; r++)
764 auto& verticesRow = vertices.emplace_back(cols);
765 auto& colorsRow = colors.emplace_back(cols);
767 for (
int c = 0;
c < cols;
c++)
770 colorsRow.at(
c) = asColor(costmap.
getGrid()(r,
c));
774 mesh.grid2D(vertices, colors);
786 if (not navigatorId.has_value())
791 return &navigators.at(navigatorId.value());
794 std::optional<std::string>
799 const auto isActive = [](
const auto& nameNavPair) ->
bool
801 const auto& [name,
navigator] = nameNavPair;
805 const auto it = std::find_if(navigators.begin(), navigators.end(), isActive);
808 if (it == navigators.end())
823 tab.stopAll.setLabel(
"Stop All");
833 if (tab.stopAll.wasClicked())
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
armarx::viz::Client & getArvizClient()
static DateTime Now()
Current time on the virtual clock.
Default component property definition container.
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
plugins::DebugObserverComponentPlugin & getDebugObserverComponentPlugin()
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
PluginT * addPlugin(const std::string prefix="", ParamsT &&... params)
std::string getName() const
Retrieve name of object.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
void setLogObjectDiscoveryError(bool logEnabled)
objpose::ObjectPoseClient getClient() const
bool hasElement(const std::string &) const
VariantPtr getElement(const std::string &) const
static PointerType DynamicCast(const VariantPtr &n)
ComponentPlugin & getControlComponentPlugin()
const Grid & getGrid() const
Position toPositionGlobal(const Index &index) const
void moveToLocation(const std::string &location, const IceUtil::Optional< std::string > &providerName, const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
void removeConfig(const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
void onInitComponent() override
void pause(const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
void resume(const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
void setVelocityFactor(float velocityFactor, const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
std::optional< std::string > activeNavigatorId() const
server::Navigator * activeNavigator()
void onDisconnectComponent() override
void moveToAlternatives(const client::detail::TargetAlternatives &targets, const std::string &navigationMode, const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
void RemoteGui_update() override
After calling RemoteGui_startRunningTask, this function is called periodically in a separate thread.
bool isPaused(const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
bool isStopped(const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
PropertyDefinitionsPtr createPropertyDefinitions() override
void updateMoveTo(const std::vector< Eigen::Matrix4f > &waypoints, const std::string &navigationMode, const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
const core::Scene & scene() const
void onConnectComponent() override
void createConfig(const aron::data::dto::DictPtr &stackConfig, const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
static std::string GetDefaultName()
void stop(const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
void onExitComponent() override
void moveTo(const std::vector< Eigen::Matrix4f > &waypoints, const std::string &navigationMode, const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
void moveTowards(const Eigen::Vector3f &direction, const std::string &navigationMode, const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
void stopAllImpl(bool emitMemoryEvent)
void moveTo2(const client::detail::Waypoints &waypoints, const std::string &navigationMode, const std::string &callerId, const Ice::Current &c=Ice::emptyCurrent) override
void createRemoteGuiTab()
This function should be called once in onConnect() or when you need to re-create the Remote GUI tab.
std::string getDefaultName() const override
static server::NavigationStack create(const aron::data::DictPtr ¶ms, const core::Scene &scene, std::experimental::observer_ptr< viz::Client > arviz, std::experimental::observer_ptr< DebugObserverComponentPluginUser > debugObserver)
An executer the server navigator will use to send its control commands to.
ObjectFinder objectFinder
Brief description of class targets.
virtual Layer layer(std::string const &name) const
CommitResult commit(StagedCommit const &commit)
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
idempotent void stopAll()
::IceInternal::Handle< Dict > DictPtr
sequence< Waypoint > Waypoints
sequence< TargetAlternative > TargetAlternatives
client::GlobalPlanningStrategy defrost(const client::detail::GlobalPlanningStrategy &strategy)
void visualize(const algorithms::Costmap &costmap, viz::Client &arviz, const std::string &name)
std::vector< Eigen::Vector3f > to3D(const std::vector< Eigen::Vector2f > &v)
const std::string PARAMS_KEY
const simox::meta::EnumNames< StackLayer > StackLayerNames
const simox::meta::EnumNames< NavigationFrame > NavigationFrameNames
This file is part of ArmarX.
core::GoalReachedConfig GoalReachedMonitorConfig
This file is part of ArmarX.
std::vector< core::Pose > convert(const std::vector< Eigen::Matrix4f > &wps)
std::string GetHandledExceptionString()
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
observer_ptr< _Tp > make_observer(_Tp *__p) noexcept
double distance(const Point &a, const Point &b)
void RemoteGui_startRunningTask()
void RemoteGui_createTab(std::string const &name, RemoteGui::Client::Widget const &rootWidget, RemoteGui::Client::Tab *tab)
static GoalReachedConfig FromAron(const aron::data::DictPtr &dict)
Event describing that the user aborted the current execution.
local_planning::LocalPlannerPtr localPlanner