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.";
247 bool isAnyNavigatorRunning =
false;
250 isAnyNavigatorRunning = std::any_of(
253 [](
const auto& p) ->
bool { return not p.second->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.";
279 decltype(navigators) stale;
281 const std::scoped_lock lock{navigatorsMtx};
282 stale.swap(navigators);
286 sceneProvider.reset();
288 introspector.reset();
317 const std::string& callerId,
328 sceneProvider->scene(),
339 auto memoryIntrospector =
340 std::make_unique<server::MemoryIntrospector>(resultsWriterPlugin->get(), callerId);
342 auto memoryPublisher = std::make_unique<server::MemoryPublisher>(
343 &resultsWriterPlugin->get(), &eventsWriterPlugin->get(), callerId);
346 if (executor.has_value())
348 executorPtr = &executor.value();
355 const std::string goalReachedKey =
359 auto goalReachedElement =
368 goalReachedCfg.
posTh = coreCfg.posTh;
369 goalReachedCfg.
oriTh = coreCfg.oriTh;
386 .publisher = std::move(memoryPublisher),
387 .introspector = std::move(memoryIntrospector),
390 .general = params.navigatorGeneralConfig,
391 .goalReachedConfig = goalReachedCfg},
393 .executor = executorPtr,
394 .publisher = publisherPtr,
395 .introspector = introspector.has_value() ? &(introspector.value()) :
nullptr,
396 .drawer = introspector.has_value() ? &(introspector.value()) :
nullptr,
399 sceneProvider.has_value() ? &sceneProvider.value() :
nullptr}}});
407 const std::scoped_lock lock{navigatorsMtx};
408 previous = std::exchange(navigators[callerId], std::move(
entry));
419 const std::scoped_lock lock{navigatorsMtx};
420 if (
const auto it = navigators.find(callerId); it != navigators.end())
422 entry = std::move(it->second);
423 navigators.erase(it);
432 const std::scoped_lock lock{navigatorsMtx};
434 const auto it = navigators.find(callerId);
436 <<
"Navigator config for caller " <<
QUOTED(callerId) <<
" not registered!";
441 std::vector<std::pair<std::string, Component::NavigatorEntryPtr>>
444 const std::scoped_lock lock{navigatorsMtx};
445 return {navigators.begin(), navigators.end()};
450 const std::string& navigationMode,
451 const std::string& callerId,
457 <<
" with navigation mode `" << navigationMode <<
"`.";
469 <<
"Movement will be paused.";
477 const std::string& navigationMode,
478 const std::string& callerId,
479 const Ice::Current& )
484 const auto checkIsActiveNavigator = [&](
const std::string& callerId)
487 if (not activeNavigatorCallerId.has_value())
493 return activeNavigatorCallerId == callerId;
497 <<
"The navigator with id " <<
QUOTED(callerId) <<
" is not active!";
505 const std::string& navigationMode,
506 const std::string& callerId,
507 const Ice::Current&
c)
513 const std::vector<client::WaypointTarget> wps =
client::defrost(waypoints);
520 const std::string& navigationMode,
521 const std::string& callerId,
522 const Ice::Current&
c)
527 <<
" with navigation mode `" << navigationMode <<
"`.";
532 entry(callerId)->navigator.moveToAlternatives(
541 <<
"Movement will be paused.";
549 const IceUtil::Optional<std::string>& providerNameIce,
550 const std::string& callerId,
551 const Ice::Current&
c)
557 std::optional<std::string> providerName;
560 providerName = providerNameIce.value();
563 entry(callerId)->navigator.moveToLocation(
location, providerName);
568 const std::string& navigationMode,
569 const std::string& callerId,
576 entry(callerId)->navigator.moveTowards(
582 const std::string& callerId,
586 entry(callerId)->navigator.setVelocityFactor(velocityFactor);
592 entry(configId)->navigator.pause();
599 entry(configId)->navigator.resume();
615 e->publisher->userAbortTriggered(event);
632 for (
const auto& [_, e] : entries)
639 ARMARX_INFO <<
"Trying to emit memory event `UserAbortTriggered`";
645 for (
const auto& [callerId, e] : entries)
647 e->publisher->userAbortTriggered(event);
656 return entry(configId)->navigator.isPaused();
663 return sceneProvider->scene();
670 return entry(configId)->navigator.isStopped();
690 def->optional(params.occupiedGridThreshold,
691 "p.occupancy_grid.occopied_threshold",
692 "Threshold for each cell to be considered occupied. Increase this value to "
695 def->optional(params.disableExecutor,
697 "If the executor is disabled, the navigator will only plan the trajectory "
698 "but won't execute it.");
700 def->required(params.sceneCfg.robotName,
"p.scene.robotName");
701 def->optional(params.sceneCfg.staticCostmapProviderName,
702 "p.scene.staticCostmapProviderName");
703 def->optional(params.sceneCfg.staticCostmapName,
"p.scene.staticCostmapName");
704 def->optional(params.sceneCfg.costmap3dProviderName,
"p.scene.costmap3dProviderName");
705 def->optional(params.sceneCfg.costmap3dName,
"p.scene.costmap3dName");
706 def->optional(params.sceneCfg.humanProviderName,
"p.scene.humanProviderName");
707 def->optional(params.sceneCfg.laserScannerFeaturesProviderName,
708 "p.scene.laserScannerFeaturesProviderName");
710 def->optional(params.rtUnitDynamicallyLoadLibraries,
711 "p.rtUnitDynamicallyLoadLibraries",
712 "If enabled, the controller library will automatically be loaded in the "
713 "RobotUnit. If disabled (desired), you have to make sure that the controller "
714 "library is listed in the RobotUnit's property `LoadLibraries`");
716 def->optional(params.emergencyStopMasterName,
717 "p.navigator.emergencyStopMasterName",
718 "Name of the emergency stop master. While it reports the emergency stop "
719 "engaged, the trajectory controllers are not (re-)activated. Empty disables "
720 "the check, as does an unresolvable name.");
723 def->optional(params.navigatorGeneralConfig.tasks.replanningUpdatePeriod,
724 "p.navigator.general.replanningPeriod");
726 def->optional(params.navigatorGeneralConfig.platform,
727 "p.navigator.general.platform",
728 "Which platform's drive parameters the TOPP-RA parametrization uses: the "
729 "suffix selecting config/platform/PlatformDynamics<Platform>.json in the "
730 "armarx_navigation package: Armar7, Armar6 or ArmarDE.");
731 def->optional(params.navigatorGeneralConfig.platformDynamicsEnabled,
732 "p.navigator.general.platformDynamicsEnabled",
733 "Whether to read drive parameters at all. False makes TOPP-RA unavailable, "
734 "so the stack falls back to ramping.");
736 def->optional(params.navigatorGeneralConfig.parametrizationDump,
737 "p.navigator.general.parametrizationDump",
738 "Write a record of every parametrized navigation request, for offline "
739 "analysis with `plot-navigation-request`.");
740 def->optional(params.navigatorGeneralConfig.parametrizationDumpPath,
741 "p.navigator.general.parametrizationDumpPath",
742 "Where that record is written. A timestamped copy is written alongside it.");
745 params.navigatorGeneralConfig.subdivision.enable,
746 "p.navigator.general.subdivision.enable",
747 "Whether to enable global path subdivision when local planner is enabled as well.");
748 def->optional(params.navigatorGeneralConfig.subdivision.localPlannerCostmapThreshold,
749 "p.navigator.general.subdivision.localPlannerCostmapThreshold",
750 "The minimum value in the costmap to enable local planning.");
752 params.navigatorGeneralConfig.subdivision.globalPlanExpansionDistance,
753 "p.navigator.general.subdivision.globalPlanExpansionDistance",
754 "The length by which global planner segments are expaned (in both directions).");
755 def->optional(params.navigatorGeneralConfig.subdivision.minSegmentDistance,
756 "p.navigator.general.subdivision.minSegmentDistance",
757 "The minimum length for a local planner segment (otherwise it is deleted and "
758 "joined with the neighboring global planner segments).");
760 def->optional(params.navigatorGeneralConfig.targetAlternativesFilterTimeSeconds,
761 "p.navigator.general.targetAlternativesFilterTimeSeconds",
762 "The number of seconds to wait before replanning alternatives after all "
763 "alternatives where impossible.");
765 def->optional(params.navigatorGoalReachedConfig.posTh,
"p.navigator.goalReached.posTh");
766 def->optional(params.navigatorGoalReachedConfig.oriTh,
"p.navigator.goalReached.oriTh");
767 def->optional(params.navigatorGoalReachedConfig.linearVelTh,
768 "p.navigator.goalReached.linearVelTh");
769 def->optional(params.navigatorGoalReachedConfig.angularVelTh,
770 "p.navigator.goalReached.angularVelTh");
771 def->optional(params.navigatorGoalReachedConfig.filterCount,
772 "p.navigator.goalReached.filterCount");
780 const auto cmap = simox::color::cmaps::viridis();
781 const float vmax = costmap.
getGrid().array().maxCoeff();
783 const auto asColor = [&cmap, &vmax](
const float distance) -> viz::data::Color
785 const auto color = cmap.at(
distance, 0.F, vmax);
786 return {color.a, color.r, color.g, color.b};
789 auto layer = arviz.
layer(
"costmap_" + name);
791 const std::int64_t cols = costmap.
getGrid().cols();
792 const std::int64_t rows = costmap.
getGrid().rows();
796 std::vector<std::vector<Eigen::Vector3f>> vertices;
797 std::vector<std::vector<viz::data::Color>> colors;
799 for (
int r = 0; r < rows; r++)
801 auto& verticesRow = vertices.emplace_back(cols);
802 auto& colorsRow = colors.emplace_back(cols);
804 for (
int c = 0;
c < cols;
c++)
807 colorsRow.at(
c) = asColor(costmap.
getGrid()(r,
c));
811 mesh.grid2D(vertices, colors);
821 const auto isActive = [](
const auto& nameNavPair) ->
bool
822 {
return not nameNavPair.second->navigator.isPaused(); };
827 const auto it = std::find_if(entries.begin(), entries.end(), isActive);
829 return it == entries.end() ? nullptr : it->second;
832 std::optional<std::string>
837 const auto isActive = [](
const auto& nameNavPair) ->
bool
838 {
return not nameNavPair.second->navigator.isPaused(); };
841 const auto it = std::find_if(entries.begin(), entries.end(), isActive);
844 if (it == entries.end())
859 tab.stopAll.setLabel(
"Stop All");
869 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
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
std::vector< std::pair< std::string, NavigatorEntryPtr > > allEntries() const
A snapshot of every registered entry, each held alive by the returned references.
NavigatorEntryPtr entry(const std::string &callerId) const
The entry for callerId, throwing if it is not registered.
NavigatorEntryPtr activeNavigator()
std::shared_ptr< NavigatorEntry > NavigatorEntryPtr
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)
Everything registered for one callerId, kept alive as one unit.
static GoalReachedConfig FromAron(const aron::data::DictPtr &dict)
Event describing that the user aborted the current execution.
local_planning::LocalPlannerPtr localPlanner