3 #include <boost/geometry.hpp>
4 #include <boost/geometry/geometries/point_xy.hpp>
5 #include <boost/geometry/geometries/polygon.hpp>
12 #include <range/v3/range/conversion.hpp>
13 #include <range/v3/view/transform.hpp>
24 std::vector<DetectedHuman> newPoses =
28 return convertHumanPoseToDetectedHuman(measurements.
detectionTime, humanPose);
33 associateHumans(newPoses);
36 for (
const auto& detectedHuman : newPoses)
38 if (not detectedHuman.associated)
43 .trackingId = detectedHuman.trackingId,
44 .associatedCluster =
nullptr,
59 std::vector<AdvancedCluster> potentialFootprints;
60 std::vector<Cluster> unusedClusters;
61 for (
const auto& cluster : measurements.
clusters)
66 .
center = getClusterCenter(cluster), .cluster = cluster, .associated =
false});
70 unusedClusters.push_back(cluster);
75 const auto sortedDistances = getSortedDistances(trackedHumans, potentialFootprints);
77 for (
auto& posDistance : sortedDistances)
83 if (posDistance.oldHuman->associated || posDistance.newCluster->associated)
88 if (!posDistance.oldHuman->associatedCluster)
90 posDistance.oldHuman->associatedCluster = posDistance.newCluster;
91 posDistance.newCluster->associated =
true;
97 auto& footprint1 = posDistance.oldHuman->associatedCluster->cluster;
98 auto& footprint2 = posDistance.newCluster->cluster;
103 (getClusterCenter(footprint1) + getClusterCenter(footprint2)) / 2;
104 pose.linear() = posDistance.oldHuman->humanFilter.get().pose.linear();
107 posDistance.oldHuman->humanFilter.update(pose, measurements.
detectionTime);
109 posDistance.oldHuman->associatedCluster =
nullptr;
110 posDistance.oldHuman->associated =
true;
111 posDistance.newCluster->associated =
true;
117 for (
auto& human : trackedHumans)
119 if (human.associated)
124 if (human.associatedCluster)
126 auto& footprint = human.associatedCluster;
129 pose.translation() = footprint->center;
130 pose.linear() = human.humanFilter.get().pose.linear();
134 human.associatedCluster =
nullptr;
135 human.associated =
true;
141 for (
auto& cluster : potentialFootprints)
143 if (!cluster.associated)
145 unusedClusters.push_back(cluster.cluster);
148 return unusedClusters;
151 std::vector<human::Human>
154 return trackedHumans |
163 trackedHumans.clear();
167 HumanTracker::convertHumanPoseToDetectedHuman(
const DateTime& time,
170 const std::map<std::string, armem::human::PoseKeypoint>& keypoints = humanPose.
keypoints;
174 Eigen::Vector3f centerPos = Eigen::Vector3f::Zero();
176 for (
const auto& [_,
v] : keypoints)
178 if (
v.positionGlobal.has_value())
180 centerPos +=
v.positionGlobal.value().toEigen();
194 Eigen::Vector3f vec(1, 0, 0);
195 Eigen::Vector3f rot3 = qhead._transformVector(vec);
196 Eigen::Vector2f rot2(rot3.x(), rot3.y());
197 if (rot2.norm() != 0)
200 yaw = atan2(rot2.y(), rot2.x());
207 pose.linear() = Eigen::Rotation2Df(yaw).toRotationMatrix();
212 std::vector<HumanTracker::PosHumanDistance>
213 HumanTracker::getSortedDistances(std::vector<HumanTracker::TrackedHuman>& oldHumans,
214 std::vector<HumanTracker::DetectedHuman>& newHumans)
216 std::vector<PosHumanDistance> posDistances;
218 for (
auto& oldHuman : oldHumans)
220 if (oldHuman.associated)
224 for (
auto& newHuman : newHumans)
226 if (newHuman.associated)
232 posDistances.push_back(
235 (newHuman.pose.translation() - oldHuman.humanFilter.get().pose.translation())
241 std::sort(posDistances.begin(),
243 [](
const PosHumanDistance&
a,
const PosHumanDistance& b) ->
bool
244 { return a.distance < b.distance; });
249 std::vector<HumanTracker::PosLaserDistance>
250 HumanTracker::getSortedDistances(std::vector<TrackedHuman>& oldHumans,
251 std::vector<AdvancedCluster>& newClusters)
253 std::vector<PosLaserDistance> posDistances;
255 for (
auto& oldHuman : oldHumans)
257 for (
auto& newCluster : newClusters)
260 posDistances.push_back(
263 (newCluster.center - oldHuman.humanFilter.get().pose.translation()).norm()});
268 std::sort(posDistances.begin(),
270 [](
const PosLaserDistance&
a,
const PosLaserDistance& b) ->
bool
271 { return a.distance < b.distance; });
277 HumanTracker::associateHumans(std::vector<DetectedHuman>& detectedHumans)
280 for (
auto& oldHuman : trackedHumans)
282 if (oldHuman.associated || not oldHuman.trackingId)
286 for (
auto& newHuman : detectedHumans)
288 if (newHuman.associated || not newHuman.trackingId)
294 if (oldHuman.trackingId.value() == newHuman.trackingId.value())
296 associate(&oldHuman, &newHuman);
302 const auto sortedDistances = getSortedDistances(trackedHumans, detectedHumans);
304 for (
auto& posDistance : sortedDistances)
310 if (posDistance.oldHuman->associated || posDistance.newHuman->associated)
315 associate(posDistance.oldHuman, posDistance.newHuman);
320 HumanTracker::associate(TrackedHuman* trackedHuman, DetectedHuman* detectedHuman)
326 trackedHuman->associated =
true;
327 detectedHuman->associated =
true;
329 trackedHuman->humanFilter.update(detectedHuman->pose, detectedHuman->detectionTime);
330 trackedHuman->trackingId = detectedHuman->trackingId;
336 HumanTracker::getClusterSize(
Cluster cluster)
338 return 2 * cluster.circle.radius;
342 HumanTracker::getClusterCenter(
Cluster cluster)
344 typedef boost::geometry::model::d2::point_xy<double> boost_point;
345 typedef boost::geometry::model::polygon<boost_point> boost_polygon;
348 std::vector<boost_point> points;
349 for (
auto& point : cluster.convexHull)
351 points.push_back(boost_point(point.x(), point.y()));
355 boost_point(cluster.convexHull.front().x(), cluster.convexHull.front().y()));
357 boost::geometry::assign_points(poly, points);
360 boost::geometry::centroid(poly, p);
362 return Eigen::Vector2f{p.x(), p.y()};
366 HumanTracker::prepareTrackedHumans(DateTime time)
369 for (
auto it = trackedHumans.begin(); it != trackedHumans.end();)
374 if (human.humanFilter.detectionAge(time) >= parameters.
maxTrackingAge ||
375 human.confidence <= 0)
377 it = trackedHumans.erase(it);
382 human.associatedCluster =
nullptr;
383 human.associated =
false;
384 human.humanFilter.propagation(time);