30 #include <RobotAPI/libraries/armem_objects/aron/ObjectInstance.aron.generated.h>
39 #include <VirtualRobot/Robot.h>
41 #include <SimoxUtility/algorithm/get_map_keys_values.h>
82 KinematicUnitObserverInterfacePrx kinematicUnitObserver,
87 this->debugObserver = debugObserver;
102 this->visualizeRun();
113 updateProviderInfo(providerName, info);
120 ARMARX_VERBOSE <<
"Received " << providedPoses.size() <<
" object poses from provider '" << providerName <<
"'.";
121 updateObjectPoses(providerName, providedPoses);
125 void SegmentAdapter::updateProviderInfo(
const std::string& providerName,
const objpose::ProviderInfo& info)
129 ARMARX_WARNING <<
"Received availability signal by provider '" << providerName <<
"' "
130 <<
"with invalid provider proxy.\nIgnoring provider '" << providerName <<
"'.";
133 segment.
doLocked([
this, &providerName, &info]()
135 std::stringstream ss;
136 for (
const auto&
id : info.supportedObjects)
138 ss <<
"- " << id <<
"\n";
140 ARMARX_VERBOSE <<
"Provider '" << providerName <<
"' available.\n"
141 <<
"Supported objects: \n" << ss.str();
147 void SegmentAdapter::updateObjectPoses(
148 const std::string& providerName,
153 RobotHeadMovement::Discard discard;
155 std::scoped_lock lock(robotHeadMutex);
161 map[
"Discarding All Updates"] =
new Variant(discard.all ? 1.f : 0.f);
164 map[
"Proportion Updated Poses"] =
new Variant(0.f);
166 debugObserver->setDebugChannel(
getName(), map);
179 Segment::CommitStats stats =
180 segment.
commitObjectPoses(providerName, providedPoses, calibration, discard.updatesUntil);
185 debugObserver->setDebugChannel(
getName(),
187 {
"Discarding All Updates",
new Variant(discard.all ? 1 : 0) },
188 {
"Proportion Updated Poses",
new Variant(
static_cast<float>(stats.numUpdated) / providedPoses.size()) }
192 handleProviderUpdate(providerName);
197 debugObserver->setDebugChannel(
getName(),
199 {
"t ReportObjectPoses [ms]",
new Variant(tReportObjectPoses.toMilliSecondsDouble()) },
200 {
"t MemorySetObjectPoses [ms]",
new Variant(tCommitObjectPoses.toMilliSecondsDouble()) },
207 void SegmentAdapter::handleProviderUpdate(
const std::string& providerName)
210 if (segment.
providers.count(providerName) == 0)
212 segment.
providers[providerName] = objpose::ProviderInfo();
232 debugObserver->setDebugChannel(
getName(),
234 {
"t GetObjectPoses() [ms]",
new Variant(tGetObjectPoses.toMilliSecondsDouble()) },
256 debugObserver->setDebugChannel(
getName(),
258 {
"t GetObjectPosesByProvider() [ms]",
new Variant(GetObjectPoses.toMilliSecondsDouble()) },
267 const objpose::observer::RequestObjectsInput&
input,
const Ice::Current&)
269 std::map<std::string, objpose::provider::RequestObjectsInput> providerRequests;
270 std::map<std::string, objpose::ObjectPoseProviderPrx> proxies;
272 objpose::observer::RequestObjectsOutput output;
274 auto updateProxy = [&](
const std::string & providerName)
276 if (proxies.count(providerName) == 0)
280 proxies[providerName] = it->second.proxy;
284 ARMARX_ERROR <<
"No proxy for provider ' " << providerName <<
"'.";
285 proxies[providerName] =
nullptr;
290 if (
input.provider.size() > 0)
292 providerRequests[
input.provider] =
input.request;
293 updateProxy(
input.provider);
299 for (
const auto& objectID :
input.request.objectIDs)
302 for (const auto& [providerName, info] : segment.providers)
305 if (std::find(info.supportedObjects.begin(), info.supportedObjects.end(), objectID) != info.supportedObjects.end())
307 providerRequests[providerName].objectIDs.push_back(objectID);
308 updateProxy(providerName);
314 ARMARX_ERROR <<
"Did not find a provider for " << objectID <<
".";
315 output.results[objectID].providerName =
"";
321 for (
const auto& [providerName, request] : providerRequests)
323 if (objpose::ObjectPoseProviderPrx proxy = proxies.at(providerName); proxy)
325 ARMARX_INFO <<
"Requesting " << request.objectIDs.size() <<
" objects by provider '"
326 << providerName <<
"' for " << request.relativeTimeoutMS <<
" ms.";
327 objpose::provider::RequestObjectsOutput providerOutput = proxy->requestObjects(request);
330 for (
const auto& [objectID, result] : providerOutput.results)
332 objpose::observer::ObjectRequestResult& res = output.results[objectID];
333 res.providerName = providerName;
335 successful += int(result.success);
337 ARMARX_INFO << successful <<
" of " << request.objectIDs.size() <<
" object requests successful.";
344 objpose::ProviderInfoMap SegmentAdapter::getAvailableProvidersInfo(
const Ice::Current&)
346 return segment.doLocked([
this]()
348 return segment.providers;
353 Ice::StringSeq SegmentAdapter::getAvailableProviderNames(
const Ice::Current&)
355 return segment.doLocked([
this]()
357 return simox::alg::get_keys(segment.providers);
362 objpose::ProviderInfo SegmentAdapter::getProviderInfo(
const std::string& providerName,
const Ice::Current&)
364 return segment.doLocked([
this, &providerName]()
366 return segment.getProviderInfo(providerName);
371 bool SegmentAdapter::hasProvider(
const std::string& providerName,
const Ice::Current&)
373 return segment.doLocked([
this, &providerName]()
375 return segment.providers.count(providerName) > 0;
380 objpose::AttachObjectToRobotNodeOutput SegmentAdapter::attachObjectToRobotNode(
381 const objpose::AttachObjectToRobotNodeInput&
input,
const Ice::Current&)
383 return segment.doLocked([
this, &
input]()
385 return segment.attachObjectToRobotNode(
input);
390 objpose::DetachObjectFromRobotNodeOutput SegmentAdapter::detachObjectFromRobotNode(
391 const objpose::DetachObjectFromRobotNodeInput&
input,
const Ice::Current&)
393 return segment.doLocked([
this, &
input]()
395 return segment.detachObjectFromRobotNode(
input);
400 objpose::DetachAllObjectsFromRobotNodesOutput SegmentAdapter::detachAllObjectsFromRobotNodes(
401 const objpose::DetachAllObjectsFromRobotNodesInput&
input,
const Ice::Current&)
403 return segment.doLocked([
this, &
input]()
405 return segment.detachAllObjectsFromRobotNodes(
input);
410 objpose::AgentFramesSeq SegmentAdapter::getAttachableFrames(
const Ice::Current&)
412 return segment.doLocked([
this]()
414 objpose::AgentFramesSeq output;
415 for (
const auto& [name, agent] : segment.robots.loaded)
417 objpose::AgentFrames& frames = output.emplace_back();
418 frames.agent = agent->getName();
419 frames.frames = agent->getRobotNodeNames();
426 objpose::SignalHeadMovementOutput
427 SegmentAdapter::signalHeadMovement(
const objpose::SignalHeadMovementInput&
input,
const Ice::Current&)
429 std::scoped_lock lock(robotHeadMutex);
430 return robotHead.signalHeadMovement(
input);
433 objpose::ObjectPosePredictionResultSeq
434 SegmentAdapter::predictObjectPoses(
const objpose::ObjectPosePredictionRequestSeq& requests,
437 objpose::ObjectPosePredictionResultSeq results;
438 std::vector<std::map<DateTime, objpose::ObjectPose>> poses;
439 std::vector<objpose::ObjectPose> latestPoses;
442 [
this, &requests, &results, &poses, &latestPoses]()
444 for (
const auto& request : requests)
446 auto& result = results.emplace_back();
449 const Duration timeWindow = armarx::fromIce<Duration>(request.timeWindow);
451 const wm::Entity* entity = segment.findObjectEntity(objID);
453 result.success =
false;
454 poses.emplace_back();
455 latestPoses.emplace_back();
458 std::stringstream sstream;
459 sstream <<
"Could not find object with ID " << objID <<
".";
460 result.errorMessage = sstream.
str();
467 std::stringstream sstream;
468 sstream <<
"No snapshots of the object " << objID <<
" were found."
469 <<
" Cannot make a prediction.";
470 result.errorMessage = sstream.
str();
474 result.success =
true;
475 poses.back() = segment.getObjectPosesInRange(
477 latestPoses.back() = aron::fromAron<objpose::ObjectPose>(dto.value().pose);
481 for (
size_t i = 0; i < requests.size(); ++i)
483 const objpose::ObjectPosePredictionRequest& request = requests.at(i);
484 objpose::ObjectPosePredictionResult& result = results.at(i);
496 armarx::fromIce<DateTime>(request.timestamp),
502 "' not available for object pose prediction.";
503 result.success =
false;
510 armem::prediction::data::PredictionEngineSeq
511 SegmentAdapter::getAvailableObjectPoseEngines(
const Ice::Current&)
513 return armarx::toIce<armem::prediction::data::PredictionEngineSeq>(predictionEngines);
517 SegmentAdapter::visualizeRun()
521 CycleUtil cycle(
static_cast<int>(1000 / visu.frequencyHz));
522 while (visu.updateTask && !visu.updateTask->isStopped())
525 std::scoped_lock lock(visuMutex);
532 std::map<ObjectID, std::map<DateTime, objpose::ObjectPose>> poseHistories;
533 visu.minConfidence = -1;
535 segment.doLocked([
this, &objectPoses, &poseHistories, &objectFinder]()
541 const float minConf = segment.decay.removeObjectsBelowConfidence;
542 segment.decay.removeObjectsBelowConfidence = -1;
544 objectPoses = segment.getObjectPoses(now);
546 segment.decay.removeObjectsBelowConfidence = minConf;
548 objectFinder = segment.objectFinder;
549 if (segment.decay.enabled)
551 visu.minConfidence = segment.decay.removeObjectsBelowConfidence;
555 for (
const auto& [
id, objectPose] : objectPoses)
557 const wm::Entity* entity = segment.findObjectEntity(
id);
558 if (entity !=
nullptr)
563 visu.linearPredictions.timeWindowSeconds),
569 const std::vector<viz::Layer> layers =
570 visu.visualizeCommit(objectPoses, poseHistories, objectFinder);
571 arviz.commit(layers);
579 debugValues[
"t Visualize [ms]"] =
new Variant(tVisu.toMilliSecondsDouble());
580 for (
const auto& [
id, pose] : objectPoses)
582 debugValues[
"confidence(" +
id.str() +
")"] =
new Variant(pose.confidence);
584 debugObserver->setDebugChannel(getName(), debugValues);
588 cycle.waitForCycleDuration();
593 const std::string SegmentAdapter::linearPredictionEngineID =
"Linear Position Regression";
594 const std::vector<PredictionEngine> SegmentAdapter::predictionEngines{{linearPredictionEngineID}};
601 this->visu.setup(adapter.visu);
602 this->segment.setup(adapter.segment);
603 this->decay.setup(adapter.segment.
decay);
604 this->robotHead.setup(adapter.robotHead);
608 this->visu.group, this->segment.group, this->decay.group, this->robotHead.group,
613 group.setLabel(
"Instance");
614 group.addChild(layout);
622 std::scoped_lock lock(adapter.visuMutex);
623 this->visu.update(adapter.visu);
625 this->segment.update(adapter.segment);
627 adapter.segment.
doLocked([
this, &adapter]()
629 this->decay.update(adapter.segment.
decay);
633 std::scoped_lock lock(adapter.robotHeadMutex);
634 this->robotHead.update(adapter.robotHead);