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,
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 
150  Duration
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  {
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
armarx::navigation::human::HumanFilter::HumanFilter
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...
Definition: HumanFilter.cpp:17
armarx::navigation::human::HumanFilter::Parameters::obs_rot_cov
double obs_rot_cov
Definition: HumanFilter.h:56
HumanFilter.h
UnscentedKalmanFilter
Definition: UnscentedKalmanFilter.h:36
armarx::navigation::human::Human
Definition: types.h:36
basic_types.h
armarx::navigation::human::HumanFilter::Parameters::initial_state_rot_cov
double initial_state_rot_cov
Definition: HumanFilter.h:58
armarx::navigation::human::HumanFilter::Parameters::control_pos_cov
double control_pos_cov
Definition: HumanFilter.h:53
DateTime.h
Duration.h
armarx::navigation::human::Human::pose
core::Pose2D pose
Definition: types.h:38
armarx::navigation::human::kalman_filter::SystemModelSE2::observationFunction
static ObsT observationFunction(const StateT &state)
Definition: HumanSystemModel.cpp:72
types.h
armarx::navigation::human
This file is part of ArmarX.
Definition: aron_conversions.cpp:10
armarx::navigation::human::HumanFilter::update
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...
Definition: HumanFilter.cpp:77
armarx::navigation::human::Human::estimateAt
core::Pose2D estimateAt(const DateTime &time) const
Definition: types.cpp:15
armarx::navigation::human::HumanFilter::Parameters::obs_pos_cov
double obs_pos_cov
Definition: HumanFilter.h:55
armarx::navigation::human::HumanFilter::Parameters::positionAverageBinSize
unsigned int positionAverageBinSize
Definition: HumanFilter.h:65
armarx::navigation::core::Pose2D
Eigen::Isometry2f Pose2D
Definition: basic_types.h:34
armarx::navigation::human::Human::detectionTime
DateTime detectionTime
Definition: types.h:40
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:570
armarx::navigation::human::kalman_filter::SystemModelSE2::ControlT
ControlSE2< FloatT > ControlT
Definition: HumanSystemModel.h:104
StateSE3
Definition: SystemModel.h:39
armarx::navigation::human::HumanFilter::Parameters::initial_state_pos_cov
double initial_state_pos_cov
Definition: HumanFilter.h:57
armarx::navigation::human::HumanFilter::Parameters::velocityAverageBinSize
unsigned int velocityAverageBinSize
Definition: HumanFilter.h:63
armarx::navigation::human::kalman_filter::StateSE2
Definition: HumanSystemModel.h:81
armarx::navigation::human::HumanFilter::detectionAge
Duration detectionAge(const DateTime &currentTime) const
Definition: HumanFilter.cpp:151
armarx::navigation::human::Human::linearVelocity
Eigen::Vector2f linearVelocity
Definition: types.h:39
armarx::navigation::human::HumanFilter::Parameters::alpha
double alpha
Definition: HumanFilter.h:59
armarx::navigation::human::HumanFilter::Parameters::control_rot_cov
double control_rot_cov
Definition: HumanFilter.h:54
armarx::navigation::human::kalman_filter::SystemModelSE2::ObsT
Eigen::Matrix< FloatT, dim::obs, 1 > ObsT
Definition: HumanSystemModel.h:105
armarx::navigation::human::HumanFilter::get
const Human & get() const
HumanFilter::get returns the human whose pose is filtered containing the most recent state.
Definition: HumanFilter.cpp:145
armarx::navigation::human::HumanFilter::propagation
void propagation(const DateTime &detectionTime)
HumanFilter::propagation propagate the system model to the given point in time.
Definition: HumanFilter.cpp:57
armarx::core::time::DateTime::toMilliSecondsSinceEpoch
std::int64_t toMilliSecondsSinceEpoch() const
Definition: DateTime.cpp:93
armarx::core::time::DateTime
Represents a point in time.
Definition: DateTime.h:24
armarx::navigation::human::HumanFilter::Parameters::velocityAverageBinDistance
unsigned int velocityAverageBinDistance
Definition: HumanFilter.h:64
armarx::core::time::Duration
Represents a duration.
Definition: Duration.h:16
armarx::navigation::human::kalman_filter::ControlSE2
Definition: HumanSystemModel.h:87
Eigen::Matrix< FloatT, dim::control, dim::control >
UnscentedKalmanFilter.h
control
This file is part of ArmarX.
dt
constexpr T dt
Definition: UnscentedKalmanFilterTest.cpp:45
StateSE3::pose
manif::SE3< floatT > pose
Definition: SystemModel.h:41