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 eTensorflow // Tensorflow detection using a YOLO model.
49 };
50
51
58 struct ArucoTag
59 {
60 public:
61 // Declare public struct member attributes.
62 std::shared_ptr<cv::Rect2d> pBoundingBox = std::make_shared<cv::Rect2d>(); // The bounding box of the detected tag.
63 double dConfidence = 0.0; // The detection confidence of the tag (from Torch/Tensorflow models).
64 double dStraightLineDistance = 0.0; // Distance between the tag and the camera.
65 double dYawAngle = 0.0; // This is the yaw angle so roll and pitch are ignored.
66 int nID = -1; // The ID of the tag. This is set to -1 if the tag is not detected.
67 std::string szClassName = ""; // The class name of the tag (used in Torch/Tensorflow models).
68 std::chrono::system_clock::time_point tmCreation = std::chrono::system_clock::now(); // Set the time detected to the minimum time point.
69 TagDetectionMethod eDetectionMethod = TagDetectionMethod::eUnknown; // The detection method used to detect the tag.
70 cv::Size cvImageResolution = cv::Size(0, 0); // The resolution of the image used to detect the tag.
71 double dHorizontalFOV = 0.0; // The horizontal field of view of the camera used to detect the tag.
72 geoops::Waypoint stGeolocatedPosition = geoops::Waypoint(); // The geolocated position of the tag.
73
74
84 bool operator==(const ArucoTag& stOther) const
85 {
86 return *pBoundingBox == *stOther.pBoundingBox && dConfidence == stOther.dConfidence && dStraightLineDistance == stOther.dStraightLineDistance &&
87 dYawAngle == stOther.dYawAngle && nID == stOther.nID && szClassName == stOther.szClassName && tmCreation == stOther.tmCreation &&
88 eDetectionMethod == stOther.eDetectionMethod && cvImageResolution == stOther.cvImageResolution && dHorizontalFOV == stOther.dHorizontalFOV &&
89 stGeolocatedPosition == stOther.stGeolocatedPosition;
90 }
91
92
102 bool operator!=(const ArucoTag& stOther) const { return !(*this == stOther); }
103
104
113 ArucoTag& operator=(const ArucoTag& stOther)
114 {
115 // Check if the other ArucoTag is not the same as this one.
116 if (this != &stOther)
117 {
118 // Shallow copy the bounding box.
119 pBoundingBox = stOther.pBoundingBox;
120
121 // Copy other member variables.
122 dConfidence = stOther.dConfidence;
123 dStraightLineDistance = stOther.dStraightLineDistance;
124 dYawAngle = stOther.dYawAngle;
125 nID = stOther.nID;
126 szClassName = stOther.szClassName;
127 tmCreation = stOther.tmCreation;
128 eDetectionMethod = stOther.eDetectionMethod;
129 cvImageResolution = stOther.cvImageResolution;
130 dHorizontalFOV = stOther.dHorizontalFOV;
131 stGeolocatedPosition = stOther.stGeolocatedPosition;
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:392
Represents a single ArUco tag. Combines attributes from TorchTag, TensorflowTag, and the original Aru...
Definition TagDetectionUtilty.hpp:59
bool operator!=(const ArucoTag &stOther) const
Overload the inequality operator for the ArucoTag struct.
Definition TagDetectionUtilty.hpp:102
bool operator==(const ArucoTag &stOther) const
Overload the equality operator for the ArucoTag struct.
Definition TagDetectionUtilty.hpp:84
ArucoTag & operator=(const ArucoTag &stOther)
Overload the assignment operator for the ArucoTag struct to perform a deep copy.
Definition TagDetectionUtilty.hpp:113