2024-06-21 15:44:42 +08:00

480 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Car.h"
namespace ORB_SLAM2
{
Car::Car(Frame &CurrentFrame, vector<double> &bbox) : mnLastFrameID(CurrentFrame.mnId),
mnFirstFrameID(CurrentFrame.mnId),
mbBad(false),
mvLostTrackTimes(0),
mmVelocity(cv::Mat::eye(4, 4, CV_32FC1)),
mnVisual(1),
myaw(bbox[7]),
mdelta_w(0),
mbStatic(false),
mbErro(false),
mvStatic(0),
mV(0),
mnInsight(0),
Tow(cv::Mat::eye(4, 4, CV_32FC1)),
mbInsight(true)
{
static int instanceCount = 0; // 计数器
instanceCount++;
mnCar_ID = instanceCount;
mRcl = mmVelocity.rowRange(0, 3).colRange(0, 3);
mtcl = mmVelocity.rowRange(0, 3).col(3);
m_bev_K = (cv::Mat_<float>(3, 3) << 608.0 / 50.0, 0, 304, 0, 608.0 / 50.0, 608, 0, 0, 1);
m_bev_K_inv = (cv::Mat_<float>(3, 3) << 50.0 / 608.0, 0, -25, 0, 50.0 / 608.0, -50, 0, 0, 1);
mRbw = (cv::Mat_<float>(3, 3) << 1, 0, 0, 0, 0, -1, 0, 1, 0); // world->bev
vector<cv::Point> vp_c;
get_bbx(bbox, vp_c);
bev2world(vp_c, mvmBboxWorldPose, CurrentFrame.mRwc, CurrentFrame.mOw);
mvmBboxWorldPosePredict.resize(4);
for (int i = 0; i < 4; i++)
{
mvmBboxWorldPosePredict[i] = mvmBboxWorldPose[i];
}
cv::Point carBev;
carBev.x = bbox[1];
carBev.y = bbox[2];
bev2world(carBev, mCarWorldPose, CurrentFrame.mRwc, CurrentFrame.mOw);
updatetraj();
SetColor();
mkalman_H << 1, 0, 0, 0,
0, 1, 0, 0;
}
bool Car::isStatic()
{
return mbStatic;
}
bool Car::isErro()
{
return mbErro;
}
double Car::get_Vel(double &t)
{
mV = sqrt(pow(mtcl.at<float>(0, 0), 2) + pow(mtcl.at<float>(1, 0), 2) + pow(mtcl.at<float>(2, 0), 2)) / 0.1;
if (mV * 3.6 > 120)
{
mbBad = true;
}
if (mV < 2)
{
if (mvLostTrackTimes == 0)
{
mvStatic++;
}
mmVelocity = cv::Mat::eye(4, 4, CV_32FC1);
mRcl = mmVelocity.rowRange(0, 3).colRange(0, 3);
mtcl = mmVelocity.rowRange(0, 3).col(3);
mV = 0;
}
else
{
mvStatic = 0;
mbStatic = false;
}
if (mvStatic > 6)
{
mbStatic = true;
}
return mV;
}
void Car::SetColor()
{
int min = 0, max = 255;
random_device seed; // 硬件生成随机数种子
ranlux48 engine(seed()); // 利用种子生成随机数引擎
uniform_int_distribution<> distrib(min, max); // 设置随机数范围,并为均匀分布
int random_r = distrib(engine); // 随机数
int random_g = distrib(engine); // 随机数
int random_b = distrib(engine); // 随机数
mr = random_r / 255.0;
mg = random_g / 255.0;
mb = random_b / 255.0;
}
void Car::get_bbx(const vector<double> &label1, std ::vector<cv::Point> &pts)
{
cv::Point p1, p2, p3, p4;
double x = label1[1];
double y = label1[2];
double w = label1[3];
double l = label1[4];
double yaw = label1[7];
double cos_yaw, sin_yaw;
cos_yaw = cos(yaw);
sin_yaw = sin(yaw);
// front left
p1.x = x - w / 2 * cos_yaw - l / 2 * sin_yaw;
p1.y = y - w / 2 * sin_yaw + l / 2 * cos_yaw;
// rear left
p2.x = x - w / 2 * cos_yaw + l / 2 * sin_yaw;
p2.y = y - w / 2 * sin_yaw - l / 2 * cos_yaw;
// rear right
p3.x = x + w / 2 * cos_yaw + l / 2 * sin_yaw;
p3.y = y + w / 2 * sin_yaw - l / 2 * cos_yaw;
// front right
p4.x = x + w / 2 * cos_yaw - l / 2 * sin_yaw;
p4.y = y + w / 2 * sin_yaw + l / 2 * cos_yaw;
pts.push_back(p1);
pts.push_back(p2);
pts.push_back(p3);
pts.push_back(p4);
// cout << pts << endl;
}
void Car::bev2world(vector<cv::Point> &vp_c, vector<cv::Mat> &vmBboxWorldPose, cv::Mat &Rwc, cv::Mat &twc)
{
// cout << vp_c << endl;
vmBboxWorldPose.clear();
for (auto p_c : vp_c)
{
cv::Mat p_uv_c_bev, p_cam_c_bev, p_cam_c_cam, p_cam_w_cam, R_ij;
p_uv_c_bev = cv::Mat::zeros(3, 1, CV_32FC1);
p_uv_c_bev.at<float>(0, 0) = p_c.x; // 取bev像素坐标
p_uv_c_bev.at<float>(1, 0) = p_c.y;
p_uv_c_bev.at<float>(2, 0) = 1.0;
p_cam_c_bev = m_bev_K_inv * p_uv_c_bev; // bev像素坐标转bev相机坐标
p_cam_c_cam = mRbw.t() * p_cam_c_bev; // bev相机坐标转cam的相机坐标
p_cam_c_cam.at<float>(1, 0) = -1.0;
p_cam_w_cam = Rwc * p_cam_c_cam + twc; // 当前cam相机坐标转到世界坐标
vmBboxWorldPose.push_back(p_cam_w_cam);
}
}
void Car::bev2world(cv::Point &carBev, cv::Mat &CarWorldPose, cv::Mat &Rwc, cv::Mat &twc)
{
cv::Mat p_uv_c_bev, p_cam_c_bev, p_cam_c_cam, p_cam_w_cam, R_ij;
p_uv_c_bev = cv::Mat::zeros(3, 1, CV_32FC1);
p_uv_c_bev.at<float>(0, 0) = carBev.x; // 取bev像素坐标
p_uv_c_bev.at<float>(1, 0) = carBev.y;
p_uv_c_bev.at<float>(2, 0) = 1.0;
p_cam_c_bev = m_bev_K_inv * p_uv_c_bev; // bev像素坐标转bev相机坐标
p_cam_c_cam = mRbw.t() * p_cam_c_bev; // bev相机坐标转cam的相机坐标
p_cam_c_cam.at<float>(1, 0) = -1.0;
CarWorldPose = Rwc * p_cam_c_cam + twc; // 当前cam相机坐标转到世界坐标
}
bool Car::isBad()
{
return mbBad;
}
bool Car::isInSight()
{
return mbInsight;
}
void Car::InCreaseFound(cv::Mat Tcw)
{
mbInsight = false;
cv::Mat p_3d_w = mCarWorldPose;
cv::Mat Rcw, tcw, R_ij;
cv::Mat p_3d_w_mat = cv::Mat::zeros(3, 1, CV_32FC1);
int u, v;
p_3d_w_mat.at<float>(0, 0) = p_3d_w.at<float>(0, 0); // 取bev像素坐标
p_3d_w_mat.at<float>(1, 0) = p_3d_w.at<float>(1, 0);
p_3d_w_mat.at<float>(2, 0) = p_3d_w.at<float>(2, 0);
Rcw = Tcw.rowRange(0, 3).colRange(0, 3);
tcw = Tcw.rowRange(0, 3).col(3);
cv::Mat p_3d_c, p_3d_bev, p_uv_bev;
p_3d_c = Rcw * p_3d_w_mat + tcw; // 世界坐标转相机坐标
cv::Mat Rbc = (cv::Mat_<float>(3, 3) << 1, 0, 0, 0, 0, -1, 0, 1, 0); // 相机转bev的矩阵
p_3d_bev = Rbc * p_3d_c; // 相机转bev
p_3d_bev.at<float>(2, 0) = 1.0; // 归一
p_uv_bev = m_bev_K * p_3d_bev; // 过去bev相机坐标转过去bev像素坐标
u = p_uv_bev.at<float>(0, 0) / p_3d_bev.at<float>(2, 0);
v = p_uv_bev.at<float>(1, 0) / p_3d_bev.at<float>(2, 0);
if (u > 0 && u < 608 && v > 0 && v < 608)
{
mnInsight++;
mbInsight = true;
}
}
void Car::world2bev(vector<cv::Mat> &vm_3d_w, vector<cv::Point> &vp_bev, cv::Mat &Tcw) // 世界坐标转bev像素
{
for (auto p_3d_w : vm_3d_w)
{
cv::Mat Rcw, tcw, R_ij;
cv::Mat p_3d_w_mat = cv::Mat::zeros(3, 1, CV_32FC1);
cv::Point p_bev;
p_3d_w_mat.at<float>(0, 0) = p_3d_w.at<float>(0, 0); // 取bev像素坐标
p_3d_w_mat.at<float>(1, 0) = p_3d_w.at<float>(1, 0);
p_3d_w_mat.at<float>(2, 0) = p_3d_w.at<float>(2, 0);
Rcw = Tcw.rowRange(0, 3).colRange(0, 3);
tcw = Tcw.rowRange(0, 3).col(3);
cv::Mat p_3d_c, p_3d_bev, p_uv_bev;
p_3d_c = Rcw * p_3d_w_mat + tcw; // 世界坐标转相机坐标
cv::Mat Rbc = (cv::Mat_<float>(3, 3) << 1, 0, 0, 0, 0, -1, 0, 1, 0); // 相机转bev的矩阵
p_3d_bev = Rbc * p_3d_c; // 相机转bev
p_3d_bev.at<float>(2, 0) = 1.0; // 归一
p_uv_bev = m_bev_K * p_3d_bev; // 过去bev相机坐标转过去bev像素坐标
p_bev.x = p_uv_bev.at<float>(0, 0) / p_3d_bev.at<float>(2, 0);
p_bev.y = p_uv_bev.at<float>(1, 0) / p_3d_bev.at<float>(2, 0);
vp_bev.push_back(p_bev);
}
}
void Car::update_untracked_Car()
{
mvLostTrackTimes++;
if (mvLostTrackTimes > 6)
{
mbBad = true;
}
else
{
// Step1: 速度不变
// Step2: 恒速运动,根据速度推算目标位置
int tmp_i = 0;
for (auto bboxPose : mvmBboxWorldPose)
{
mvmBboxWorldPose[tmp_i] = mRcl * mvmBboxWorldPose[tmp_i] + mtcl;
tmp_i++;
}
mCarWorldPose = mRcl * mCarWorldPose + mtcl;
}
}
void Car::setTrackedState(bool state)
{
mnTracked = state;
}
bool Car::isTracked()
{
return mnTracked;
}
void Car::updateVelocityAndPose(cv::Mat &pose, double &delta_t, vector<cv::Point> &vp_c, cv::Mat &Rwc, cv::Mat &twc)
{
cv::Mat pose_inv;
// matrix_inv(pose, pose_inv);
cv::Mat tmp_V, tmp_R, tmp_t;
// tmp_V = pose_inv * mCarWorldPose; // pose是当前位置mCarWorldPose在更新时已经是上一帧的位置了
tmp_R = cv::Mat::eye(3, 3, CV_32FC1);
tmp_t = pose - mCarWorldPose;
Eigen::Vector2f yk(pose.at<float>(0, 0), pose.at<float>(2, 0));
if (this->mnVisual > 1)
{
kalmanfilter(yk, 0.1);
pose.at<float>(0, 0) = mmk_1(0);
pose.at<float>(2, 0) = mmk_1(1);
cv::Point2f tmp, tmp_v;
pose.at<float>(0, 0) = mmk_1(0);
pose.at<float>(2, 0) = mmk_1(1);
tmp.x = pose.at<float>(0, 0);
tmp.y = pose.at<float>(2, 0);
tmp_v.x = mmk_1(2);
tmp_v.y = mmk_1(3);
// cout << "第 " << mnCar_ID << " 辆车的位置为: " << tmp.x << " " << tmp.y << endl;
// cout << "第 " << mnCar_ID << " 辆车的位置为: " << pose.at<float>(0, 0) << " " << pose.at<float>(1, 0) << " " << pose.at<float>(2, 0) << endl;
mvvelocity.push_back(tmp_v);
mvpose.push_back(tmp);
}
/*
这里加入卡尔曼滤波,构造
mkmtcl里是位移
*/
if (mdelta_w * 180 / 3.1415927 < 30) // 速度变化在合理范围内TODO hong 速度变化计算
{
// Step1: 更新速度
// mmVelocity = tmp_V;
mtcl = tmp_t;
mRcl = tmp_R;
mtcl.at<float>(1, 0) = 0.0;
// Step2: 更新位置
mCarWorldPose = pose;
mvLostTrackTimes = 0;
bev2world(vp_c, mvmBboxWorldPose, Rwc, twc);
}
else
{
mvLostTrackTimes++;
if (mvLostTrackTimes > 6)
{
mbBad = true;
}
else
{
// Step1: 速度不变
// Step2: 恒速运动,根据速度推算目标位置
int tmp_i = 0;
for (auto bboxPose : mvmBboxWorldPose)
{
mvmBboxWorldPose[tmp_i] = mRcl * mvmBboxWorldPose[tmp_i] + mtcl;
tmp_i++;
}
mCarWorldPose = mRcl * mCarWorldPose + mtcl;
}
}
}
void Car::matrix_inv(cv::Mat T, cv::Mat T_inv)
{
T.copyTo(T_inv);
cv::Mat Rcw, Rwc, tcw, twc, Twc;
Rcw = T.rowRange(0, 3).colRange(0, 3);
Rwc = Rcw.t();
tcw = T.rowRange(0, 3).col(3);
twc = -Rcw.t() * tcw;
Rwc.copyTo(T_inv.rowRange(0, 3).colRange(0, 3));
twc.copyTo(T_inv.rowRange(0, 3).col(3));
}
void Car::updateTrackState(int ID)
{
if (ID - mnLastFrameID > 6)
{
if (mnVisual < 3)
{
mbErro = true;
}
mbBad = true;
}
}
void Car::updateState(vector<double> &bbox, cv::Mat &Rwc, cv::Mat &twc, double &delta_t)
{
cv::Mat tmp_CarWorldPose;
cv::Point carBev;
carBev.x = bbox[1];
carBev.y = bbox[2];
vector<cv::Point> vp_c;
get_bbx(bbox, vp_c);
bev2world(carBev, tmp_CarWorldPose, Rwc, twc); // 获得目标框世界坐标
mdelta_w = bbox[7] - myaw;
updateVelocityAndPose(tmp_CarWorldPose, delta_t, vp_c, Rwc, twc); // 更新速度并更新世界坐标
myaw = bbox[7];
Tow.rowRange(0, 3).colRange(0, 3) = Rwc * (cv::Mat_<float>(3, 3) << cos(myaw), 0, sin(myaw),
0, 1, 0,
-sin(myaw), 0, cos(myaw));
Tow.rowRange(0, 3).col(3) = mCarWorldPose;
}
void Car::updateObservations(int CurrentFrameId)
{
if (mbBad)
return;
mnVisual++;
mnLastFrameID = CurrentFrameId;
}
void Car::updatetraj()
{
cv::Point3f pose;
pose.x = mCarWorldPose.at<float>(0, 0);
pose.y = mCarWorldPose.at<float>(1, 0);
pose.z = mCarWorldPose.at<float>(2, 0);
mtraj.push_back(pose);
}
void Car::kalmanfilter(Eigen::Vector2f &yk, double delta_t)
{
if (mnVisual == 2)
{
mmk_1 << this->mCarWorldPose.at<float>(0, 0), this->mCarWorldPose.at<float>(2, 0), (yk[0] - this->mCarWorldPose.at<float>(0, 0)) / 0.1, (yk[1] - this->mCarWorldPose.at<float>(2, 0)) / 0.1;
}
if (mnVisual == 1)
{
cout << "error in kalmanfilter" << endl;
return;
}
Eigen::Matrix4f A;
A << 1, 0, delta_t, 0,
0, 1, 0, delta_t,
0, 0, 1, 0,
0, 0, 0, 1;
float q1c, q2c;
float sigma1, sigma2;
q1c = 1.0;
q2c = 1.0;
sigma1 = 0.5;
sigma2 = 0.5;
float delta_t3 = delta_t * delta_t * delta_t / 3;
float delta_t2 = delta_t * delta_t / 2;
Eigen::Matrix4f Q;
Q << q1c * delta_t3, 0, q1c * delta_t2, 0,
0, q2c * delta_t3, 0, q2c * delta_t2,
q1c * delta_t2, 0, q1c * delta_t, 0,
0, q2c * delta_t2, 0, q2c * delta_t;
Eigen::Vector4f mk_ = A * mmk_1;
Eigen::Matrix4f Pk_ = A * mPK_1 * A.transpose() + Q;
// 更新
Eigen::Vector2f vk = yk - mkalman_H * mk_;
Eigen::Matrix2f S_k = mkalman_H * Pk_ * mkalman_H.transpose() + mkalman_R;
Eigen::MatrixXf Kk = Pk_ * mkalman_H.transpose() * S_k.inverse();
mmk_1 = mk_ + Kk * vk;
Eigen::Matrix4f tmpawd = Pk_ - Kk * S_k * Kk.transpose();
mPK_1 = tmpawd;
// cout << "row = " << tmp_mmk_1.rows() << " col = " << tmp_mmk_1.cols() << endl;
}
void Car::Save_car_v()
{
std::string filename = "./Car_data/kalmanfilter/file_" + std::to_string(this->mnCar_ID) + ".txt";
if (this->mvpose.size() < 6)
{
return;
}
// 使用文件流打开文件
std::fstream fileStream(filename, std::ios::out | std::ios::app);
if (!fileStream.is_open())
{
std::ofstream newFile(filename);
// 如果需要在创建文件后写入,请在此处添加相应的写入代码
}
// 写入位置数据
for (size_t i = 0; i < mvpose.size(); i++)
{
fileStream << mvpose[i].x << " " << mvpose[i].y << " " << mvvelocity[i].x << " " << mvvelocity[i].y << std::endl;
}
// 关闭文件流
fileStream.close();
}
}