From cbd8d96eae7f277461effd81c36bb3b95b936e92 Mon Sep 17 00:00:00 2001 From: Rainer Kartmann <rainer.kartmann@kit.edu> Date: Mon, 22 Feb 2021 15:30:23 +0100 Subject: [PATCH] Visualize in own thread --- .../ObjectPoseObserver/ObjectPoseObserver.cpp | 168 +++++++++++++----- .../ObjectPoseObserver/ObjectPoseObserver.h | 15 +- 2 files changed, 137 insertions(+), 46 deletions(-) diff --git a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp index 7e0631906..6a317ab27 100644 --- a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp +++ b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.cpp @@ -96,6 +96,14 @@ namespace armarx }); decay.updateTask->start(); } + if (!visu.updateTask) + { + visu.updateTask = new SimpleRunningTask<>([this]() + { + this->visualizeRun(); + }); + visu.updateTask->start(); + } createRemoteGuiTab(); RemoteGui_startRunningTask(); @@ -120,6 +128,7 @@ namespace armarx const std::string& providerName, const objpose::data::ProvidedObjectPoseSeq& providedPoses, const Ice::Current&) { ARMARX_VERBOSE << "Received object poses from '" << providerName << "'."; + TIMING_START(ReportObjectPoses); std::optional<IceUtil::Time> discardUpdatesUntil; bool discardAll = false; @@ -246,6 +255,15 @@ namespace armarx data.objectPoses[providerName] = newObjectPoses; handleProviderUpdate(providerName); + + TIMING_END_STREAM(ReportObjectPoses, ARMARX_VERBOSE); + if (debugObserver) + { + debugObserver->setDebugChannel(getName(), + { + { "ReportObjectPoses [ms]", new Variant(ReportObjectPoses.toMilliSecondsDouble()) }, + }); + } } } @@ -647,73 +665,118 @@ namespace armarx if (visu.enabled) { - visProviderUpdate(providerName); + // Trigger a visu update (we are holding dataMutex). + std::vector<viz::Layer> layers; + visualizeProvider(providerName, data.objectPoses.at(providerName), data.robot, layers); + arviz.commit(layers); } } - void ObjectPoseObserver::visProviderUpdate(const std::string& providerName) + void ObjectPoseObserver::visualizeRun() { - viz::Layer layer = arviz.layer(providerName); + CycleUtil cycle(static_cast<int>(1000 / visu.frequencyHz)); + while (visu.updateTask && !visu.updateTask->isStopped()) + { + TIMING_START(Visu); + if (visu.enabled) + { + std::scoped_lock lock(dataMutex); + visualizeCommit(data.objectPoses, data.robot); + } + if (visu.enabled) + { + TIMING_END_STREAM(Visu, ARMARX_VERBOSE); + if (debugObserver) + { + debugObserver->setDebugChannel(getName(), + { + { "Visualize [ms]", new Variant(Visu.toMilliSecondsDouble()) }, + }); + } + } + cycle.waitForCycleDuration(); + } + } - bool synchronized = false; - for (objpose::ObjectPose& objectPose : data.objectPoses.at(providerName)) + void ObjectPoseObserver::visualizeCommit(std::map<std::string, objpose::ObjectPoseSeq>& objectPoses, VirtualRobot::RobotPtr robot) + { + std::vector<viz::Layer> layers; + for (auto& [name, poses] : objectPoses) { - const armarx::ObjectID id = objectPose.objectID; - std::string key = id.str(); + visualizeProvider(name, poses, robot, layers); + } + arviz.commit(layers); + } + + void ObjectPoseObserver::visualizeProvider( + const std::string& providerName, objpose::ObjectPoseSeq& objectPoses, + VirtualRobot::RobotPtr robot, std::vector<viz::Layer>& layers) + { + viz::Layer& layer = layers.emplace_back(arviz.layer(providerName)); + for (objpose::ObjectPose& objectPose : objectPoses) + { + visualizeObjectPose(layer, objectPose, robot); + } + } + + void ObjectPoseObserver::visualizeObjectPose(viz::Layer& layer, objpose::ObjectPose& objectPose, VirtualRobot::RobotPtr robot) + { + bool synchronized = false; - Eigen::Matrix4f pose = Eigen::Matrix4f::Identity(); + const armarx::ObjectID id = objectPose.objectID; + std::string key = id.str(); - if (data.isAttachedCached(objectPose)) + Eigen::Matrix4f pose = Eigen::Matrix4f::Identity(); + + // TODO: Get this out of visu function. + if (data.isAttachedCached(objectPose)) + { + if (!synchronized) { - if (!synchronized) - { - RobotState::synchronizeLocalClone(data.robot); - synchronized = true; - } - objpose::ObjectPose updated = objectPose.getAttached(data.robot); - pose = visu.inGlobalFrame ? updated.objectPoseGlobal : updated.objectPoseRobot; + RobotState::synchronizeLocalClone(robot); + synchronized = true; } - else + objpose::ObjectPose updated = objectPose.getAttached(robot); + pose = visu.inGlobalFrame ? updated.objectPoseGlobal : updated.objectPoseRobot; + } + else + { + pose = visu.inGlobalFrame ? objectPose.objectPoseGlobal : objectPose.objectPoseRobot; + } + + { + viz::Object object = viz::Object(key).pose(pose); + if (std::optional<ObjectInfo> objectInfo = data.objectFinder.findObject(id)) { - pose = visu.inGlobalFrame ? objectPose.objectPoseGlobal : objectPose.objectPoseRobot; + object.file(objectInfo->package(), objectInfo->simoxXML().relativePath); } - + else { - viz::Object object = viz::Object(key).pose(pose); - if (std::optional<ObjectInfo> objectInfo = data.objectFinder.findObject(id)) - { - object.file(objectInfo->package(), objectInfo->simoxXML().relativePath); - } - else - { - object.fileByObjectFinder(id); - } - if (visu.alphaByConfidence && objectPose.confidence < 1.0f) - { - object.overrideColor(simox::Color::white().with_alpha(objectPose.confidence)); - } - else if (visu.alpha < 1) - { - object.overrideColor(simox::Color::white().with_alpha(visu.alpha)); - } - layer.add(object); + object.fileByObjectFinder(id); } - - if (visu.oobbs && objectPose.localOOBB) + if (visu.alphaByConfidence && objectPose.confidence < 1.0f) { - const simox::OrientedBoxf& oobb = *objectPose.localOOBB; - layer.add(viz::Box(key + " OOBB").set(oobb.transformed(pose)) - .color(simox::Color::lime(255, 64))); + object.overrideColor(simox::Color::white().with_alpha(objectPose.confidence)); } - if (visu.objectFrames) + else if (visu.alpha < 1) { - layer.add(viz::Pose(key + " Pose").pose(pose).scale(visu.objectFramesScale)); + object.overrideColor(simox::Color::white().with_alpha(visu.alpha)); } + layer.add(object); } - arviz.commit(layer); + if (visu.oobbs && objectPose.localOOBB) + { + const simox::OrientedBoxf& oobb = *objectPose.localOOBB; + layer.add(viz::Box(key + " OOBB").set(oobb.transformed(pose)) + .color(simox::Color::lime(255, 64))); + } + if (visu.objectFrames) + { + layer.add(viz::Pose(key + " Pose").pose(pose).scale(visu.objectFramesScale)); + } } objpose::ObjectPoseProviderPrx ObjectPoseObserver::getProviderProxy(const std::string& providerName) @@ -749,6 +812,8 @@ namespace armarx CycleUtil cycle(static_cast<int>(1000 / decay.updateFrequencyHz)); while (decay.updateTask && !decay.updateTask->isStopped()) { + TIMING_START(Decay); + if (decay.enabled) { std::scoped_lock lock(dataMutex); IceUtil::Time now = TimeUtil::GetTime(); @@ -760,6 +825,18 @@ namespace armarx } } } + if (decay.enabled) + { + TIMING_END_STREAM(Decay, ARMARX_VERBOSE); + if (debugObserver) + { + debugObserver->setDebugChannel(getName(), + { + { "Decay Update [ms]", new Variant(Decay.toMilliSecondsDouble()) }, + }); + } + } + cycle.waitForCycleDuration(); } } @@ -923,6 +1000,7 @@ namespace armarx void ObjectPoseObserver::Visu::defineProperties(PropertyDefinitionsPtr defs, const std::string& prefix) { defs->optional(enabled, prefix + "enabled", "Enable or disable visualization of objects."); + defs->optional(frequencyHz, prefix + "frequenzyHz", "Frequency of visualization."); defs->optional(inGlobalFrame, prefix + "inGlobalFrame", "If true, show global poses. If false, show poses in robot frame."); defs->optional(alpha, prefix + "alpha", "Alpha of objects (1 = solid, 0 = transparent)."); defs->optional(alphaByConfidence, prefix + "alphaByConfidence", "If true, use the pose confidence as alpha (if < 1.0)."); diff --git a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h index be40690be..1c4f032ff 100644 --- a/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h +++ b/source/RobotAPI/components/ObjectPoseObserver/ObjectPoseObserver.h @@ -145,7 +145,6 @@ namespace armarx void updateProviderInfo(const std::string& providerName, const objpose::ProviderInfo& info); void handleProviderUpdate(const std::string& providerName); - void visProviderUpdate(const std::string& providerName); objpose::ObjectPoseProviderPrx getProviderProxy(const std::string& providerName); @@ -155,6 +154,16 @@ namespace armarx void decayUpdateRun(); + // Visualization + + void visualizeRun(); + + void visualizeCommit(std::map<std::string, objpose::ObjectPoseSeq>& objectPoses, VirtualRobot::RobotPtr robot); + void visualizeProvider(const std::string& providerName, objpose::ObjectPoseSeq& objectPoses, + VirtualRobot::RobotPtr robot, std::vector<viz::Layer>& layers); + void visualizeObjectPose(viz::Layer& layer, objpose::ObjectPose& objectPose, VirtualRobot::RobotPtr robot); + + private: DebugObserverInterfacePrx debugObserver; @@ -197,6 +206,8 @@ namespace armarx struct Visu { bool enabled = false; + float frequencyHz = 10; + bool inGlobalFrame = true; float alpha = 1.0; bool alphaByConfidence = false; @@ -204,6 +215,8 @@ namespace armarx bool objectFrames = false; float objectFramesScale = 1.0; + SimpleRunningTask<>::pointer_type updateTask; + void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string& prefix = "visu."); }; Visu visu; -- GitLab