RobotReceiver.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 "RobotReceiver.h"
23 
24 #include <Eigen/Core>
25 
26 #include <VirtualRobot/Robot.h>
27 
30 
32 
34 
36 {
37  RobotReceiver::RobotReceiver(const std::string& humanTrackingId,
38  const VirtualRobot::RobotPtr& robot) :
39  HandoverTargetProvider(humanTrackingId, robot)
40  {
41  }
42 
43  std::vector<gaze_targets::GazeTarget>
45  {
46  std::vector<gaze_targets::GazeTarget> targets;
47 
48  switch (phase_)
49  {
50  case Phase::PreHandover:
52  break;
55  break;
56  }
57 
58  return targets;
59  }
60 
61  std::vector<gaze_targets::GazeTarget>
63  {
64 
65  const auto headKpName = util::headKeypoint(human.poseModelId);
66  const auto pelvisKpName = util::pelvisKeypoint(human.poseModelId);
67  const auto leftWristKpName = util::leftWristKeypoint(human.poseModelId);
68  const auto rightWristKpName = util::rightWristKeypoint(human.poseModelId);
69 
70  ARMARX_CHECK(headKpName.has_value());
71  ARMARX_CHECK(leftWristKpName.has_value());
72  ARMARX_CHECK(rightWristKpName.has_value());
73  ARMARX_CHECK(pelvisKpName.has_value());
74 
75  std::vector<gaze_targets::GazeTarget> gazeTargets;
76 
77  if (human.keypoints.count(headKpName.value()) == 0)
78  {
79  ARMARX_WARNING << deactivateSpam(1) << "Head keypoint `" << headKpName.value()
80  << "` not available!";
81  return {};
82  };
83 
84  // head target
85  {
86  const armem::human::PoseKeypoint headKp = human.keypoints.at(headKpName.value());
87 
88  const gaze_targets::TargetPriority targetPriority(
90 
91  gaze_targets::GazeTarget headTarget(
92  "head", headKp.positionGlobal.value(), targetPriority, Duration::Seconds(1), false);
93  gazeTargets.push_back(headTarget);
94  }
95 
96  const armem::human::PoseKeypoint pelvisKp = human.keypoints.at(pelvisKpName.value());
97 
98  const float distanceHumanRobot =
99  (pelvisKp.positionGlobal.value().toEigen() - robot_->getGlobalPosition())
100  .head<2>()
101  .norm();
102  ARMARX_VERBOSE << VAROUT(distanceHumanRobot);
103 
104  if (distanceHumanRobot > params.maxHandoverInitializationDistance)
105  {
106  return gazeTargets;
107  }
108 
109 
110  // the priority to look at the humans hands is defined by the distance to the pelvis (2d projection)
111 
112  const auto handPriorityFromDistance =
113  [&](const float handBodyDistance, const float handRobotDistance)
114  {
115  // f = 1: highest priority
116  // f = 0: low prio
117  const float normalizedHandBodyPriority =
118  std::clamp((handBodyDistance - params.minHandReachoutDistance) /
120  0.f,
121  1.f);
122 
123  // f = 1: highest priority
124  // f = 0: low prio
125  const float normalizedHandRobotPriority = std::clamp(
126  (params.maxHandoverInitializationDistance - handRobotDistance) /
128  0.f,
129  1.f);
130 
131  return params.handPriorityScaling * normalizedHandBodyPriority *
132  normalizedHandRobotPriority;
133  };
134 
135  const auto handsPriorityFromDistance = [&](const float handsRobotDistance)
136  {
137  return handsRobotDistance < params.maxHandsInitializationDistance
138  ? (params.headPriority + 1)
139  : 0;
140  };
141 
142 
143  // left wrist target
144  if (human.keypoints.count(leftWristKpName.value()) > 0)
145  {
146  const armem::human::PoseKeypoint leftWristKp =
147  human.keypoints.at(leftWristKpName.value());
148 
149  const float distanceLeft =
150  (leftWristKp.positionGlobal->toEigen() - pelvisKp.positionGlobal->toEigen()).norm();
151 
152  const float handRobotDistance = leftWristKp.positionRobot->toEigen().head<2>().norm();
153 
154  const float priority = handPriorityFromDistance(distanceLeft, handRobotDistance);
155  const gaze_targets::TargetPriority targetPriority(
157 
158  gaze_targets::GazeTarget handTarget("left_hand",
159  leftWristKp.positionGlobal.value(),
160  targetPriority,
162  false);
163  gazeTargets.push_back(handTarget);
164  }
165 
166  // right wrist target
167  if (human.keypoints.count(rightWristKpName.value()) > 0)
168  {
169  const armem::human::PoseKeypoint rightWristKp =
170  human.keypoints.at(rightWristKpName.value());
171 
172  const float distanceRight =
173  (rightWristKp.positionGlobal->toEigen() - pelvisKp.positionGlobal->toEigen())
174  .norm();
175 
176  const float handRobotDistance = rightWristKp.positionRobot->toEigen().head<2>().norm();
177 
178  const float priority = handPriorityFromDistance(distanceRight, handRobotDistance);
179 
180  const gaze_targets::TargetPriority targetPriority(
182 
183  gaze_targets::GazeTarget handTarget("right_hand",
184  rightWristKp.positionGlobal.value(),
185  targetPriority,
187  false);
188  gazeTargets.push_back(handTarget);
189  }
190 
191  // In addition to the individual hand targets, we create one target for the center point of both hands
192  // This will lower the gaze target and the head won't need to move too much once an arm is streched out.
193  {
194  const armem::human::PoseKeypoint leftWristKp =
195  human.keypoints.at(leftWristKpName.value());
196  const armem::human::PoseKeypoint rightWristKp =
197  human.keypoints.at(rightWristKpName.value());
198 
199  const float alpha = 0.5; // might be improved in the future
200 
201  const Eigen::Vector3f centerHandsPosition =
202  leftWristKp.positionGlobal->toEigen() +
203  alpha * (rightWristKp.positionGlobal->toEigen() -
204  leftWristKp.positionGlobal->toEigen());
205 
206  const float centerHandsRobotDistance =
207  (centerHandsPosition - robot_->getGlobalPosition()).head<2>().norm();
208 
209  const float priority = handsPriorityFromDistance(centerHandsRobotDistance);
210 
211  const gaze_targets::TargetPriority targetPriority(
213 
214  const std::string& agent = leftWristKp.positionGlobal->agent;
215 
216  gaze_targets::GazeTarget handsTarget(
217  "center_hands",
218  FramedPosition(centerHandsPosition, GlobalFrame, agent),
219  targetPriority,
221  false);
222  gazeTargets.push_back(handsTarget);
223  }
224 
225  // combined wrist
226 
227  // some debugging
228  {
229  for (const auto& target : gazeTargets)
230  {
231  ARMARX_VERBOSE << target.name << ": " << target.priority;
232  }
233  }
234 
235  return gazeTargets;
236  }
237 
238  std::vector<gaze_targets::GazeTarget>
240  {
241 
242  const auto headKpName = util::headKeypoint(human.poseModelId);
243  const auto leftWristKpName = util::leftWristKeypoint(human.poseModelId);
244  const auto rightWristKpName = util::rightWristKeypoint(human.poseModelId);
245 
246  ARMARX_CHECK(headKpName.has_value());
247  ARMARX_CHECK(leftWristKpName.has_value());
248  ARMARX_CHECK(rightWristKpName.has_value());
249 
250  std::vector<gaze_targets::GazeTarget> gazeTargets;
251 
252  if (human.keypoints.count(headKpName.value()) == 0)
253  {
254  ARMARX_WARNING << deactivateSpam(1) << "Head keypoint `" << headKpName.value()
255  << "` not available!";
256  return {};
257  };
258 
259  // head target
260  {
261  const armem::human::PoseKeypoint headKp = human.keypoints.at(headKpName.value());
262 
263  const gaze_targets::TargetPriority targetPriority(
265 
266  gaze_targets::GazeTarget headTarget(
267  "head", headKp.positionGlobal.value(), targetPriority, Duration::Seconds(1), false);
268  gazeTargets.push_back(headTarget);
269  }
270 
271  return gazeTargets;
272  }
273 
274 } // namespace armarx::view_selection::target_provider::handover
armarx::view_selection::target_provider::handover::util::rightWristKeypoint
std::optional< std::string > rightWristKeypoint(const std::string &poseModelId)
Definition: util.cpp:53
armarx::view_selection::target_provider::handover::Phase::PreHandover
@ PreHandover
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
armarx::targets
Brief description of class targets.
Definition: targets.h:38
armarx::view_selection::target_provider::handover::RobotReceiver::Params::minHandReachoutDistance
float minHandReachoutDistance
Definition: RobotReceiver.h:49
armarx::view_selection::target_provider::handover::util::leftWristKeypoint
std::optional< std::string > leftWristKeypoint(const std::string &poseModelId)
Definition: util.cpp:33
armarx::view_selection::target_provider::handover
This file is part of ArmarX.
Definition: HandoverTargetProvider.cpp:3
armarx::view_selection::target_provider::handover::HandoverTargetProvider
Definition: HandoverTargetProvider.h:34
armarx::GlobalFrame
const std::string GlobalFrame
Definition: FramedPose.h:65
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:668
armarx::view_selection::target_provider::handover::RobotReceiver::Params::headPriority
float headPriority
Definition: RobotReceiver.h:54
armarx::view_selection::target_provider::handover::HandoverTargetProvider::robot_
const VirtualRobot::RobotPtr robot_
Definition: HandoverTargetProvider.h:49
armarx::view_selection::gaze_targets::GazeTarget
Business Object (BO) class of GazeTarget.
Definition: GazeTarget.h:39
util.h
ARMARX_CHECK
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
Definition: ExpressionException.h:82
armarx::view_selection::target_provider::handover::util::pelvisKeypoint
std::optional< std::string > pelvisKeypoint(const std::string &poseModelId)
Definition: util.cpp:73
clamp
double clamp(double x, double a, double b)
Definition: point.hpp:136
armarx::view_selection::gaze_targets::AttentionType::TaskDriven
@ TaskDriven
Task-Driven attention has highest priority.
armarx::view_selection::target_provider::handover::util::headKeypoint
std::optional< std::string > headKeypoint(const std::string &poseModelId)
Definition: util.cpp:13
deactivateSpam
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition: Logging.cpp:75
armarx::armem::human::HumanPose::poseModelId
std::string poseModelId
Definition: types.h:32
armarx::view_selection::target_provider::handover::RobotReceiver::Params::maxHandReachoutDistance
float maxHandReachoutDistance
Definition: RobotReceiver.h:50
armarx::view_selection::target_provider::handover::RobotReceiver::Params::minHandoverDistance
float minHandoverDistance
Definition: RobotReceiver.h:56
armarx::armem::human::PoseKeypoint::positionRobot
std::optional< armarx::FramedPosition > positionRobot
Definition: types.h:24
armarx::core::time::Duration::Seconds
static Duration Seconds(std::int64_t seconds)
Constructs a duration in seconds.
Definition: Duration.cpp:72
armarx::armem::human::PoseKeypoint
Definition: types.h:17
FramedPose.h
RobotReceiver.h
armarx::view_selection::target_provider::handover::RobotReceiver::Params::maxHandoverInitializationDistance
float maxHandoverInitializationDistance
the distance below which the hand targets will be generated.
Definition: RobotReceiver.h:45
armarx::armem::human::HumanPose
Definition: types.h:30
armarx::view_selection::target_provider::handover::HandoverTargetProvider::phase_
Phase phase_
Definition: HandoverTargetProvider.h:51
ExpressionException.h
armarx::view_selection::target_provider::handover::RobotReceiver::RobotReceiver
RobotReceiver(const std::string &humanTrackingId, const VirtualRobot::RobotPtr &robot)
Definition: RobotReceiver.cpp:37
armarx::view_selection::target_provider::handover::RobotReceiver::Params::handPriorityScaling
float handPriorityScaling
Definition: RobotReceiver.h:52
armarx::view_selection::target_provider::handover::RobotReceiver::Params::maxHandsInitializationDistance
float maxHandsInitializationDistance
Definition: RobotReceiver.h:47
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:198
armarx::armem::human::PoseKeypoint::positionGlobal
std::optional< armarx::FramedPosition > positionGlobal
Definition: types.h:26
armarx::armem::human::HumanPose::keypoints
KeyPointMap keypoints
Definition: types.h:35
Logging.h
armarx::VariantType::FramedPosition
const VariantTypeId FramedPosition
Definition: FramedPose.h:38
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::view_selection::gaze_targets::TargetPriority
The Priority of a GazeTarget.
Definition: TargetPriority.h:39
armarx::view_selection::target_provider::handover::RobotReceiver::updateTargetsPreHandover
std::vector< gaze_targets::GazeTarget > updateTargetsPreHandover(const armem::human::HumanPose &human) const
Definition: RobotReceiver.cpp:62
armarx::view_selection::target_provider::handover::RobotReceiver::params
const Params params
Definition: RobotReceiver.h:72
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:19
armarx::view_selection::target_provider::handover::Phase::PostHandover
@ PostHandover
armarx::view_selection::target_provider::handover::RobotReceiver::updateTargetsAfterHandover
std::vector< gaze_targets::GazeTarget > updateTargetsAfterHandover(const armem::human::HumanPose &human) const
Definition: RobotReceiver.cpp:239
armarx::view_selection::target_provider::handover::RobotReceiver::updateTargets
std::vector< gaze_targets::GazeTarget > updateTargets(const armem::human::HumanPose &human) override
Definition: RobotReceiver.cpp:44
norm
double norm(const Point &a)
Definition: point.hpp:102