34 #include <opencv2/calib3d/calib3d.hpp>
35 #include <opencv2/core/affine.hpp>
36 #include <opencv2/core/core.hpp>
45 #undef OSVR_UVBI_TEST_RANSAC_REPROJECTION
47 static const float MAX_REPROJECTION_ERROR = 4.f;
53 BeaconStateVec
const &beacons,
54 std::vector<BeaconData> &beaconDebug, Eigen::Vector3d &outXlate,
55 Eigen::Quaterniond &outQuat,
int skipBrightsCutoff,
56 std::size_t iterations) {
58 bool skipBrights =
false;
60 if (skipBrightsCutoff > 0) {
62 std::count_if(begin(leds), end(leds),
64 if (nonBrights >= skipBrightsCutoff) {
77 std::vector<cv::Point3f> objectPoints;
78 std::vector<cv::Point2f> imagePoints;
79 std::vector<ZeroBasedBeaconId> beaconIds;
80 for (
auto const &led : leds) {
81 if (skipBrights && led->isBright()) {
84 auto id = makeZeroBased(led->getID());
85 auto index = asIndex(
id);
86 beaconDebug[index].variance = -1;
87 beaconDebug[index].measurement = led->getLocationForTracking();
88 beaconIds.push_back(
id);
92 imagePoints.push_back(led->getLocationForTracking());
93 objectPoints.push_back(
94 vec3dToCVPoint3f(beacons[index]->stateVector()));
98 if (objectPoints.size() < m_permittedOutliers + m_requiredInliers) {
111 bool usePreviousGuess =
false;
112 cv::Mat inlierIndices;
116 #if CV_MAJOR_VERSION == 2
118 objectPoints, imagePoints, camParams.cameraMatrix,
119 camParams.distortionParameters, rvec, tvec, usePreviousGuess,
120 iterations, MAX_REPROJECTION_ERROR,
121 static_cast<int>(objectPoints.size() - m_permittedOutliers),
123 #elif CV_MAJOR_VERSION == 3
128 double confidence = 0.99;
129 auto ransacResult = cv::solvePnPRansac(
130 objectPoints, imagePoints, camParams.cameraMatrix,
131 camParams.distortionParameters, rvec, tvec, usePreviousGuess,
132 iterations, MAX_REPROJECTION_ERROR, confidence, inlierIndices);
137 #error "Unrecognized OpenCV version!"
143 if (inlierIndices.rows < static_cast<int>(m_requiredInliers)) {
147 if (inlierIndices.rows > 0) {
149 #ifdef OSVR_UVBI_TEST_RANSAC_REPROJECTION
154 const double pixelReprojectionErrorForSingleAxisMax = 4;
155 std::vector<cv::Point3f> inlierObjectPoints;
156 std::vector<cv::Point2f> inlierImagePoints;
157 for (
int i = 0; i < inlierIndices.rows; i++) {
158 inlierObjectPoints.push_back(objectPoints[i]);
159 inlierImagePoints.push_back(imagePoints[i]);
161 std::vector<cv::Point2f> reprojectedPoints;
163 inlierObjectPoints, rvec, tvec, camParams.cameraMatrix,
164 camParams.distortionParameters, reprojectedPoints);
166 for (
size_t i = 0; i < reprojectedPoints.size(); i++) {
167 if (reprojectedPoints[i].x - inlierImagePoints[i].x >
168 pixelReprojectionErrorForSingleAxisMax) {
169 std::cout <<
"Reject on reprojected beacon id "
170 << makeOneBased(inlierBeaconIds[i]).value()
171 <<
" x axis." << std::endl;
174 if (reprojectedPoints[i].y - inlierImagePoints[i].y >
175 pixelReprojectionErrorForSingleAxisMax) {
176 std::cout <<
"Reject on reprojected beacon id "
177 << makeOneBased(inlierBeaconIds[i]).value()
178 <<
" y axis." << std::endl;
185 std::vector<ZeroBasedBeaconId> inlierBeaconIds;
186 for (
int i = 0; i < inlierIndices.rows; i++) {
187 inlierBeaconIds.push_back(beaconIds[i]);
196 return lhs.value() < rhs.value();
198 std::sort(begin(inlierBeaconIds), end(inlierBeaconIds),
202 auto isAnInlierBeacon = [&inlierBeaconIds, &idComparator](
204 return std::binary_search(begin(inlierBeaconIds),
205 end(inlierBeaconIds), needle,
208 for (
auto &led : leds) {
209 if (isAnInlierBeacon(led->getID())) {
241 Eigen::Affine3d xform = Eigen::Affine3d(cv::Affine3d(rvec, tvec));
242 Eigen::Vector3d xlate(xform.translation());
243 Eigen::Quaterniond quat(xform.rotation());
244 if (!xlate.array().allFinite()) {
245 std::cout <<
"[UnifiedTracker] Computed a non-finite position with "
250 if (!quat.coeffs().array().allFinite()) {
251 std::cout <<
"[UnifiedTracker] Computed a non-finite orientation "
262 std::cout <<
"On the wrong side of the looking glass:"
263 << xlate.transpose() << std::endl;
265 pinholeCameraFlipPose(xlate, quat);
268 if (!xlate.array().allFinite()) {
269 std::cout <<
"[UnifiedTracker] Computed a non-finite position with "
270 "RANSAC post-pinhole-flip."
274 if (!quat.coeffs().array().allFinite()) {
275 std::cout <<
"[UnifiedTracker] Computed a non-finite orientation "
276 "with RANSAC post-pinhole-flip."
282 quat = Eigen::Quaterniond(-quat.coeffs());
290 static const double InitialPositionStateError = 0.;
292 static const double InitialOrientationStateError = 0.5;
293 static const double InitialVelocityStateError = 0.;
294 static const double InitialAngVelStateError = 0.;
295 static const double InitialStateError[] = {
296 InitialPositionStateError, InitialPositionStateError,
297 InitialPositionStateError, InitialOrientationStateError,
298 InitialOrientationStateError, InitialOrientationStateError,
299 InitialVelocityStateError, InitialVelocityStateError,
300 InitialVelocityStateError, InitialAngVelStateError,
301 InitialAngVelStateError, InitialAngVelStateError};
303 LedPtrList
const &leds) {
304 Eigen::Vector3d xlate;
305 Eigen::Quaterniond quat;
308 auto ret = (*this)(p.camParams, leds, p.beacons, p.beaconDebug,
316 p.state.position() = xlate;
320 p.state.incrementalOrientation() = Eigen::Vector3d::Zero();
321 p.state.velocity() = Eigen::Vector3d::Zero();
322 p.state.angularVelocity() = Eigen::Vector3d::Zero();
327 StateSquareMatrix covariance = StateVec(InitialStateError).asDiagonal();
333 p.state.setErrorCovariance(covariance);
Helper class to keep track of the state of a blob over time. This is used to help determine the ident...
void setQuaternion(Eigen::Quaterniond const &quaternion)
Intended for startup use.
Vector< Dimension< T >::value > DimVector
A vector of length = dimension of T.
bool isBright() const
Returns the most-recent boolean "bright" state according to the LED identifier. Note that the value i...
SquareMatrix< Dimension< T >::value > DimSquareMatrix
A square matrix, n x n, where n is the dimension of T.
Header file for class that tracks and identifies LEDs.
bool operator()(CameraParameters const &camParams, LedPtrList const &leds, BeaconStateVec const &beacons, std::vector< BeaconData > &beaconDebug, Eigen::Vector3d &outXlate, Eigen::Quaterniond &outQuat, int skipBrightsCutoff=-1, std::size_t iterations=5)