#include "buff_solver.hpp" namespace auto_buff { cv::Matx33f Solver::rotation_matrix(double angle) const { return cv::Matx33f( 1, 0, 0, 0, std::cos(angle), -std::sin(angle), 0, std::sin(angle), std::cos(angle)); } void Solver::compute_rotated_points(std::vector> & object_points) { const std::vector & base_points = object_points[0]; for (int i = 1; i < 5; ++i) { double angle = i * THETA; cv::Matx33f R = rotation_matrix(angle); std::vector rotated_points; for (const auto & point : base_points) { cv::Vec3f vec(point.x, point.y, point.z); cv::Vec3f rotated_vec = R * vec; rotated_points.emplace_back(rotated_vec[0], rotated_vec[1], rotated_vec[2]); } object_points[i] = rotated_points; } } Solver::Solver(const std::string & config_path) : R_gimbal2world_(Eigen::Matrix3d::Identity()) { auto yaml = YAML::LoadFile(config_path); auto R_gimbal2imubody_data = yaml["R_gimbal2imubody"].as>(); auto R_camera2gimbal_data = yaml["R_camera2gimbal"].as>(); auto t_camera2gimbal_data = yaml["t_camera2gimbal"].as>(); R_gimbal2imubody_ = Eigen::Matrix(R_gimbal2imubody_data.data()); R_camera2gimbal_ = Eigen::Matrix(R_camera2gimbal_data.data()); t_camera2gimbal_ = Eigen::Matrix(t_camera2gimbal_data.data()); auto camera_matrix_data = yaml["camera_matrix"].as>(); auto distort_coeffs_data = yaml["distort_coeffs"].as>(); Eigen::Matrix camera_matrix(camera_matrix_data.data()); Eigen::Matrix distort_coeffs(distort_coeffs_data.data()); cv::eigen2cv(camera_matrix, camera_matrix_); cv::eigen2cv(distort_coeffs, distort_coeffs_); // compute_rotated_points(OBJECT_POINTS); } Eigen::Matrix3d Solver::R_gimbal2world() const { return R_gimbal2world_; } void Solver::set_R_gimbal2world(const Eigen::Quaterniond & q) { Eigen::Matrix3d R_imubody2imuabs = q.toRotationMatrix(); R_gimbal2world_ = R_gimbal2imubody_.transpose() * R_imubody2imuabs * R_gimbal2imubody_; } void Solver::solve(std::optional & ps) const { if (!ps.has_value()) return; PowerRune & p = ps.value(); // std::vector image_points; // std::vector object_points; // int i = 0; // for (auto & fanblade : p.fanblades) { // if (fanblade.type != _unlight) { // image_points.insert(image_points.end(), fanblade.points.begin(), fanblade.points.end()); // image_points.emplace_back(fanblade.center); // object_points.insert(object_points.end(), OBJECT_POINTS[i].begin(), OBJECT_POINTS[i].end()); // } // ++i; // } // image_points.emplace_back(p.r_center); //r_center // object_points.emplace_back(cv::Point3f(0, 0, 0)); std::vector image_points = p.target().points; // image_points.emplace_back(p.target().center); image_points.emplace_back(p.r_center); std::vector image_points_fourth(image_points.begin(), image_points.begin() + 4); std::vector OBJECT_POINTS_FOURTH(OBJECT_POINTS.begin(), OBJECT_POINTS.begin() + 4); cv::solvePnP( OBJECT_POINTS_FOURTH, image_points_fourth, camera_matrix_, distort_coeffs_, rvec_, tvec_, false, cv::SOLVEPNP_IPPE); Eigen::Vector3d t_buff2camera; cv::cv2eigen(tvec_, t_buff2camera); cv::Mat rmat; cv::Rodrigues(rvec_, rmat); Eigen::Matrix3d R_buff2camera; cv::cv2eigen(rmat, R_buff2camera); Eigen::Vector3d blade_xyz_in_buff{{0, 0, 700e-3}}; // buff -> camera Eigen::Vector3d xyz_in_camera = t_buff2camera; Eigen::Vector3d blade_xyz_in_camera = R_buff2camera * blade_xyz_in_buff + t_buff2camera; // camera -> gimbal Eigen::Matrix3d R_buff2gimbal = R_camera2gimbal_ * R_buff2camera; Eigen::Vector3d xyz_in_gimbal = R_camera2gimbal_ * xyz_in_camera + t_camera2gimbal_; Eigen::Vector3d blade_xyz_in_gimbal = R_camera2gimbal_ * blade_xyz_in_camera + t_camera2gimbal_; /// gimbal -> world Eigen::Matrix3d R_buff2world = R_gimbal2world_ * R_buff2gimbal; p.xyz_in_world = R_gimbal2world_ * xyz_in_gimbal; p.ypd_in_world = tools::xyz2ypd(p.xyz_in_world); p.blade_xyz_in_world = R_gimbal2world_ * blade_xyz_in_gimbal; p.blade_ypd_in_world = tools::xyz2ypd(p.blade_xyz_in_world); p.ypr_in_world = tools::eulers(R_buff2world, 2, 1, 0); } // 调试用 cv::Point2f Solver::point_buff2pixel(cv::Point3f x) { // buff坐标系(单位:m)到像素坐标系 std::vector world_points; std::vector image_points; world_points.push_back(x); cv::projectPoints(world_points, rvec_, tvec_, camera_matrix_, distort_coeffs_, image_points); return image_points.back(); } // xyz_in_world2xyz_in_pix std::vector Solver::reproject_buff( const Eigen::Vector3d & xyz_in_world, double yaw, double row) const { auto R_buff2world = tools::rotation_matrix(Eigen::Vector3d(yaw, 0.0, row)); // clang-format on // get R_buff2camera t_buff2camera const Eigen::Vector3d & t_buff2world = xyz_in_world; Eigen::Matrix3d R_buff2camera = R_camera2gimbal_.transpose() * R_gimbal2world_.transpose() * R_buff2world; Eigen::Vector3d t_buff2camera = R_camera2gimbal_.transpose() * (R_gimbal2world_.transpose() * t_buff2world - t_camera2gimbal_); // get rvec tvec cv::Vec3d rvec; cv::Mat R_buff2camera_cv; cv::eigen2cv(R_buff2camera, R_buff2camera_cv); cv::Rodrigues(R_buff2camera_cv, rvec); cv::Vec3d tvec(t_buff2camera[0], t_buff2camera[1], t_buff2camera[2]); // reproject std::vector image_points; cv::projectPoints(OBJECT_POINTS, rvec, tvec, camera_matrix_, distort_coeffs_, image_points); return image_points; } } // namespace auto_buff