Autonomy Software C++ 24.5.1
Welcome to the Autonomy Software repository of the Mars Rover Design Team (MRDT) at Missouri University of Science and Technology (Missouri S&T)! API reference contains the source code and other resources for the development of the autonomy software for our Mars rover. The Autonomy Software project aims to compete in the University Rover Challenge (URC) by demonstrating advanced autonomous capabilities and robust navigation algorithms.
Loading...
Searching...
No Matches
TagDetectionUtilty.hpp
1
13#ifndef TAG_DETECTION_UTILITY_HPP
14#define TAG_DETECTION_UTILITY_HPP
15
16#include "../../AutonomyConstants.h"
17#include "../../AutonomyLogging.h"
18#include "../GeospatialOperations.hpp"
19
21#include <opencv2/opencv.hpp>
22
24
26
27
35{
36
44 {
45 eUnknown, // Unknown detection method.
46 eOpenCV, // Standard OpenCV detection using the ArUco library.
47 eTorch // Torch detection using a YOLO model.
48 };
49
50
56 struct ArucoTag
57 {
58 public:
59 // Declare public struct member attributes.
60 std::shared_ptr<cv::Rect2d> pBoundingBox = std::make_shared<cv::Rect2d>(); // The bounding box of the detected tag.
61 double dConfidence = 0.0; // The detection confidence of the tag (from Torch models).
62 double dStraightLineDistance = 0.0; // Distance between the tag and the camera.
63 double dYawAngle = 0.0; // This is the yaw angle so roll and pitch are ignored.
64 int nID = -1; // The ID of the tag. This is set to -1 if the tag is not detected.
65 std::string szClassName = ""; // The class name of the tag (used in Torch models).
66 std::chrono::system_clock::time_point tmCreation = std::chrono::system_clock::now(); // Set the time detected to the minimum time point.
67 TagDetectionMethod eDetectionMethod = TagDetectionMethod::eUnknown; // The detection method used to detect the tag.
68 cv::Size cvImageResolution = cv::Size(0, 0); // The resolution of the image used to detect the tag.
69 double dHorizontalFOV = 0.0; // The horizontal field of view of the camera used to detect the tag.
70 geoops::Waypoint stGeolocatedPosition = geoops::Waypoint(); // The geolocated position of the tag.
71 std::string szDetectorUUID = ""; // The UUID of the detector that detected the tag. This is used to associate tags with their detectors.
72
73
83 bool operator==(const ArucoTag& stOther) const
84 {
85 return *pBoundingBox == *stOther.pBoundingBox && dConfidence == stOther.dConfidence && dStraightLineDistance == stOther.dStraightLineDistance &&
86 dYawAngle == stOther.dYawAngle && nID == stOther.nID && szClassName == stOther.szClassName && tmCreation == stOther.tmCreation &&
87 eDetectionMethod == stOther.eDetectionMethod && cvImageResolution == stOther.cvImageResolution && dHorizontalFOV == stOther.dHorizontalFOV &&
88 stGeolocatedPosition == stOther.stGeolocatedPosition && szDetectorUUID == stOther.szDetectorUUID;
89 }
90
91
101 bool operator!=(const ArucoTag& stOther) const { return !(*this == stOther); }
102
103
112 ArucoTag& operator=(const ArucoTag& stOther)
113 {
114 // Check if the other ArucoTag is not the same as this one.
115 if (this != &stOther)
116 {
117 // Shallow copy the bounding box.
118 pBoundingBox = stOther.pBoundingBox;
119
120 // Copy other member variables.
121 dConfidence = stOther.dConfidence;
122 dStraightLineDistance = stOther.dStraightLineDistance;
123 dYawAngle = stOther.dYawAngle;
124 nID = stOther.nID;
125 szClassName = stOther.szClassName;
126 tmCreation = stOther.tmCreation;
127 eDetectionMethod = stOther.eDetectionMethod;
128 cvImageResolution = stOther.cvImageResolution;
129 dHorizontalFOV = stOther.dHorizontalFOV;
130 stGeolocatedPosition = stOther.stGeolocatedPosition;
131 szDetectorUUID = stOther.szDetectorUUID;
132 }
133 return *this;
134 }
135 };
136
137
146 inline cv::Point2f FindTagCenter(const ArucoTag& stTag)
147 {
148 // Calculate the center point of the tag.
149 cv::Point2f cvCenter = cv::Point2f(stTag.pBoundingBox->x + stTag.pBoundingBox->width / 2, stTag.pBoundingBox->y + stTag.pBoundingBox->height / 2);
150
151 return cvCenter;
152 }
153
154
164 inline void EstimatePoseFromPNP(cv::Mat& cvCameraMatrix, cv::Mat& cvDistCoeffs, ArucoTag& stTag)
165 {
166 // rotVec is how the tag is orientated with respect to the camera. It's 3 numbers defining an axis of rotation around which we rotate the angle which is the
167 // euclidean distance of the vector. transVec is the XYZ translation of the tag from the camera if you image the convergence of light as a pinhole sitting at
168 // (0,0,0) in space.
169 cv::Vec3d cvRotVec, cvTransVec;
170
171 // Set expected object coordinate system shape.
172 cv::Mat cvObjPoints(4, 1, CV_32FC3);
173 cvObjPoints.at<cv::Vec3f>(0) = cv::Vec3f{0, 0, 0}; // Top-left corner.
174 cvObjPoints.at<cv::Vec3f>(1) = cv::Vec3f{constants::ARUCO_TAG_SIDE_LENGTH, 0, 0}; // Bottom-left corner.
175 cvObjPoints.at<cv::Vec3f>(2) = cv::Vec3f{0, constants::ARUCO_TAG_SIDE_LENGTH, 0}; // Top-right corner.
176 cvObjPoints.at<cv::Vec3f>(3) = cv::Vec3f{constants::ARUCO_TAG_SIDE_LENGTH, constants::ARUCO_TAG_SIDE_LENGTH, 0}; // Bottom-right corner.
177
178 // Repackage tag image points into a mat.
179 cv::Mat cvImgPoints(4, 1, CV_32FC3);
180 cvImgPoints.at<cv::Vec3f>(0) = cv::Vec3f{static_cast<float>(stTag.pBoundingBox->x), static_cast<float>(stTag.pBoundingBox->y), 0.0f}; // Top-left corner.
181 cvImgPoints.at<cv::Vec3f>(1) =
182 cv::Vec3f{static_cast<float>(stTag.pBoundingBox->x), static_cast<float>(stTag.pBoundingBox->y + stTag.pBoundingBox->height), 0.0f}; // Bottom-left corner.
183 cvImgPoints.at<cv::Vec3f>(2) =
184 cv::Vec3f{static_cast<float>(stTag.pBoundingBox->x + stTag.pBoundingBox->width), static_cast<float>(stTag.pBoundingBox->y), 0.0f}; // Top-right corner.
185 cvImgPoints.at<cv::Vec3f>(3) = cv::Vec3f{static_cast<float>(stTag.pBoundingBox->x + stTag.pBoundingBox->width),
186 static_cast<float>(stTag.pBoundingBox->y + stTag.pBoundingBox->height),
187 0.0f}; // Bottom-right corner.
188
189 // Use solve perspective n' point algorithm to estimate pose of the tag.
190 cv::solvePnP(cvObjPoints, cvImgPoints, cvCameraMatrix, cvDistCoeffs, cvRotVec, cvTransVec);
191
192 // Grab (x,y,z) coordinates from where the tag was detected
193 double dForward = cvTransVec[2];
194 double dRight = cvTransVec[0];
195 double dUp = cvTransVec[1];
196
197 // Calculate euclidean distance from ZED camera left eye to the point of interest
198 stTag.dStraightLineDistance = std::sqrt(std::pow(dForward, 2) + std::pow(dRight, 2) + std::pow(dUp, 2));
199
200 // Calculate the angle on plane horizontal to the viewpoint
201 stTag.dYawAngle = std::atan2(dRight, dForward);
202 }
203
204
215 {
216 // Use camera field of view and camera frame size to determine tag angle in degrees from center of camera.
217 double dDegreesPerPixel = stTag.dHorizontalFOV / stTag.cvImageResolution.width;
218 // Find tag error in pixels from center of image.
219 double dTagErrorX = (stTag.pBoundingBox->x + stTag.pBoundingBox->width / 2) - (stTag.cvImageResolution.width / 2);
220 // Find angle error.
221 double dTagAngleX = dTagErrorX * dDegreesPerPixel;
222 // Reassign yaw and distance to tag.
223 stTag.dYawAngle = dTagAngleX;
224
225 // For the distance, we'll just use the screen percentage of the tag.
226 stTag.dStraightLineDistance = (stTag.pBoundingBox->area() / (stTag.cvImageResolution.width * stTag.cvImageResolution.height)) * 100.0;
227 }
228
229} // namespace tagdetectutils
230
231#endif
_Tp & at(int i0=0)
bool solvePnP(InputArray objectPoints, InputArray imagePoints, InputArray cameraMatrix, InputArray distCoeffs, OutputArray rvec, OutputArray tvec, bool useExtrinsicGuess=false, int flags=SOLVEPNP_ITERATIVE)
Size2i Size
Point_< float > Point2f
#define CV_32FC3
Namespace containing function to assist in tag detection.
Definition TagDetectionUtilty.hpp:35
cv::Point2f FindTagCenter(const ArucoTag &stTag)
Given an tagdetectutils::ArucoTag struct find the center point of the corners.
Definition TagDetectionUtilty.hpp:146
void EstimatePoseFromPNP(cv::Mat &cvCameraMatrix, cv::Mat &cvDistCoeffs, ArucoTag &stTag)
Estimate the pose of a position with respect to the observer using an image.
Definition TagDetectionUtilty.hpp:164
TagDetectionMethod
Enum class to define the different tag detection methods available.
Definition TagDetectionUtilty.hpp:44
void EstimatePoseFromCameraFrame(ArucoTag &stTag)
Estimate the pose of a tag from a camera frame.
Definition TagDetectionUtilty.hpp:214
This struct is used by the WaypointHandler class to store location, size, and type information about ...
Definition GeospatialOperations.hpp:423
Represents a single ArUco tag.
Definition TagDetectionUtilty.hpp:57
bool operator!=(const ArucoTag &stOther) const
Overload the inequality operator for the ArucoTag struct.
Definition TagDetectionUtilty.hpp:101
bool operator==(const ArucoTag &stOther) const
Overload the equality operator for the ArucoTag struct.
Definition TagDetectionUtilty.hpp:83
ArucoTag & operator=(const ArucoTag &stOther)
Overload the assignment operator for the ArucoTag struct to perform a deep copy.
Definition TagDetectionUtilty.hpp:112