LookAtHumanFace.cpp
Go to the documentation of this file.
1#include "LookAtHumanFace.h"
2
3#include <memory>
4#include <optional>
5#include <vector>
6
7#include <Eigen/Core>
8#include <Eigen/Geometry>
9#include <Eigen/src/Core/Matrix.h>
10
15
23
25#include <armarx/view_selection/gaze_targets/aron/AttentionType.aron.generated.h>
30
31#include <VisionX/libraries/armem_human/aron/HumanPose.aron.generated.h>
34
36{
38 {
39 srv_.emplace(srv);
40 }
41
43 LookAtHumanFace::init(const Base::SpecializedInitInput& in)
44 {
45 // initialize variables; store which human to follow
46
47 fromAron(in.parameters.humanTrackingId, humanTrackingId);
48
49 handoverTargetProvider = std::make_unique<target_provider::handover::RobotReceiver>(
50 humanTrackingId, srv_->robot);
51 handoverTargetProvider->setPhase(target_provider::handover::Phase::PostHandover);
52
53 return ::armarx::skills::Skill::InitResult{
55 }
56
58 LookAtHumanFace::main(const Base::SpecializedMainInput& in)
59 {
60 // repeatedly update the robot's gaze target to follow the requested human
61 // (method is blocking, as intended for skills)
62
63 const auto tsStart = armarx::Clock::Now();
64
65 // setup metronome to control execution frequency
66 const auto metronomeTargetPeriod =
67 armarx::Duration::MilliSecondsDouble(properties.updatePeriodMs);
68 armarx::Metronome metronome(metronomeTargetPeriod);
69
70 while (not shouldSkillTerminate() and not stop_requested_)
71 {
72 // update the view target based on the current pose of the human
73 ARMARX_VERBOSE << "Before update";
74 update();
75 ARMARX_VERBOSE << "After update";
76
77 metronome.waitForNextTick();
78
79 if ((armarx::Clock::Now() - tsStart) > in.parameters.timeout)
80 {
81 ARMARX_INFO << "Timeout (skill parameter " << in.parameters.timeout << " ) reached";
82 break;
83 }
84 }
85
86 ARMARX_INFO << "Successfully finished skill";
87
88 return ::armarx::skills::Skill::MainResult{
90 }
91
92 void
93 LookAtHumanFace::update()
94 {
95 std::optional<armem::human::HumanPose> latestPoseOfRequestedHuman =
96 getLatestPoseOfRequestedHuman();
97
98 if (latestPoseOfRequestedHuman.has_value())
99 {
100 // updateTargetsAfterHandover generates targets to look at the head
101 std::vector<gaze_targets::GazeTarget> gazeTargets =
102 handoverTargetProvider->updateTargetsAfterHandover(
103 latestPoseOfRequestedHuman.value());
104
105
106
107 auto in = getParameters();
108 for (auto& gazeTarget : gazeTargets)
109 {
110 gazeTarget.priority.priority = in.priority;
111 if (in.zOffset.has_value())
112 {
113 gazeTarget.position.z += in.zOffset.value();
114 // Eigen::Vector3f pos = gazeTarget.position.toEigen();
115 // pos.z() += getParameters().zOffset.value();
116 // gazeTarget.position = FramedPosition(pos, gazeTarget.position.frame, gazeTarget.position.agent);
117 }
118 fromAron(getParameters().attentionType, gazeTarget.priority.attentionType);
119
120 ARMARX_VERBOSE << "Committing gaze target " << gazeTarget;
121 }
122 srv_->viewSelectionClient.commitGazeTargets(gazeTargets);
123 }
124 else
125 {
126 ARMARX_VERBOSE << "Did not find any pose for the requested human tracking ID";
127 }
128 }
129
130 std::optional<armem::human::HumanPose>
131 LookAtHumanFace::getLatestPoseOfRequestedHuman()
132 {
133 // get the current pose of the human
135 builder.coreSegments()
136 .withName(srv_->humanPoseMemoryID.coreSegmentName)
138 .all()
139 .entities()
140 .all()
141 .snapshots()
142 .latest();
143 armem::client::QueryResult result =
144 srv_->memoryNameSystem.getReader(srv_->humanPoseMemoryID)
145 .query(builder.buildQueryInput());
146
147 std::optional<armem::human::HumanPose> latestPoseOfRequestedHuman = std::nullopt;
148 if (result.success)
149 {
150 result.memory.forEachInstance(
151 [this, &latestPoseOfRequestedHuman](const armem::wm::EntityInstance& instance)
152 {
153 armem::human::HumanPose humanPose;
154 armarx::human::arondto::HumanPose dto =
155 armarx::human::arondto::HumanPose::FromAron(instance.data());
156 fromAron(dto, humanPose);
157 if (humanPose.humanTrackingId == humanTrackingId &&
158 (!latestPoseOfRequestedHuman.has_value() ||
159 humanPose.timestamp > latestPoseOfRequestedHuman->timestamp))
160 {
161 latestPoseOfRequestedHuman = humanPose;
162 }
163 });
164 }
165 else
166 {
167 ARMARX_WARNING << "Failed to query the human memory: " << result.errorMessage;
168 }
169 return latestPoseOfRequestedHuman;
170 }
171
172 void
173 LookAtHumanFace::onStopRequested()
174 {
175 ARMARX_INFO << "Stop requested";
176 stop_requested_ = true;
177 }
178
179 armarx::skills::SkillDescription
181 {
182 using armarx::view_selection::gaze_targets::arondto::AttentionType;
183
184 ParamType defaultParameters;
185 defaultParameters.priority = 1; //lowest possible priority
186 defaultParameters.attentionType = AttentionType::TaskDriven;
187 defaultParameters.timeout = armarx::Duration::Seconds(60);
188 defaultParameters.zOffset = std::nullopt;
189
191 .skillId = {.skillName = constants::skill_names::LookAtHumanFace},
192 .description = "Look at the face of a human specified by their tracking ID.",
193 .rootProfileDefaults = defaultParameters.toAron(),
195 .parametersType = Params::ToAronType()};
196 }
197} // namespace armarx::view_selection::skills
static DateTime Now()
Current time on the virtual clock.
Definition Clock.cpp:93
static Duration Seconds(std::int64_t seconds)
Constructs a duration in seconds.
Definition Duration.cpp:72
static Duration MilliSecondsDouble(double milliSeconds)
Constructs a duration in milliseconds.
Definition Duration.cpp:54
CoreSegmentSelector & coreSegments()
Start specifying core segments.
Definition Builder.cpp:42
CoreSegmentSelector & withName(const std::string &name) override
ProviderSegmentSelector & providerSegments()
Start specifying provider segments.
SnapshotSelector & snapshots()
Start specifying entity snapshots.
Definition selectors.cpp:92
EntitySelector & entities()
Start specifying entities.
ProviderSegmentSelector & all() override
static Duration Seconds(std::int64_t seconds)
Constructs a duration in seconds.
Definition Duration.cpp:72
Simple rate limiter for use in loops to maintain a certain frequency given a clock.
Definition Metronome.h:57
bool shouldSkillTerminate() const override
Returns whether the skill should terminate as soon as possible.
Definition Skill.cpp:469
::armarx::skills::SimpleSpecializedSkill< Params > Base
static armarx::skills::SkillDescription DefaultSkillDescription()
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#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
This file is part of ArmarX.
Definition constants.cpp:26
void fromAron(const arondto::PackagePath &dto, PackageFileLocation &bo)
wm::Memory memory
The slice of the memory that matched the query.
Definition Query.h:58
std::optional< std::string > humanTrackingId
Definition types.h:47
A result struct for skill initialization.
Definition Skill.h:50
A result struct for th main method of a skill.
Definition Skill.h:62