Visualization.cpp
Go to the documentation of this file.
1#include "Visualization.h"
2
3#include <exception>
4#include <map>
5#include <string>
6#include <vector>
7
8#include <Eigen/Geometry>
9
16#include <ArmarXCore/interface/observers/ObserverInterface.h>
17
23
31
33{
34
35 Visu::Visu(const PoseSegment& poseSegment,
36 const FaceRecognitionSegment& faceRecognitionSegment,
37 const PersonInstanceSegment& personInstanceSegment) :
38 poseSegment(poseSegment),
39 faceRecognitionSegment(faceRecognitionSegment),
40 personInstanceSegment(personInstanceSegment)
41 {
42 Logging::setTag("HumanVisualization");
43 }
44
45 void
47 {
48 defs->optional(p.enabled, prefix + "enabled", "Enable or disable visualization of humans.");
49 defs->optional(p.frequencyHz, prefix + "frequenzyHz", "Frequency of visualization.");
50 }
51
52 void
54 {
55 ;
56 }
57
58 void
60 {
61 this->arviz = arviz;
62 if (debugObserver)
63 {
64 bool batchMode = true;
65 this->debugObserver = DebugObserverHelper("HumanMemory", debugObserver, batchMode);
66 }
67
68 if (updateTask)
69 {
70 updateTask->stop();
71 updateTask->join();
72 updateTask = nullptr;
73 }
74 updateTask = new SimpleRunningTask<>([this]() { this->visualizeRun(); });
75 updateTask->start();
76 }
77
78 void
79 Visu::visualizeHumanPoses(armarx::viz::HumanPoseLayers& layers,
80 const std::vector<armarx::armem::human::HumanPose>& humanPoses)
81 {
82 std::string providerName = "azure_kinect"; // TODO: Get actual value.
83
84 std::map<std::string, armarx::armem::human::HumanPose> poseMap;
85 int unknown = 0;
86 for (const armarx::armem::human::HumanPose& humanPose : humanPoses)
87 {
88 if (humanPose.humanTrackingId.has_value())
89 {
90 poseMap[humanPose.humanTrackingId.value()] = humanPose;
91 }
92 else
93 {
94 // ARMARX_WARNING << "Found unknown human id...";
95 poseMap["unknown_human_" + std::to_string(unknown++)] = humanPose;
96 }
97 }
98
99 armarx::viz::addPosesToLayer(poseMap, layers, providerName);
100 }
101
102 void
103 Visu::visualizeFaceRecognitions(
104 armarx::viz::Layer& faceRecognitionLayer,
105 const std::vector<armarx::armem::human::FaceRecognition>& faceRecognitions)
106 {
107 std::string providerName = "azure_kinect"; // TODO: Get actual value.
108
109 std::map<std::string, armarx::armem::human::FaceRecognition> faceRecognitionMap;
110 int unknown = 0;
111 for (const armarx::armem::human::FaceRecognition& faceRecognition : faceRecognitions)
112 {
113 if (faceRecognition.profileID.has_value())
114 {
115 faceRecognitionMap[faceRecognition.profileID.value().entityName] = faceRecognition;
116 }
117 else
118 {
119 // ARMARX_WARNING << "Found unknown human id...";
120 faceRecognitionMap["unknown_face_" + std::to_string(unknown++)] = faceRecognition;
121 }
122 }
123 if (faceRecognitionMap.size() == 0)
124 {
125 return;
126 }
127
129 faceRecognitionLayer,
130 providerName);
131 }
132
133 void
134 Visu::visualizePersonInstances(
135 armarx::viz::Layer& personInstanceLayer,
136 const std::vector<armarx::armem::human::PersonInstance>& personInstances)
137 {
138 std::string providerName = "person_instanciator"; // TODO: Get actual value.
139
140 std::map<std::string, armarx::armem::human::PersonInstance> personInstanceMap;
141 for (const armarx::armem::human::PersonInstance& personInstance : personInstances)
142 {
143 personInstanceMap[personInstance.profileID.entityName] = personInstance;
144 }
145 if (personInstanceMap.empty())
146 {
147 return;
148 }
149 for (const auto& [name, personInstance] : personInstanceMap)
150 {
151 ARMARX_VERBOSE << VAROUT(name);
152 // armarx::armem::human::FaceRecognition faceReco =
153 // faceRecognitionSegment.getFaceRecognition(personInstance.faceRecognitionID);
155 name,
156 personInstanceLayer,
157 providerName);
158 }
159 }
160
161 void
162 Visu::visualizeRun()
163 {
164 armarx::Metronome metronome{armarx::Frequency::Hertz(p.frequencyHz)};
165 while (updateTask and not updateTask->isStopped())
166 {
167 if (p.enabled)
168 {
169 const Time timestamp = Time::Now();
171
172 try
173 {
174 visualizeOnce(timestamp);
175 }
176 catch (const std::exception& e)
177 {
178 ARMARX_WARNING << "Caught exception while visualizing robots: \n" << e.what();
179 }
180 catch (...)
181 {
182 ARMARX_WARNING << "Caught unknown exception while visualizing robots.";
183 }
184
185 if (debugObserver.has_value())
186 {
187 debugObserver->sendDebugObserverBatch();
188 }
189 }
190 metronome.waitForNextTick();
191 }
192 }
193
194 void
195 Visu::visualizeOnce(const Time& timestamp)
196 {
197 TIMING_START(tVisuTotal);
198
199 // TODO(fabian.reister): use timestamp
200
201 const Duration maxAge = Duration::MilliSeconds(2000);
202
203 // Get data.
204 TIMING_START(tVisuGetData);
205
206 TIMING_START(tRobotDescriptions);
207 const std::map<std::string, std::vector<armarx::armem::human::HumanPose>>
208 humanPosesPerProvider = poseSegment.getHumanPoseEntities(maxAge);
209 const std::map<std::string, std::vector<armarx::armem::human::FaceRecognition>>
210 faceRecognitionsPerProvider = faceRecognitionSegment.getFaceRecognitionEntities(maxAge);
211 const std::map<std::string, std::vector<armarx::armem::human::PersonInstance>>
212 personInstancesPerProvider = personInstanceSegment.getPersonInstanceEntities(maxAge);
213 TIMING_END_STREAM(tRobotDescriptions, ARMARX_DEBUG);
214
215 TIMING_END_STREAM(tVisuGetData, ARMARX_DEBUG);
216
217 // Build layers.
218 TIMING_START(tVisuBuildLayers);
219
220 std::vector<viz::Layer> providerLayers;
221 for (const auto& [providerName, humanPoses] : humanPosesPerProvider)
222 {
223 viz::Layer layerSkeleton = arviz.layer("HumanPoses_" + providerName);
224 viz::Layer layerFrames = arviz.layer("HumanPoses_" + providerName + "_Frames");
225 armarx::viz::HumanPoseLayers layers{.skeleton = layerSkeleton, .frames = layerFrames};
226
227 visualizeHumanPoses(layers, humanPoses);
228 providerLayers.push_back(layerSkeleton);
229 providerLayers.push_back(layerFrames);
230 }
231 for (const auto& [providerName, faceRecognitions] : faceRecognitionsPerProvider)
232 {
233 viz::Layer faceRecognitionLayer = arviz.layer("FaceRecognitions_" + providerName);
234 visualizeFaceRecognitions(faceRecognitionLayer, faceRecognitions);
235 providerLayers.push_back(faceRecognitionLayer);
236 }
237 for (const auto& [providerName, personInstances] : personInstancesPerProvider)
238 {
239 viz::Layer personInstanceLayer = arviz.layer("PersonInstances_" + providerName);
240 visualizePersonInstances(personInstanceLayer, personInstances);
241 providerLayers.push_back(personInstanceLayer);
242 }
243
244 TIMING_END_STREAM(tVisuBuildLayers, ARMARX_DEBUG);
245
246 // Commit layers.
247
248 ARMARX_DEBUG << "Commit visualization ...";
249 TIMING_START(tVisuCommit);
250 arviz.commit(providerLayers);
251 TIMING_END_STREAM(tVisuCommit, ARMARX_DEBUG);
252
253 TIMING_END_STREAM(tVisuTotal, ARMARX_DEBUG);
254
255 if (debugObserver.has_value())
256 {
257 const std::string p = "Visu | ";
258 debugObserver->setDebugObserverDatafield(p + "t Total (ms)",
259 tVisuTotal.toMilliSecondsDouble());
260 debugObserver->setDebugObserverDatafield(p + "t 1 Get Data (ms)",
261 tVisuGetData.toMilliSecondsDouble());
262 debugObserver->setDebugObserverDatafield(p + "t 1.1 Descriptions (ms)",
263 tRobotDescriptions.toMilliSecondsDouble());
264
265 debugObserver->setDebugObserverDatafield(p + "t 2 Build Layers (ms)",
266 tVisuBuildLayers.toMilliSecondsDouble());
267 debugObserver->setDebugObserverDatafield(p + "t 3 Commit (ms)",
268 tVisuCommit.toMilliSecondsDouble());
269 }
270 }
271
272} // namespace armarx::armem::server::human
std::string timestamp()
#define VAROUT(x)
Brief description of class DebugObserverHelper.
static Frequency Hertz(std::int64_t hertz)
Definition Frequency.cpp:20
void setTag(const LogTag &tag)
Definition Logging.cpp:54
void defineProperties(armarx::PropertyDefinitionsPtr defs, const std::string &prefix="visu.")
Visu(const PoseSegment &poseSegment, const FaceRecognitionSegment &faceRecognitionSegment, const PersonInstanceSegment &personInstanceSegment)
void connect(const viz::Client &arviz, DebugObserverInterfacePrx debugObserver=nullptr)
static DateTime Now()
Definition DateTime.cpp:51
static Duration MilliSeconds(std::int64_t milliSeconds)
Constructs a duration in milliseconds.
Definition Duration.cpp:48
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
#define TIMING_START(name)
Helper macro to do timing tests.
Definition TimeUtil.h:289
#define TIMING_END_STREAM(name, os)
Prints duration.
Definition TimeUtil.h:310
facerecog::Segment FaceRecognitionSegment
Definition Segment.h:66
armarx::core::time::DateTime Time
armarx::core::time::Duration Duration
std::string toStringMilliSeconds(const Time &time, int decimals=3)
Returns time as e.g.
Definition Time.cpp:11
void addFaceRecognitionsToLayer(const std::map< std::string, armarx::armem::human::FaceRecognition > &faceRecognitions, armarx::viz::Layer &faceRecognitionLayer, const std::string &prefix)
void addPosesToLayer(const std::map< std::string, armarx::armem::human::HumanPose > &poses, HumanPoseLayers &layers, const std::string &prefix, const DrawingStyle &drawingStyle=DrawingStyle())
Definition HumanPose.cpp:47
void addPersonInstanceToLayer(const armarx::armem::human::FaceRecognition &faceReco, const std::string &name, armarx::viz::Layer &personInstanceLayer, const std::string &prefix)
::IceInternal::ProxyHandle<::IceProxy::armarx::DebugObserverInterface > DebugObserverInterfacePrx
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
SimpleRunningTask(Ts...) -> SimpleRunningTask< std::function< void(void)> >