RobotGiver.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 * @author Fabian Reister ( fabian dot reister at kit dot edu )
17 * @date 2022
18 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
19 * GNU General Public License
20 */
21
22#include "RobotGiver.h"
23
24#include <VirtualRobot/Robot.h>
25
29
33
35{
36 std::vector<gaze_targets::GazeTarget>
38 {
39 std::vector<gaze_targets::GazeTarget> targets;
40
41 switch (phase_)
42 {
44 targets = updateTargetsPreHandover(human);
45 break;
47 targets = updateTargetsPreHandover(human);
48 break;
49 }
50
51 return targets;
52 }
53
54 std::vector<gaze_targets::GazeTarget>
55 RobotGiver::updateTargetsPreHandover(const armem::human::HumanPose& human) const
56 {
57
58 const auto headKpName = util::headKeypoint(human.poseModelId);
59 const auto pelvisKpName = util::pelvisKeypoint(human.poseModelId);
60 const auto leftWristKpName = util::leftWristKeypoint(human.poseModelId);
61 const auto rightWristKpName = util::rightWristKeypoint(human.poseModelId);
62
63 ARMARX_CHECK(headKpName.has_value());
64 ARMARX_CHECK(leftWristKpName.has_value());
65 ARMARX_CHECK(rightWristKpName.has_value());
66 ARMARX_CHECK(pelvisKpName.has_value());
67
68 std::vector<gaze_targets::GazeTarget> gazeTargets;
69
70 if (human.keypoints.count(headKpName.value()) == 0)
71 {
72 ARMARX_WARNING << deactivateSpam(1) << "Head keypoint `" << headKpName.value()
73 << "` not available!";
74 return {};
75 };
76
77 // head target
78 {
79 const armem::human::PoseKeypoint headKp = human.keypoints.at(headKpName.value());
80
81 const gaze_targets::TargetPriority targetPriority(
83
84 gaze_targets::GazeTarget headTarget(
85 "head", headKp.positionGlobal.value(), targetPriority, Duration::Seconds(1), false);
86 gazeTargets.push_back(headTarget);
87 }
88
89 const armem::human::PoseKeypoint pelvisKp = human.keypoints.at(pelvisKpName.value());
90
91 const float distanceHumanRobot =
92 (pelvisKp.positionGlobal.value().toEigen() - robot_->getGlobalPosition())
93 .head<2>()
94 .norm();
95 ARMARX_VERBOSE << VAROUT(distanceHumanRobot);
96
97 if (distanceHumanRobot > params.maxHandoverInitializationDistance)
98 {
99 return gazeTargets;
100 }
101
102
103 // the priority to look at the humans hands is defined by the distance to the pelvis (2d projection)
104
105 const auto priorityFromDistance =
106 [&](const float handBodyDistance, const float handRobotDistance)
107 {
108 // f = 1: highest priority
109 // f = 0: low prio
110 const float normalizedHandBodyPriority =
111 std::clamp((handBodyDistance - params.minHandReachoutDistance) /
113 0.f,
114 1.f);
115
116 const float normalizedHandRobotPriority = std::clamp(
117 (params.maxHandoverInitializationDistance - handRobotDistance) /
119 0.f,
120 1.f);
121
122 return params.handPriorityScaling * normalizedHandBodyPriority *
123 normalizedHandRobotPriority;
124 };
125
126 // left wrist target
127 if (human.keypoints.count(leftWristKpName.value()) > 0)
128 {
129 const armem::human::PoseKeypoint leftWristKp =
130 human.keypoints.at(leftWristKpName.value());
131
132 const float distanceLeft =
133 (leftWristKp.positionGlobal->toEigen() - pelvisKp.positionGlobal->toEigen()).norm();
134
135 const float handRobotDistance = leftWristKp.positionRobot->toEigen().head<2>().norm();
136
137 const float priority = priorityFromDistance(distanceLeft, handRobotDistance);
138 const gaze_targets::TargetPriority targetPriority(
140
141 gaze_targets::GazeTarget handTarget("left_hand",
142 leftWristKp.positionGlobal.value(),
143 targetPriority,
145 false);
146 gazeTargets.push_back(handTarget);
147 }
148
149 // right wrist target
150 if (human.keypoints.count(rightWristKpName.value()) > 0)
151 {
152 const armem::human::PoseKeypoint rightWristKp =
153 human.keypoints.at(rightWristKpName.value());
154
155 const float distanceRight =
156 (rightWristKp.positionGlobal->toEigen() - pelvisKp.positionGlobal->toEigen())
157 .norm();
158
159 const float handRobotDistance = rightWristKp.positionRobot->toEigen().head<2>().norm();
160
161 const float priority = priorityFromDistance(distanceRight, handRobotDistance);
162
163 const gaze_targets::TargetPriority targetPriority(
165
166 gaze_targets::GazeTarget handTarget("right_hand",
167 rightWristKp.positionGlobal.value(),
168 targetPriority,
170 false);
171 gazeTargets.push_back(handTarget);
172 }
173
174 // combined wrist
175
176 // some debugging
177 {
178 for (const auto& target : gazeTargets)
179 {
180 ARMARX_VERBOSE << target.name << ": " << target.priority;
181 }
182 }
183
184 return gazeTargets;
185 }
186
187 std::vector<gaze_targets::GazeTarget>
188 RobotGiver::updateTargetsAfterHandover(const armem::human::HumanPose& human) const
189 {
190
191 const auto headKpName = util::headKeypoint(human.poseModelId);
192 const auto leftWristKpName = util::leftWristKeypoint(human.poseModelId);
193 const auto rightWristKpName = util::rightWristKeypoint(human.poseModelId);
194
195 ARMARX_CHECK(headKpName.has_value());
196 ARMARX_CHECK(leftWristKpName.has_value());
197 ARMARX_CHECK(rightWristKpName.has_value());
198
199 std::vector<gaze_targets::GazeTarget> gazeTargets;
200
201 if (human.keypoints.count(headKpName.value()) == 0)
202 {
203 ARMARX_WARNING << deactivateSpam(1) << "Head keypoint `" << headKpName.value()
204 << "` not available!";
205 return {};
206 };
207
208 // head target
209 {
210 const armem::human::PoseKeypoint headKp = human.keypoints.at(headKpName.value());
211
212 const gaze_targets::TargetPriority targetPriority(
213 gaze_targets::AttentionType::TaskDriven, params.headPriority);
214
215 gaze_targets::GazeTarget headTarget(
216 "head", headKp.positionGlobal.value(), targetPriority, Duration::Seconds(1), false);
217 gazeTargets.push_back(headTarget);
218 }
219
220 return gazeTargets;
221 }
222
223
224} // namespace armarx::view_selection::target_provider::handover
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
#define VAROUT(x)
static Duration Seconds(std::int64_t seconds)
Constructs a duration in seconds.
Definition Duration.cpp:72
Business Object (BO) class of GazeTarget.
Definition GazeTarget.h:23
std::vector< gaze_targets::GazeTarget > updateTargets(const armem::human::HumanPose &human) override
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#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
@ TaskDriven
Task-Driven attention has highest priority.
std::optional< std::string > pelvisKeypoint(const std::string &poseModelId)
Definition util.cpp:73
std::optional< std::string > headKeypoint(const std::string &poseModelId)
Definition util.cpp:13
std::optional< std::string > rightWristKeypoint(const std::string &poseModelId)
Definition util.cpp:53
std::optional< std::string > leftWristKeypoint(const std::string &poseModelId)
Definition util.cpp:33
This file is part of ArmarX.
Definition Human.cpp:33
Eigen::Vector3f toEigen(const pcl::PointXYZ &pt)
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
double norm(const Point &a)
Definition point.hpp:102
std::optional< armarx::FramedPosition > positionRobot
Definition types.h:35
std::optional< armarx::FramedPosition > positionGlobal
Definition types.h:37
float maxHandoverInitializationDistance
the distance below which the hand targets will be generated.
Definition RobotGiver.h:46