HumanFilter.cpp
Go to the documentation of this file.
1#include "HumanFilter.h"
2
3#include <cstdint>
4#include <memory>
5
8
10
13
15{
16
18 const DateTime& detectionTime,
19 bool useKalmanFilter) :
20 useKalmanFilter(useKalmanFilter)
21 {
22 //initialize new human for detected human
23 human.pose = pose0;
24 human.linearVelocity = Eigen::Vector2f::Zero();
25 human.detectionTime = detectionTime;
26 lastDetectedHuman = human;
27
28 if (useKalmanFilter)
29 {
30 //initialize new kalman filter for new detected human
33 Q.block<2, 2>(0, 0) *= params.control_pos_cov * params.control_pos_cov;
34 Q.block<1, 1>(2, 2) *= params.control_rot_cov * params.control_rot_cov;
35
38 R.block<2, 2>(0, 0) *= params.obs_pos_cov * params.obs_pos_cov;
39 R.block<1, 1>(2, 2) *= params.obs_rot_cov * params.obs_rot_cov;
40
43 P0.block<2, 2>(0, 0) *= params.initial_state_pos_cov * params.initial_state_pos_cov;
44 P0.block<1, 1>(2, 2) *= params.initial_state_rot_cov * params.initial_state_rot_cov;
45
48
49 //initial position and orientation according to detected human
50 SystemModelT::StateT state0 = toUkfState(pose0);
51
52 ukf = std::make_unique<UnscentedKalmanFilter<SystemModelT>>(Q, R, alpha, state0, P0);
53 }
54 }
55
56 void
58 {
59 double dt = (detectionTime - human.detectionTime).toSecondsDouble();
60
61 if (useKalmanFilter)
62 {
63 SystemModelT::ControlT control = toUkfControl(human.linearVelocity);
64 ukf->propagation(control, dt);
65
66 human.pose = fromUkfState(ukf->getCurrentState());
67 human.detectionTime = detectionTime;
68 }
69 else
70 {
71 human.pose = human.estimateAt(detectionTime);
72 human.detectionTime = detectionTime;
73 }
74 }
75
76 void
77 HumanFilter::update(const core::Pose2D& pose, const DateTime& detectionTime)
78 {
79 core::Pose2D newPose;
80
81 if (useKalmanFilter)
82 {
83 //update ukf with new observation
84 SystemModelT::ObsT observation = toUkfObs(pose);
85 ukf->update(observation);
86
87 newPose = fromUkfState(ukf->getCurrentState());
88 newPose.linear() = pose.linear();
89 }
90 else
91 {
92 newPose = pose;
93 }
94
95 // calculate velocity
96 Eigen::Vector2f newVelocity = human.linearVelocity;
97 if (pastPoses.size() >= (params.velocityAverageBinDistance + params.velocityAverageBinSize))
98 {
99 TimedVector2f p1 = getAveragedTimedPose(0, params.velocityAverageBinSize);
100 TimedVector2f p2 = getAveragedTimedPose(params.velocityAverageBinDistance,
101 params.velocityAverageBinDistance +
102 params.velocityAverageBinSize);
103 Eigen::Vector2f ds = p2.pose - p1.pose;
104 double dt = (p2.time * 1000.0) / (p1.time * 1000.0);
105 Eigen::Vector2f linVelocity = ds / dt;
106 if (linVelocity.norm() > 1000)
107 {
108 linVelocity = linVelocity.normalized();
109 linVelocity *= 1000;
110 }
111 newVelocity = linVelocity;
112 }
113 else
114 {
115 newVelocity = Eigen::Vector2f::Zero();
116 }
117
118 // update newPose with average over last Poses
119 if (pastPoses.size() >= params.positionAverageBinSize)
120 {
121 TimedVector2f p = getAveragedTimedPose(pastPoses.size() - params.positionAverageBinSize,
122 params.positionAverageBinSize);
123 newPose = core::Pose2D{Eigen::Translation2f{p.pose}};
124 }
125
126 // fix of Temporary fix
127 // newVelocity.setZero();
128
129 //update stored information about the human
130 human.detectionTime = detectionTime;
131 human.pose = newPose;
132 human.linearVelocity = newVelocity;
133
134 pastPoses.emplace_back(TimedVector2f{detectionTime.toMilliSecondsSinceEpoch(),
135 Eigen::Vector2f{pose.translation()}});
136 if (pastPoses.size() > (params.velocityAverageBinDistance + params.velocityAverageBinSize))
137 {
138 pastPoses.pop_front();
139 }
140
141 lastDetectedHuman = human;
142 }
143
144 const Human&
146 {
147 return human;
148 }
149
151 HumanFilter::detectionAge(const DateTime& currentTime) const
152 {
153 return (currentTime - lastDetectedHuman.detectionTime);
154 }
155
157 HumanFilter::toUkfState(const core::Pose2D& pose)
158 {
159 // [mm] to [m]
160 return {{pose.translation().x() / 1000,
161 pose.translation().y() / 1000,
162 0 /*Eigen::Rotation2Df(pose.linear()).angle()*/}};
163 }
164
166 HumanFilter::fromUkfState(const SystemModelT::StateT& pose)
167 {
168 core::Pose2D pose2d = core::Pose2D::Identity();
169 // [m] to [mm]
170 pose2d.translation().x() = pose.pose.x() * 1000;
171 pose2d.translation().y() = pose.pose.y() * 1000;
172 pose2d.linear() = Eigen::Rotation2Df(0 /*pose.pose.angle()*/).toRotationMatrix();
173
174 return pose2d;
175 }
176
178 HumanFilter::toUkfControl(const Eigen::Vector2f& vel)
179 {
180 // convert velocity from global frame to human frame (required by kalman filter)
181 const auto& global_R_human = human.pose.linear();
182 const auto human_V_vel = global_R_human.inverse() * vel;
183
184 // [mm] to [m]
185 return {{human_V_vel.x() / 1000, human_V_vel.y() / 1000, 0}};
186 }
187
189 HumanFilter::toUkfObs(const core::Pose2D& pose)
190 {
191 return SystemModelT::observationFunction(toUkfState(pose));
192 }
193
194 HumanFilter::TimedVector2f
195 HumanFilter::getAveragedTimedPose(unsigned int start_idx, unsigned int end_idx)
196 {
197 std::int64_t avgTime = 0;
198 Eigen::Vector2f avgPose = Eigen::Vector2f::Zero();
199 auto it = pastPoses.begin();
200 for (std::int64_t i = 0; i < start_idx; ++i)
201 {
202 ++it; // advance iterater to correct window
203 }
204 const auto numItems = end_idx - start_idx;
205 for (std::int64_t i = start_idx; i < end_idx; i++)
206 {
207 const auto& [time, pose] = *it;
208
209 avgTime += time / numItems;
210 avgPose += pose;
211
212 ++it;
213 }
214 avgPose /= numItems;
215 return {avgTime, avgPose};
216 }
217
218
219} // namespace armarx::navigation::human
constexpr T dt
Eigen::Matrix< FloatT, dim::control, dim::control > PropCovT
Eigen::Matrix< FloatT, dim::obs, dim::obs > ObsCovT
Eigen::Matrix< FloatT, 3, 1 > AlphaT
Eigen::Matrix< FloatT, dim::state, dim::state > StateCovT
Represents a point in time.
Definition DateTime.h:25
std::int64_t toMilliSecondsSinceEpoch() const
Definition DateTime.cpp:93
Represents a duration.
Definition Duration.h:17
const Human & get() const
HumanFilter::get returns the human whose pose is filtered containing the most recent state.
void propagation(const DateTime &detectionTime)
HumanFilter::propagation propagate the system model to the given point in time.
void update(const core::Pose2D &pose, const DateTime &detectionTime)
HumanFilter::update update the filter a new detected pose of the tracked human and the detection time...
HumanFilter(const core::Pose2D &pose0, const DateTime &detectionTime, bool useKalmanFilter)
HumanFilter::HumanFilter creates a new filter that filters 2D poses (position and rotation in a two d...
Duration detectionAge(const DateTime &currentTime) const
Eigen::Isometry2f Pose2D
Definition basic_types.h:34
This file is part of ArmarX.
This file is part of ArmarX.
manif::SE3< floatT > pose
Definition SystemModel.h:41
StateSE3< FloatT > StateT
Definition SystemModel.h:88