149 lines
5.7 KiB
C++
149 lines
5.7 KiB
C++
#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<std::vector<cv::Point3f>> & object_points)
|
|
{
|
|
const std::vector<cv::Point3f> & base_points = object_points[0];
|
|
for (int i = 1; i < 5; ++i) {
|
|
double angle = i * THETA;
|
|
cv::Matx33f R = rotation_matrix(angle);
|
|
std::vector<cv::Point3f> 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<std::vector<double>>();
|
|
auto R_camera2gimbal_data = yaml["R_camera2gimbal"].as<std::vector<double>>();
|
|
auto t_camera2gimbal_data = yaml["t_camera2gimbal"].as<std::vector<double>>();
|
|
R_gimbal2imubody_ = Eigen::Matrix<double, 3, 3, Eigen::RowMajor>(R_gimbal2imubody_data.data());
|
|
R_camera2gimbal_ = Eigen::Matrix<double, 3, 3, Eigen::RowMajor>(R_camera2gimbal_data.data());
|
|
t_camera2gimbal_ = Eigen::Matrix<double, 3, 1>(t_camera2gimbal_data.data());
|
|
|
|
auto camera_matrix_data = yaml["camera_matrix"].as<std::vector<double>>();
|
|
auto distort_coeffs_data = yaml["distort_coeffs"].as<std::vector<double>>();
|
|
Eigen::Matrix<double, 3, 3, Eigen::RowMajor> camera_matrix(camera_matrix_data.data());
|
|
Eigen::Matrix<double, 1, 5> 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<PowerRune> & ps) const
|
|
{
|
|
if (!ps.has_value()) return;
|
|
PowerRune & p = ps.value();
|
|
// std::vector<cv::Point2f> image_points;
|
|
// std::vector<cv::Point3f> 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<cv::Point2f> image_points = p.target().points;
|
|
// image_points.emplace_back(p.target().center);
|
|
image_points.emplace_back(p.r_center);
|
|
|
|
std::vector<cv::Point2f> image_points_fourth(image_points.begin(), image_points.begin() + 4);
|
|
std::vector<cv::Point3f> 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<cv::Point3d> world_points;
|
|
std::vector<cv::Point2d> 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<cv::Point2f> 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<cv::Point2f> image_points;
|
|
cv::projectPoints(OBJECT_POINTS, rvec, tvec, camera_matrix_, distort_coeffs_, image_points);
|
|
return image_points;
|
|
}
|
|
} // namespace auto_buff
|