#include "Car.h" namespace ORB_SLAM2 { Car::Car(Frame &CurrentFrame, vector &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_(3, 3) << 608.0 / 50.0, 0, 304, 0, 608.0 / 50.0, 608, 0, 0, 1); m_bev_K_inv = (cv::Mat_(3, 3) << 50.0 / 608.0, 0, -25, 0, 50.0 / 608.0, -50, 0, 0, 1); mRbw = (cv::Mat_(3, 3) << 1, 0, 0, 0, 0, -1, 0, 1, 0); // world->bev vector 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(0, 0), 2) + pow(mtcl.at(1, 0), 2) + pow(mtcl.at(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 &label1, std ::vector &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 &vp_c, vector &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(0, 0) = p_c.x; // 取bev像素坐标 p_uv_c_bev.at(1, 0) = p_c.y; p_uv_c_bev.at(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(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(0, 0) = carBev.x; // 取bev像素坐标 p_uv_c_bev.at(1, 0) = carBev.y; p_uv_c_bev.at(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(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(0, 0) = p_3d_w.at(0, 0); // 取bev像素坐标 p_3d_w_mat.at(1, 0) = p_3d_w.at(1, 0); p_3d_w_mat.at(2, 0) = p_3d_w.at(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_(3, 3) << 1, 0, 0, 0, 0, -1, 0, 1, 0); // 相机转bev的矩阵 p_3d_bev = Rbc * p_3d_c; // 相机转bev p_3d_bev.at(2, 0) = 1.0; // 归一 p_uv_bev = m_bev_K * p_3d_bev; // 过去bev相机坐标转过去bev像素坐标 u = p_uv_bev.at(0, 0) / p_3d_bev.at(2, 0); v = p_uv_bev.at(1, 0) / p_3d_bev.at(2, 0); if (u > 0 && u < 608 && v > 0 && v < 608) { mnInsight++; mbInsight = true; } } void Car::world2bev(vector &vm_3d_w, vector &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(0, 0) = p_3d_w.at(0, 0); // 取bev像素坐标 p_3d_w_mat.at(1, 0) = p_3d_w.at(1, 0); p_3d_w_mat.at(2, 0) = p_3d_w.at(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_(3, 3) << 1, 0, 0, 0, 0, -1, 0, 1, 0); // 相机转bev的矩阵 p_3d_bev = Rbc * p_3d_c; // 相机转bev p_3d_bev.at(2, 0) = 1.0; // 归一 p_uv_bev = m_bev_K * p_3d_bev; // 过去bev相机坐标转过去bev像素坐标 p_bev.x = p_uv_bev.at(0, 0) / p_3d_bev.at(2, 0); p_bev.y = p_uv_bev.at(1, 0) / p_3d_bev.at(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 &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(0, 0), pose.at(2, 0)); if (this->mnVisual > 1) { kalmanfilter(yk, 0.1); pose.at(0, 0) = mmk_1(0); pose.at(2, 0) = mmk_1(1); cv::Point2f tmp, tmp_v; pose.at(0, 0) = mmk_1(0); pose.at(2, 0) = mmk_1(1); tmp.x = pose.at(0, 0); tmp.y = pose.at(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(0, 0) << " " << pose.at(1, 0) << " " << pose.at(2, 0) << endl; mvvelocity.push_back(tmp_v); mvpose.push_back(tmp); } /* 这里加入卡尔曼滤波,构造 mk,mtcl里是位移 */ if (mdelta_w * 180 / 3.1415927 < 30) // 速度变化在合理范围内:TODO hong 速度变化计算 { // Step1: 更新速度 // mmVelocity = tmp_V; mtcl = tmp_t; mRcl = tmp_R; mtcl.at(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 &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 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_(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(0, 0); pose.y = mCarWorldPose.at(1, 0); pose.z = mCarWorldPose.at(2, 0); mtraj.push_back(pose); } void Car::kalmanfilter(Eigen::Vector2f &yk, double delta_t) { if (mnVisual == 2) { mmk_1 << this->mCarWorldPose.at(0, 0), this->mCarWorldPose.at(2, 0), (yk[0] - this->mCarWorldPose.at(0, 0)) / 0.1, (yk[1] - this->mCarWorldPose.at(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(); } }