Files
ANSCORE/modules/ANSMOT/UCMCKalman.cpp

252 lines
7.1 KiB
C++

#pragma once
#include <opencv2/opencv.hpp>
#include <cmath>
#include <iostream>
#include "UCMClapjv.h"
#include "UCMCKalman.h"
namespace UCMCKalman {
void lapjv(const Eigen::MatrixXd& costMatrix, double costLimit,
std::vector<int>& x, std::vector<int>& y) {
//
int n_rows = costMatrix.rows();
int n_cols = costMatrix.cols();
x.clear();
y.clear();
x.resize(n_rows);
y.resize(n_cols);
const int n = n_rows + n_cols;
costLimit /= 2.;
double** cost_ptr = new double* [n];
for (int i = 0; i < n; i++) {
cost_ptr[i] = new double[n];
for (int j = 0; j < n; j++) {
if (i < n_rows && j < n_cols) {
cost_ptr[i][j] = costMatrix(i, j);
}
else if (i >= n_rows && j >= n_cols) {
cost_ptr[i][j] = 0.;
}
else {
cost_ptr[i][j] = costLimit;
}
}
}
UCMC::int_t* x_c = new UCMC::int_t[n];
UCMC::int_t* y_c = new UCMC::int_t[n];
UCMC::lapjv_internal(n, cost_ptr, &x_c[0], &y_c[0]);
for (int i = 0; i < n; i++) delete[] cost_ptr[i];
delete[] cost_ptr;
for (int i = 0; i < n_rows; i++) {
x[i] = (x_c[i] >= n_cols) ? -1 : x_c[i];
}
for (int i = 0; i < n_cols; i++) {
y[i] = (y_c[i] >= n_rows) ? -1 : y_c[i];
}
delete[] x_c;
delete[] y_c;
}
void linearAssignment(const Eigen::MatrixXd& costMatrix, double thresh,
std::vector<std::vector<int>>& matches,
std::vector<int>& unmatched_a,
std::vector<int>& unmatched_b) {
matches.clear();
unmatched_a.clear();
unmatched_b.clear();
int n = costMatrix.rows();
int m = costMatrix.cols();
if (n == 0 || m == 0) {
for (int i = 0; i < n; i++) unmatched_a.push_back(i);
for (int i = 0; i < m; i++) unmatched_b.push_back(i);
return;
}
std::vector<int> x, y;
lapjv(costMatrix, thresh, x, y);
for (int i = 0; i < n; ++i) {
if (x[i] < 0) {
unmatched_a.push_back(i);
}
else {
std::vector<int> this_match;
this_match.push_back(i);
this_match.push_back(x[i]);
matches.push_back(this_match);
}
}
for (int j = 0; j < m; ++j) {
if (y[j] < 0) {
unmatched_b.push_back(j);
}
}
}
Filter:: Filter(int dim_x, int dim_z, int dim_u)
: dim_x(dim_x), dim_z(dim_z), dim_u(dim_u),
x(dim_x, 1), P(dim_x, dim_x), Q(dim_x, dim_x),
F(dim_x, dim_x), H(dim_z, dim_x), R(dim_z, dim_z),
_alpha_sq(1.0), M(dim_z, dim_z), z(dim_z, 1),
K(dim_x, dim_z), y(dim_z, 1), S(dim_z, dim_z),
SI(dim_z, dim_z), _I(dim_x, dim_x),
x_prior(dim_x, 1), P_prior(dim_x, dim_x),
x_post(dim_x, 1), P_post(dim_x, dim_x) {
x.setZero();
P.setIdentity();
Q.setIdentity();
F.setIdentity();
H.setZero();
R.setIdentity();
M.setZero();
z.setOnes()* std::numeric_limits<float>::quiet_NaN();
K.setZero();
y.setZero();
S.setZero();
SI.setZero();
_I.setIdentity();
x_prior = x;
P_prior = P;
x_post = x;
P_post = P;
}
void Filter::predict() {
x = F * x;
P = _alpha_sq * (F * P * F.transpose()) + Q;
x_prior = x;
P_prior = P;
}
void Filter::update(const Eigen::VectorXd& z,
const Eigen::MatrixXd& R) {
if (R.rows() != dim_z || R.cols() != dim_z) {
throw std::invalid_argument("R matrix has incorrect dimensions");
}
// Update state
y = z - H * x;
Eigen::MatrixXd PHT = P_prior * H.transpose();
S = H * PHT + R;
SI = S.inverse();
K = PHT * S.inverse();
x += K * y;
// Update covariance
Eigen::MatrixXd I_KH = _I - K * H;
P = (I_KH * P_prior) * I_KH.transpose() + (K * R) * K.transpose();
// Prepare for next prediction
this->z = z;
x_post = x;
P_post = P;
}
Eigen::VectorXd Filter::getState() const {
return x;
}
Eigen::MatrixXd Filter::getCovariance() const {
return P;
}
void Tracker::voteClassId(int new_class_id, float score)
{
if (class_id_locked_) return;
class_id_scores_[new_class_id] += score;
detection_count_++;
int best_id = class_id_;
float best_score = 0.0f;
for (const auto& entry : class_id_scores_)
{
if (entry.second > best_score)
{
best_score = entry.second;
best_id = entry.first;
}
}
class_id_ = best_id;
if (detection_count_ >= CLASS_ID_LOCK_FRAMES)
{
class_id_locked_ = true;
}
}
Tracker::Tracker(Eigen::Vector2d y, Eigen::Matrix2d R, double wx, double wy,
double vmax, double w, double h, double dt, int tracker_count)
: id(tracker_count), age(0), death_count(0), birth_count(0), detidx(-1),
w(w), h(h), status(TrackStatus::Tentative), kf(4, 2),
class_id_(0), detection_count_(0), class_id_locked_(false) {
kf.F = Eigen::Matrix4d::Identity();
kf.F(0, 1) = dt;
kf.F(2, 3) = dt;
kf.H = Eigen::Matrix<double, 2, 4>::Zero();
kf.H(0, 0) = 1;
kf.H(1, 2) = 1;
kf.R = R;
kf.P.setZero(); //= Eigen::Matrix<double, 4, 4>::Zero();
kf.P << 1, 0, 0, 0,
0, vmax* vmax / 3.0, 0, 0,
0, 0, 1, 0,
0, 0, 0, vmax* vmax / 3.0;
// INFO << "P:\n" << kf.P << ENDL;
Eigen::Matrix<double, 4, 2> G;
G << 0.5 * dt * dt, 0,
dt, 0,
0, 0.5 * dt * dt,
0, dt;
Eigen::Matrix<double, 2, 2> Q0;
Q0.setZero();
Q0(0, 0) = wx;
Q0(1, 1) = wy;
Eigen::MatrixXd _Q = (G * Q0) * G.transpose();
kf.Q = _Q;
kf.x << y(0), 0, y(1), 0;
}
void Tracker::update(const Eigen::Vector2d& y, Eigen::Matrix2d& R) {
kf.update(y, R);
}
Eigen::Vector2d Tracker::predict() {
kf.predict();
this->age += 1;
return kf.H * kf.x;
}
Eigen::Vector4d Tracker::getState() const {
return kf.x;
}
double Tracker::distance(const Eigen::Vector2d& y, Eigen::Matrix2d& R, bool show = false) const {
Eigen::Vector2d diff = y - (kf.H * kf.x);
Eigen::Matrix2d S = kf.H * (kf.P * kf.H.transpose()) + R;
Eigen::Matrix2d SI = S.inverse();
auto mahalanobis = diff.transpose() * (SI * diff);
double logdet = log(S.determinant());
return mahalanobis(0, 0) + logdet;
}
}