25#include <SimoxUtility/algorithm/contains.h>
26#include <SimoxUtility/algorithm/get_map_keys_values.h>
27#include <SimoxUtility/algorithm/string.h>
34#include <RobotAPI/interface/core/PoseBase.h>
49 commonVisu(descriptionSegment, proprioceptionSegment, localizationSegment)
56 robotUnit.plugin->setRobotUnitAsOptionalDependency(
true);
57 robotUnit.dataBuffer = std::make_unique<RobotUnit::Queue>();
68 const std::string robotUnitPrefix = RobotUnit::sensorValuePrefix;
71 defs->optional(robotUnit.waitForRobotUnit,
73 "Add the robot unit as dependency to the component. This memory requires a "
74 "running RobotUnit, therefore we should add it as explicit dependency.");
76 defs->optional(robotUnit.reader.properties.sensorPrefix,
77 robotUnitPrefix +
"SensorValuePrefix",
78 "Prefix of all sensor values.");
79 defs->optional(robotUnit.pollFrequency,
80 robotUnitPrefix +
"UpdateFrequency",
81 "The frequency to store values in Hz. All other values get discarded. "
82 "Minimum is 1, max is " +
83 std::to_string(RobotUnit::ROBOT_UNIT_MAXIMUM_FREQUENCY) +
".")
85 .setMax(RobotUnit::ROBOT_UNIT_MAXIMUM_FREQUENCY);
87 defs->optional(robotUnit.writer.properties.queueSizeWarningThreshold,
88 robotUnitPrefix +
"QueueSizeWarningThreshold",
89 "If the RobotStateWriter's data queue grows larger than this value, "
90 "a warning is logged (rate-limited).");
93 const std::string prefix =
"mem.";
97 descriptionSegment.defineProperties(defs, prefix +
"desc.");
98 exteroceptionSegment.defineProperties(defs, prefix +
"ext.");
99 proprioceptionSegment.defineProperties(defs, prefix +
"prop.");
100 localizationSegment.defineProperties(defs, prefix +
"loc.");
101 commonVisu.defineProperties(defs, prefix +
"visu.");
109 return "RobotStateMemory";
115 descriptionSegment.init();
116 proprioceptionSegment.init();
117 exteroceptionSegment.init();
118 localizationSegment.init();
121 robotUnit.pollFrequency =
122 std::clamp(robotUnit.pollFrequency, 0.F, RobotUnit::ROBOT_UNIT_MAXIMUM_FREQUENCY);
124 std::vector<std::string> includePaths;
128 for (
const std::string& projectName : packages)
130 if (projectName.empty())
136 const std::string pathsString = project.getIncludePaths();
137 std::vector<std::string> projectIncludePaths = simox::alg::split(pathsString,
";,");
139 includePaths.end(), projectIncludePaths.begin(), projectIncludePaths.end());
142 if (robotUnit.waitForRobotUnit)
144 usingProxy(robotUnit.plugin->getRobotUnitName());
152 ARMARX_CHECK(not robotUnit.reader.task or not robotUnit.reader.task->isRunning());
153 ARMARX_CHECK(not robotUnit.writer.task or not robotUnit.writer.task->isRunning());
154 robotUnit.dataBuffer = std::make_unique<RobotUnit::Queue>();
160 ARMARX_INFO <<
"Debug observer set for LTM timing measurements";
163 localizationSegment.onConnect();
164 commonVisu.connect(
getArvizClient(), debugObserver->getDebugObserver());
167 if (robotUnit.plugin->hasRobotUnitName())
169 robotUnit.plugin->waitUntilRobotUnitIsRunning();
172 robotUnit.reader.setTag(
getName());
173 robotUnit.writer.setTag(
getName());
175 descriptionSegment.onConnect(robotUnitPrx);
176 proprioceptionSegment.onConnect(robotUnitPrx);
178 robotUnit.reader.connect(
181 proprioceptionSegment.getRobotUnitProviderID().providerSegmentName);
182 robotUnit.writer.connect(*debugObserver);
183 robotUnit.writer.properties.robotUnitProviderID =
184 proprioceptionSegment.getRobotUnitProviderID();
187 [
this]() { robotUnit.reader.run(robotUnit.pollFrequency, *robotUnit.dataBuffer); },
188 "Robot Unit Reader");
192 robotUnit.writer.run(robotUnit.pollFrequency,
193 *robotUnit.dataBuffer,
195 localizationSegment);
197 "Robot State Writer");
199 startRobotUnitStream();
202 createRemoteGuiTab();
209 stopRobotUnitStream();
215 stopRobotUnitStream();
220 const std::string& robotName,
221 const ::Ice::Current& )
227 auto poseMap = localizationSegment.getRobotGlobalPoses(
timestamp);
229 const bool robotNameFound = simox::alg::contains_key(poseMap, robotName);
231 <<
"Robot with name " << robotName <<
" does not exist at or before timestamp "
233 <<
"Available robots are: " << simox::alg::get_keys(poseMap);
235 return {
new Pose(poseMap[robotName].matrix())};
244 RobotStateMemory::startRobotUnitStream()
255 ARMARX_WARNING <<
"Found inconsistency in running tasks. Restarting all!";
256 stopRobotUnitStream();
259 std::stringstream ss;
260 ss <<
"Getting sensor values for:" << std::endl;
261 for (
const auto& [name, dataEntry] : robotUnit.reader.
description.entries)
263 const std::string type =
265 ss <<
"\t" << name <<
" (type: '" << type <<
"')" << std::endl;
275 RobotStateMemory::stopRobotUnitStream()
278 robotUnit.dataBuffer->close();
279 robotUnit.reader.task->stop();
281 robotUnit.writer.task->stop();
286 RobotStateMemory::createRemoteGuiTab()
288 using namespace armarx::RemoteGui::Client;
292 tab.clearRobotStateWriterQueueButton.setLabel(
"Clear RobotStateWriter Queue");
293 root.
addChild(tab.clearRobotStateWriterQueueButton);
299 RobotStateMemory::RemoteGui_update()
303 if (tab.clearRobotStateWriterQueueButton.wasClicked())
305 clearRobotStateWriterQueue();
308 catch (
const std::exception& e)
310 ARMARX_WARNING <<
"RemoteGui_update: exception while handling button click: "
315 ARMARX_WARNING <<
"RemoteGui_update: unknown exception while handling button click.";
320 RobotStateMemory::clearRobotStateWriterQueue()
322 std::size_t dropped = 0;
325 if (not robotUnit.dataBuffer)
327 ARMARX_WARNING <<
"Cannot clear RobotStateWriter queue: data buffer is null.";
331 proprioception::RobotUnitData discarded;
334 boost::queue_op_status
status = boost::queue_op_status::empty;
337 status = robotUnit.dataBuffer->try_pull(discarded);
339 catch (
const std::exception& e)
341 ARMARX_WARNING <<
"Exception during queue try_pull after dropping " << dropped
342 <<
" entries: " << e.what() <<
". Stopping drain.";
347 ARMARX_WARNING <<
"Unknown exception during queue try_pull after dropping "
348 << dropped <<
" entries. Stopping drain.";
352 if (
status != boost::queue_op_status::success)
362 catch (
const std::exception& e)
364 ARMARX_WARNING <<
"clearRobotStateWriterQueue failed after dropping " << dropped
365 <<
" entries: " << e.what();
369 ARMARX_WARNING <<
"clearRobotStateWriterQueue failed with unknown exception after "
371 << dropped <<
" entries.";
static const std::string & GetProjectName()
static const Ice::StringSeq & GetProjectDependencies()
armarx::viz::Client & getArvizClient()
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
Default component property definition container.
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
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.
void start()
Starts the thread.
bool isRunning() const
Retrieve running state of the thread.
void setDebugObserver(DebugObserverInterfacePrx observer)
Set an optional debug observer for timing measurements.
server::ltm::Memory & longtermMemory()
void setMemoryName(const std::string &memoryName)
MemoryToIceAdapter & iceAdapter()
void onInitComponent() override
Pure virtual hook for the subclass.
void onDisconnectComponent() override
Hook for subclass.
armarx::PoseBasePtr getGlobalRobotPose(Ice::Long timestamp, const std::string &robotName, const ::Ice::Current &) override
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Creates the property definition container.
void onConnectComponent() override
Pure virtual hook for the subclass.
void onExitComponent() override
Hook for subclass.
~RobotStateMemory() override
std::string getDefaultName() const override
Retrieve default name of component.
armarx::SimpleRunningTask ::pointer_type task
RobotUnitDataStreaming::DataStreamingDescription description
armarx::SimpleRunningTask ::pointer_type task
static Duration MicroSeconds(std::int64_t microSeconds)
Constructs a duration in microseconds.
bool robotUnitIsRunning() const
#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_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
const simox::meta::EnumNames< DataEntryType > DataEntryNames
armarx::core::time::DateTime Time
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotUnitInterface > RobotUnitInterfacePrx
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
SimpleRunningTask(Ts...) -> SimpleRunningTask< std::function< void(void)> >
void RemoteGui_startRunningTask()
void RemoteGui_createTab(std::string const &name, RemoteGui::Client::Widget const &rootWidget, RemoteGui::Client::Tab *tab)