35 #include <VirtualRobot/Nodes/RobotNode.h>
36 #include <VirtualRobot/XML/RobotIO.h>
39 #include <Ice/Current.h>
56 m_onlyUseFirstNResults(-1),
58 m_human_confidence_filter_value(0.3),
59 m_min_velocity_treshold(15),
80 const unsigned int periodic_task_interval = 100;
84 m_check_human_task->start();
95 m_check_human_task->stop();
111 const armarx::HumanPose3DMap& kpml,
116 if (m_onlyUseFirstNResults == 0)
121 if (m_onlyUseFirstNResults > 0)
123 m_onlyUseFirstNResults--;
129 std::lock_guard l{m_enabled_mutex};
130 if (not m_enabled or kpml.empty())
135 ARMARX_DEBUG <<
"TIme delta: " << start - IceUtil::Time::microSeconds(timestamp);
138 std::lock_guard l{m_human_mutex};
139 const IceUtil::Time time = IceUtil::Time::microSeconds(timestamp);
143 std::vector<Keypoint3DMap> legacy_kpml;
144 for (
const auto& [name, entity] : kpml)
146 legacy_kpml.push_back(entity.keypointMap);
149 const OpenPoseResult closestHuman = find_closest_human(legacy_kpml, time);
152 if (not closestHuman.valid)
157 if (closestHuman.distance < m_warn_distance)
163 HumanApproximation human = approximate_human(closestHuman);
168 m_obstacle_manager->directly_update_obstacle(
"human", Eigen::Vector2f(human.posX, human.posY), human.axisLengthX, human.axisLengthY, human.yaw);
171 ARMARX_DEBUG <<
"Drawing Human Obsacle at position (" << human.posX <<
", " << human.posY <<
"). Needed time: " << IceUtil::Time::now() - start;
175 HumanObstacleDetection::OpenPoseResult
176 HumanObstacleDetection::find_closest_human(
177 const std::vector<Keypoint3DMap>& kpml,
181 OpenPoseResult closest_human;
182 closest_human.mean_position = Eigen::Vector3f(0, 0, 0);
183 closest_human.timestamp = timestamp;
185 closest_human.confidence = 0.0;
186 closest_human.index = -1;
187 closest_human.valid =
false;
189 for (
unsigned int i = 0; i < kpml.size(); ++i)
193 Eigen::Vector3f sum_positions(0, 0, 0);
194 float sum_distance = 0;
195 float sum_confidence = 0;
198 for (
const auto& [key,
value] : kpm)
202 sum_confidence +=
value.confidence;
203 sum_positions += Eigen::Vector3f(
value.globalX,
value.globalY,
value.globalZ);
204 sum_distance +=
value.z;
214 const Eigen::Vector3f mean_position = sum_positions * (1.0 / amount);
215 const float mean_confidence = sum_confidence / amount;
216 const float mean_distance = sum_distance / amount;
217 ARMARX_DEBUG <<
"Found a human at a distance of " << sum_distance <<
"mm with confidence " << mean_confidence <<
".";
219 if (sum_distance < closest_human.distance and mean_confidence >= m_human_confidence_filter_value)
221 closest_human.mean_position = mean_position;
222 closest_human.distance = mean_distance;
223 closest_human.index = i;
224 closest_human.keypoints = kpml[i];
225 closest_human.confidence = mean_confidence;
226 closest_human.valid =
true;
230 return closest_human;
234 HumanObstacleDetection::HumanApproximation
235 HumanObstacleDetection::approximate_human(
const OpenPoseResult& closest_human)
239 std::map<std::string, std::pair<IceUtil::Time, Eigen::Vector2f>> transformed_points_with_timestamp;
242 if (m_pose_buffer_fillctr > 0)
244 auto& pose_buf = m_pose_buffer.getUpToDateReadBuffer();
245 for (
unsigned int i = 0; i < m_pose_buffer_fillctr; ++i)
247 for (
const auto& [key, timestamped_keypoint] : pose_buf[i].transformed_keypoints)
249 IceUtil::Time keypoint_timestamp = timestamped_keypoint.first;
250 if (closest_human.timestamp - keypoint_timestamp > m_keypoint_after)
252 transformed_points_with_timestamp[key] = timestamped_keypoint;
259 for (
const auto& [key,
value] : closest_human.keypoints)
268 transformed_points_with_timestamp[key] = std::make_pair(closest_human.timestamp, Eigen::Vector2f{pos(0), pos(1)});
275 unsigned int amount = 0;
276 for (
const auto& [key, timestamped_keypoint] : transformed_points_with_timestamp)
278 Eigen::Vector2f keypoint = timestamped_keypoint.second;
280 sum_x += keypoint(0);
281 sum_y += keypoint(1);
286 Eigen::Vector2f
mean = Eigen::Vector2f::Zero();
289 mean = Eigen::Vector2f{sum_x / amount, sum_y / amount};
293 float max_distance = 0;
294 for (
const auto& [key, timestamped_keypoint] : transformed_points_with_timestamp)
296 Eigen::Vector2f keypoint = timestamped_keypoint.second;
300 ARMARX_DEBUG <<
"Found positions in current frame [X,Y,Distance]: ("
301 <<
mean(0) <<
", " <<
mean(1) <<
", " << max_distance <<
").";
302 if ((last_human_approximation.valid and
mean.isZero()) or max_distance == 0.0)
305 return last_human_approximation;
309 Eigen::Vector2f velocity;
310 float velocity_length = 0.0;
312 if (m_pose_buffer_fillctr > 0)
314 Eigen::Vector2f sum{0, 0};
315 auto& pose_buf = m_pose_buffer.getUpToDateReadBuffer();
316 for (
unsigned int i = 0; i < m_pose_buffer_fillctr; ++i)
318 sum += Eigen::Vector2f{pose_buf[i].posX, pose_buf[i].posY};
320 Eigen::Vector2f temp_mean = sum / m_pose_buffer_fillctr;
321 velocity =
mean - temp_mean;
322 velocity_length = velocity.norm();
323 Eigen::Vector2f velocity_normalized = velocity.normalized();
325 const float cross_product = velocity_normalized(1);
326 const float dot_product = velocity_normalized(0);
327 yaw = acos(dot_product);
329 if (cross_product < 0)
331 yaw = 2 *
M_PI - yaw;
335 ARMARX_DEBUG <<
"Got yaw: " << yaw <<
" and velocity vector " << velocity <<
" and length "
336 << velocity_length <<
".";
337 float velocity_multiplier = velocity_length / 15.0;
339 HumanApproximation current_frame_human;
340 current_frame_human.valid =
true;
341 current_frame_human.transformed_keypoints = transformed_points_with_timestamp;
342 current_frame_human.posX =
mean(0);
343 current_frame_human.posY =
mean(1);
344 current_frame_human.axisLengthX = max_distance * velocity_multiplier;
345 current_frame_human.axisLengthY = max_distance;
346 current_frame_human.yaw = yaw;
347 current_frame_human.timestamp = closest_human.timestamp;
350 auto& buf = m_pose_buffer.getWriteBuffer();
351 buf.at(m_pose_buffer_index++) = current_frame_human;
352 m_pose_buffer_index %= buf.size();
353 m_pose_buffer.commitWrite();
354 ++m_pose_buffer_fillctr;
355 m_pose_buffer_fillctr =
std::min(m_pose_buffer_fillctr,
static_cast<unsigned int>(buf.size()));
358 HumanApproximation mean_frame_human = current_frame_human;
359 if (m_pose_buffer_fillctr > 0)
361 Eigen::Vector2f pose_sum{0, 0};
362 Eigen::Vector2f axis_length_sum{0, 0};
363 double sum_cos_yaw = 0;
364 double sum_sin_yaw = 0;
365 auto& pose_buf = m_pose_buffer.getUpToDateReadBuffer();
366 for (
unsigned int i = 0; i < m_pose_buffer_fillctr; ++i)
368 pose_sum += Eigen::Vector2f{pose_buf[i].posX, pose_buf[i].posY};
369 axis_length_sum += Eigen::Vector2f{pose_buf[i].axisLengthX, pose_buf[i].axisLengthY};
370 sum_sin_yaw += std::sin(pose_buf[i].yaw);
371 sum_cos_yaw += std::cos(pose_buf[i].yaw);
373 mean_frame_human.posX = pose_sum(0) / m_pose_buffer_fillctr;
374 mean_frame_human.posY = pose_sum(1) / m_pose_buffer_fillctr;
379 if (velocity_length > m_min_velocity_treshold)
381 double mean_yaw = std::atan2((1.0 / m_pose_buffer_fillctr) * sum_sin_yaw,
382 (1.0 / m_pose_buffer_fillctr) * sum_cos_yaw);
385 mean_yaw += 2.0 *
M_PI;
388 mean_frame_human.yaw = mean_yaw;
392 mean_frame_human.yaw = last_human_approximation.yaw;
396 last_human_approximation = mean_frame_human;
397 return mean_frame_human;
404 std::lock_guard l{m_human_mutex};
405 const bool is_data_outdated =
406 (IceUtil::Time::now() - last_human_approximation.timestamp) > m_keypoint_after;
407 if (last_human_approximation.valid and is_data_outdated)
409 ARMARX_IMPORTANT <<
"Have not seen a human for " << m_keypoint_after <<
". " <<
"Deleting obstacle.";
410 HumanApproximation human;
411 last_human_approximation = human;
413 m_obstacle_manager->remove_obstacle(
"human");
421 std::lock_guard l{m_enabled_mutex};
429 std::lock_guard l{m_enabled_mutex};
437 std::lock_guard l{m_enabled_mutex};
455 def->
topic<armarx::OpenPose3DListener>(
"OpenPoseEstimation3D");
457 def->component(m_obstacle_manager,
"DynamicObstacleManager",
"ObstacleManager",
"The name of the obstacle manager proxy");
459 def->optional(m_enabled,
"ActivateOnStartup",
"Activate the component on startup.");
460 def->optional(m_onlyUseFirstNResults,
"OnlyUseFirstNResults",
"Only use the first n results of OpenPose.");
461 def->optional(m_keypoint_after,
"ForgetOpenPoseKeypointAfter",
462 "Forget the OpenPose keypoints after X ms if not visible anymore.");
463 def->optional(m_min_velocity_treshold,
"MinVelocityThreshold",
464 "Velocities below this value will be considered zero.");
465 def->optional(m_human_confidence_filter_value,
"HumanConfidenceFilterValue",
466 "Poses with a mean confidence below this value will be discarded.");
467 def->optional(m_warn_distance,
"WarnDistance",
468 "Distance in [mm] at which a warning should be issued.").setMin(100);