| 43 | } |
| 44 | |
| 45 | bool two_view_triangulator::triangulate(const unsigned idx_1, const unsigned int idx_2, Vec3_t &pos_w) const |
| 46 | { |
| 47 | const auto &keypt_1 = keyfrm_1_->undist_keypts_.at(idx_1); |
| 48 | const float keypt_1_x_right = keyfrm_1_->stereo_x_right_.at(idx_1); |
| 49 | const bool is_stereo_1 = 0 <= keypt_1_x_right; |
| 50 | |
| 51 | const auto &keypt_2 = keyfrm_2_->undist_keypts_.at(idx_2); |
| 52 | const float keypt_2_x_right = keyfrm_2_->stereo_x_right_.at(idx_2); |
| 53 | const bool is_stereo_2 = 0 <= keypt_2_x_right; |
| 54 | |
| 55 | // rays with reference of each camera |
| 56 | const Vec3_t ray_c_1 = keyfrm_1_->bearings_.at(idx_1); |
| 57 | const Vec3_t ray_c_2 = keyfrm_2_->bearings_.at(idx_2); |
| 58 | // rays with the world reference |
| 59 | const Vec3_t ray_w_1 = rot_w1_ * ray_c_1; |
| 60 | const Vec3_t ray_w_2 = rot_w2_ * ray_c_2; |
| 61 | const auto cos_rays_parallax = ray_w_1.dot(ray_w_2); |
| 62 | |
| 63 | // compute the stereo parallax if the keypoint is observed as stereo |
| 64 | const auto cos_stereo_parallax_1 = is_stereo_1 |
| 65 | ? std::cos(2.0 * atan2(camera_1_->true_baseline_ / 2.0, keyfrm_1_->depths_.at(idx_1))) |
| 66 | : 2.0; |
| 67 | const auto cos_stereo_parallax_2 = is_stereo_2 |
| 68 | ? std::cos(2.0 * atan2(camera_2_->true_baseline_ / 2.0, keyfrm_2_->depths_.at(idx_2))) |
| 69 | : 2.0; |
| 70 | const auto cos_stereo_parallax = std::min(cos_stereo_parallax_1, cos_stereo_parallax_2); |
| 71 | |
| 72 | // select to use "linear triangulation" or "stereo triangulation" |
| 73 | // threshold of minimum angle of the two rays |
| 74 | const bool triangulate_with_two_cameras = |
| 75 | // check if the sufficient parallax is provided |
| 76 | ((!is_stereo_1 && !is_stereo_2) && 0.0 < cos_rays_parallax && cos_rays_parallax < cos_rays_parallax_thr_) |
| 77 | // check if the parallax between the two cameras is larger than the stereo parallax |
| 78 | || ((is_stereo_1 || is_stereo_2) && 0.0 < cos_rays_parallax && cos_rays_parallax < cos_stereo_parallax); |
| 79 | |
| 80 | // triangulate |
| 81 | if (triangulate_with_two_cameras) |
| 82 | { |
| 83 | pos_w = solve::triangulator::triangulate(ray_c_1, ray_c_2, cam_pose_1w_, cam_pose_2w_); |
| 84 | } |
| 85 | else if (is_stereo_1 && cos_stereo_parallax_1 < cos_stereo_parallax_2) |
| 86 | { |
| 87 | pos_w = keyfrm_1_->triangulate_stereo(idx_1); |
| 88 | } |
| 89 | else if (is_stereo_2 && cos_stereo_parallax_2 < cos_stereo_parallax_1) |
| 90 | { |
| 91 | pos_w = keyfrm_2_->triangulate_stereo(idx_2); |
| 92 | } |
| 93 | else |
| 94 | { |
| 95 | return false; |
| 96 | } |
| 97 | |
| 98 | // check the triangulated point is located in front of the two cameras |
| 99 | if (!check_depth_is_positive(pos_w, rot_1w_, trans_1w_, camera_1_) || !check_depth_is_positive(pos_w, rot_2w_, trans_2w_, camera_2_)) |
| 100 | { |
| 101 | return false; |
| 102 | } |
no test coverage detected