HumanMemory.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package RobotAPI::ArmarXObjects::ExampleMemory
17 * @author Rainer Kartmann ( rainer dot kartmann at kit dot edu )
18 * @date 2020
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#include "HumanMemory.h"
24
26
27#include <algorithm>
28#include <iterator>
29#include <string>
30#include <vector>
31
32#include <Ice/Current.h>
33
34#include <SimoxUtility/algorithm/apply.hpp>
35#include <VirtualRobot/VirtualRobot.h>
36
43#include <ArmarXCore/interface/core/time.h>
44
49#include <RobotAPI/interface/aron/Aron.h>
53
56#include <VisionX/libraries/armem_human/aron/FaceRecognition.aron.generated.h>
57#include <VisionX/libraries/armem_human/aron/HumanPose.aron.generated.h>
58#include <VisionX/libraries/armem_human/aron/Person.aron.generated.h>
60
62{
63
66 {
69
70 setMemoryName("Human");
71
72 profileSegment.defineProperties(defs, "profile.");
73 personInstanceSegment.defineProperties(defs, "instance");
74 poseSegment.defineProperties(defs, "pose.");
75 faceRecognitionSegment.defineProperties(defs, "face.");
76 identificationSegment.defineProperties(defs, "ident.");
77 humanActivitySegment.defineProperties(defs, "activity.");
78 humanRobotInteractionSegment.defineProperties(defs, "interaction.");
79
80 return defs;
81 }
82
84 profileSegment(iceAdapter()),
85 personInstanceSegment(iceAdapter()),
86 poseSegment(iceAdapter()),
87 faceRecognitionSegment(iceAdapter()),
88 identificationSegment(iceAdapter()),
89 humanActivitySegment(iceAdapter()),
90 humanRobotInteractionSegment(iceAdapter()),
91 visu(poseSegment, faceRecognitionSegment, personInstanceSegment)
92 {
93 addPlugin(virtualRobotReaderPlugin);
94 }
95
96 std::string
98 {
99 return "HumanMemory";
100 }
101
102 std::string
104 {
105 return GetDefaultName();
106 }
107
108 void
110 {
111 profileSegment.init();
112 personInstanceSegment.init();
113 poseSegment.init();
114 faceRecognitionSegment.init();
115 identificationSegment.init();
116 humanActivitySegment.init();
117 humanRobotInteractionSegment.init();
118 visu.init();
119
120 workingMemory().addCoreSegment("RecognizedAction");
121 }
122
123 void
125 {
126 visu.connect(arviz, getDebugObserver());
127 }
128
129 void
133
134 void
138
140 HumanMemory::getSynchronizedRobot(const std::string& robotName,
142 {
143 // seach and retrieve robot
144 auto& robot = [&]() -> VirtualRobot::RobotPtr&
145 {
146 // retrieve robot from memory if it is not in cache
147 if (robots.count(robotName) == 0)
148 {
149 auto newRobot = virtualRobotReaderPlugin->get().getRobot(robotName);
150 ARMARX_CHECK_NOT_NULL(newRobot)
151 << "Failed to obtain robot with name `" << robotName << "`.";
152
153 robots[robotName] = newRobot;
154 }
155
156 return robots.at(robotName);
157 }();
158
159 // synchronize robot
160 bool const success = virtualRobotReaderPlugin->get().synchronizeRobot(*robot, timestamp);
161
162 if (not success)
163 {
164 // throw armarx::LocalException(
165 // "Failed synchronizing the robot to calculate the global human pose from a reported "
166 // "human pose in camera coordinate system. Query timestamp is '")
167 // << timestamp << "'.";
168 return nullptr;
169 }
170
171 return robot;
172 }
173
174 void
176 const ::armarx::aron::data::dto::AronDictSeq& dictSeq,
177 const ::std::string& providerName,
178 const ::armarx::core::time::dto::DateTime& iceTimestamp,
179 const ::Ice::Current& /*c*/)
180 {
181 if (dictSeq.empty())
182 {
183 return;
184 }
185
186 // convert from ice
188 fromIce(iceTimestamp, timestamp);
189
190 // convert to our aron type
191 const auto toHumanPose = [](const ::armarx::aron::data::dto::DictPtr& dict)
192 { return armarx::human::arondto::HumanPose::FromAron(dict); };
193
194 std::vector<armarx::human::arondto::HumanPose> humanPoses =
195 simox::alg::apply(dictSeq, toHumanPose);
196
197 // synchronize robot
198 const std::string robotName =
199 humanPoses.front().keypoints.begin()->second.positionCamera.header.agent;
200
201 const auto robot = getSynchronizedRobot(robotName, timestamp);
202
203 if (not robot)
204 {
205 ARMARX_INFO << deactivateSpam(1) << "Failed to obtain robot `" << robotName
206 << "`. Won't commit poses";
207 return;
208 }
209
210 ARMARX_CHECK_NOT_NULL(robot) << "Failed to obtain robot with name `" << robotName << "`.";
211
212 // fill global pose info
213 {
214 for (armarx::human::arondto::HumanPose& humanPose : humanPoses)
215 {
216 for (auto& [_, keyPoint] : humanPose.keypoints)
217 {
218 const auto& cameraFrame = keyPoint.positionCamera.header.frame;
219 const auto& agent = keyPoint.positionCamera.header.agent;
220
221 const FramedPosition keypoint(
222 keyPoint.positionCamera.position, cameraFrame, agent);
223 // ARMARX_IMPORTANT << VAROUT(keyPoint.positionCamera.position.transpose());
224
225 // global pose
226 {
227 keyPoint.positionGlobal = armarx::arondto::FramedPosition();
228 armarx::toAron(keyPoint.positionGlobal.value(),
231 agent));
232 }
233
234 // pose in root frame
235 {
236 keyPoint.positionRobot = armarx::arondto::FramedPosition();
237 armarx::toAron(keyPoint.positionRobot.value(),
238 armarx::FramedPosition(keypoint.toRootEigen(robot),
239 robot->getRootNode()->getName(),
240 agent));
241 }
242
243 // Orientation information available.
244 if (keyPoint.orientationCamera.has_value())
245 {
246 ARMARX_CHECK_EQUAL(keyPoint.orientationCamera->header.frame,
247 keyPoint.positionCamera.header.frame);
248
249 const FramedPose keypointPose(
250 keyPoint.orientationCamera->orientation.toRotationMatrix(),
251 keyPoint.positionCamera.position,
252 cameraFrame,
253 agent);
254
255 // global pose
256 {
257 const Eigen::Isometry3f global_T_human(
258 keypointPose.toGlobalEigen(robot));
259
260 keyPoint.orientationGlobal = armarx::arondto::FramedOrientation();
261
263 keyPoint.orientationGlobal.value(),
264 armarx::FramedOrientation(Eigen::Matrix3f{global_T_human.linear()},
266 agent));
267 }
268
269 // pose in root frame
270 {
271 const Eigen::Isometry3f robot_root_T_human(
272 keypointPose.toRootEigen(robot));
273
274
275 keyPoint.orientationRobot = armarx::arondto::FramedOrientation();
276
277 armarx::toAron(keyPoint.orientationRobot.value(),
279 Eigen::Matrix3f{robot_root_T_human.linear()},
280 robot->getRootNode()->getName(),
281 agent));
282 }
283 }
284 }
285 }
286 }
287
288 // commit human poses
289 commitHumanPoses(humanPoses, providerName, timestamp);
290 }
291
292 void
294 const ::armarx::aron::data::dto::AronDictSeq& dictSeq,
295 const ::std::string& providerName,
296 const ::armarx::core::time::dto::DateTime& iceTimestamp,
297 const ::Ice::Current& /*c*/)
298 {
299 if (dictSeq.empty())
300 {
301 return;
302 }
303
304 // convert from ice
306 fromIce(iceTimestamp, timestamp);
307
308 // convert to our aron type
309 const auto toPersonFace = [](const ::armarx::aron::data::dto::DictPtr& dict)
310 { return armarx::human::arondto::FaceRecognition::FromAron(dict); };
311
312 std::vector<armarx::human::arondto::FaceRecognition> personFaces =
313 simox::alg::apply(dictSeq, toPersonFace);
314
315 // synchronize robot
316 const std::string robotName = "Armar7"; // TODO: Get robot name
317
318 const auto robot = getSynchronizedRobot(robotName, timestamp);
319
320 if (not robot)
321 {
322 ARMARX_INFO << deactivateSpam(1) << "Failed to obtain robot `" << robotName
323 << "`. Won't commit poses";
324 return;
325 }
326
327 ARMARX_CHECK_NOT_NULL(robot) << "Failed to obtain robot with name `" << robotName << "`.";
328
329 // fill global pose info
330 {
331 for (armarx::human::arondto::FaceRecognition& personFace : personFaces)
332 {
334 fromAron(personFace.framedPosition3D, fp);
335 personFace.position3DGlobal = fp.toGlobalEigen(robot);
336 }
337 }
338
339 // commit human poses
340 commitPersonFaces(personFaces, providerName, timestamp);
341 }
342
343 void
345 const std::vector<::armarx::human::arondto::HumanPose>& humanPoses,
346 const std::string& providerName,
348 {
350
351 const auto providerId = armem::MemoryID(
353 const auto entityID = providerId.withEntityName("human_poses").withTimestamp(timestamp);
354
355 armem::EntityUpdate update;
356 update.entityID = entityID;
357 update.sentTime = timestamp; // TODO this is not fully correct
358 update.referencedTime = timestamp;
359
360 std::transform(
361 humanPoses.begin(),
362 humanPoses.end(),
363 std::back_inserter(update.instancesData),
364 [](const ::armarx::human::arondto::HumanPose& humanPose) -> armarx::aron::data::DictPtr
365 { return humanPose.toAron(); });
366
367 commit.add(update);
368
369 ARMARX_DEBUG << "Committing " << update << " at time " << timestamp;
370
372 }
373
374 void
376 const std::vector<::armarx::human::arondto::FaceRecognition>& personFaces,
377 const std::string& providerName,
379 {
381
382 const auto providerId = armem::MemoryID(
384 const auto entityID = providerId.withEntityName("human_poses").withTimestamp(timestamp);
385
386 armem::EntityUpdate update;
387 update.entityID = entityID;
388 update.sentTime = timestamp; // TODO this is not fully correct
389 update.referencedTime = timestamp;
390
391 std::transform(personFaces.begin(),
392 personFaces.end(),
393 std::back_inserter(update.instancesData),
394 [](const ::armarx::human::arondto::FaceRecognition& personFace)
395 -> armarx::aron::data::DictPtr { return personFace.toAron(); });
396
397 commit.add(update);
398
399 ARMARX_DEBUG << "Committing " << update << " at time " << timestamp;
400
402 }
403
404 void
405 HumanMemory::commitHumanProfiles(const ::armarx::aron::data::dto::AronDictSeq& dictSeq,
406 const ::std::string& providerName,
407 const ::armarx::core::time::dto::DateTime& iceTimestamp,
408 const ::std::string& entityName,
409 const ::Ice::Current& /*unused*/)
410 {
411 if (dictSeq.empty())
412 {
413 return;
414 }
415
416 // convert from ice
418 fromIce(iceTimestamp, timestamp);
419
420 // convert to our aron type
421 const auto toHumanProfile = [](const ::armarx::aron::data::dto::DictPtr& dict)
422 { return armarx::human::arondto::Person::FromAron(dict); };
423
424 std::vector<armarx::human::arondto::Person> humanProfiles =
425 simox::alg::apply(dictSeq, toHumanProfile);
426
427 ARMARX_DEBUG << "Collected all information on human profile from ice call"
428 << "\n"
429 << "entityName: " << entityName;
430
431 //call actual commit method
432 this->commitHumanProfilesA(humanProfiles, providerName, timestamp, entityName);
433 }
434
435 void
437 const std::vector<armarx::human::arondto::Person>& humanProfiles,
438 const ::std::string& providerName,
440 const ::std::string& entityName)
441 {
443 const auto providerId = armem::MemoryID(
445 const auto entityID = providerId.withEntityName(entityName).withTimestamp(timestamp);
446
447 armem::EntityUpdate update;
448 update.entityID = entityID;
449 update.sentTime = timestamp; // TODO this is not fully correct
450 update.referencedTime = timestamp;
451
452 for (const auto& humanProfile : humanProfiles)
453 {
454 update.instancesData.push_back(humanProfile.toAron());
455 }
456
457 commit.add(update);
458
459 ARMARX_DEBUG << "Committing " << update << " at time " << timestamp;
460
462 }
463
465} // namespace armarx::armem::server::human_memory
std::string timestamp()
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
Definition Decoupled.h:29
Default component property definition container.
Definition Component.h:70
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition Component.cpp:90
const DebugObserverInterfacePrx & getDebugObserver() const
The FramedOrientation class.
Definition FramedPose.h:216
The FramedPose class.
Definition FramedPose.h:281
Eigen::Matrix4f toGlobalEigen(const SharedRobotInterfacePrx &referenceRobot) const
Eigen::Matrix4f toRootEigen(const SharedRobotInterfacePrx &referenceRobot) const
The FramedPosition class.
Definition FramedPose.h:158
Eigen::Vector3f toGlobalEigen(const SharedRobotInterfacePrx &referenceRobot) const
Eigen::Vector3f toRootEigen(const SharedRobotInterfacePrx &referenceRobot) const
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition Logging.cpp:99
PluginT * addPlugin(const std::string prefix="", ParamsT &&... params)
data::CommitResult commitLocking(const data::Commit &commitIce, Time timeArrived)
static const std::string CORE_SEGMENT_NAME
Definition PoseSegment.h:50
static const std::string CORE_SEGMENT_NAME
Definition Segment.h:38
static const std::string CORE_SEGMENT_NAME
Definition Segment.h:35
void commitHumanProfiles(const ::armarx::aron::data::dto::AronDictSeq &dictSeq, const ::std::string &providerName, const ::armarx::core::time::dto::DateTime &timestamp, const std::string &entityName, const ::Ice::Current &=::Ice::emptyCurrent) override
void onInitComponent() override
Pure virtual hook for the subclass.
void onDisconnectComponent() override
Hook for subclass.
void commitPersonFaces(const std::vector<::armarx::human::arondto::FaceRecognition > &personFaces, const std::string &providerName, const armarx::DateTime &timestamp)
void commitHumanPosesInCameraFrame(const ::armarx::aron::data::dto::AronDictSeq &dictSeq, const ::std::string &providerName, const ::armarx::core::time::dto::DateTime &timestamp, const ::Ice::Current &=::Ice::emptyCurrent) override
VirtualRobot::RobotPtr getSynchronizedRobot(const std::string &robotName, const armarx::DateTime &timestamp)
void commitHumanProfilesA(const std::vector< armarx::human::arondto::Person > &humanProfiles, const ::std::string &providerName, const armarx::DateTime &timestamp, const ::std::string &entityName)
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Creates the property definition container.
void commitPersonFacesInCameraFrame(const ::armarx::aron::data::dto::AronDictSeq &dictSeq, const ::std::string &providerName, const ::armarx::core::time::dto::DateTime &timestamp, const ::Ice::Current &=::Ice::emptyCurrent) override
void onConnectComponent() override
Pure virtual hook for the subclass.
void commitHumanPoses(const std::vector<::armarx::human::arondto::HumanPose > &humanPoses, const std::string &providerName, const armarx::DateTime &timestamp)
void onExitComponent() override
Hook for subclass.
std::string getDefaultName() const override
Retrieve default name of component.
virtual data::CommitResult commit(const data::Commit &commit, const Ice::Current &=Ice::emptyCurrent) override
CoreSegment & addCoreSegment(const std::string &name, Args... args)
Represents a point in time.
Definition DateTime.h:25
#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_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
std::string const GlobalFrame
Variable of the global coordinate system.
Definition FramedPose.h:65
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
void fromIce(const data::MemoryID &ice, MemoryID &id)
void fromAron(const arondto::MemoryID &dto, MemoryID &bo)
std::shared_ptr< Dict > DictPtr
Definition Dict.h:42
void toAron(arondto::PackagePath &dto, const PackageFileLocation &bo)
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
A bundle of updates to be sent to the memory.
Definition Commit.h:90
An update of an entity for a specific point in time.
Definition Commit.h:26