Run the state machine. Returns the next state.
101 {
102
103 LOG_DEBUG(logging::g_qSharedLogger, "ApproachingMarkerState: Running state-specific behavior.");
104
105
107
108
109 m_pRoverPathPlot->AddPathPoint(stCurrentRoverPose.
GetUTMCoordinate(),
"RoverPath");
110
111
113 if (stCurrentMeasurement.dDistanceMeters > m_stGoalWaypoint.dRadius)
114 {
115
116 LOG_WARNING(logging::g_qSharedLogger,
117 "ApproachingMarkerState: Rover is too far from the original waypoint! Waypoint radius is {} meters, current distance is {} meters.",
118 m_stGoalWaypoint.dRadius,
119 stCurrentMeasurement.dDistanceMeters);
120 globals::g_pStateMachineHandler->
HandleEvent(Event::eMarkerUnseen);
121 return;
122 }
123
124
127
128
129 static double dHeadingSetPoint = 0.0;
130 static double dDistanceFromTag = 0.0;
132 static bool bHasLastGeolocatedPosition = false;
133 static std::chrono::system_clock::time_point tLastSeenTime = std::chrono::system_clock::now();
134 static bool bAlreadyPrintedLost = false;
135 static bool bAlreadyPrintedVisualLostFallback = false;
136
137
138 if (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - tLastSeenTime).count() >
139 constants::APPROACH_MARKER_LOST_GIVE_UP_TIME + 5.0)
140 {
141 bHasLastGeolocatedPosition = false;
142 }
143
144
145 if (stBestArucoTag.nID == -1 && stBestTorchTag.dConfidence == 0.0)
146 {
147 std::chrono::system_clock::time_point tmCurrentTime = std::chrono::system_clock::now();
148 if ((std::chrono::duration_cast<std::chrono::milliseconds>(tmCurrentTime - tLastSeenTime).count() / 1000.0) > constants::APPROACH_MARKER_LOST_GIVE_UP_TIME)
149 {
150
151 globals::g_pStateMachineHandler->
HandleEvent(Event::eMarkerUnseen);
152 return;
153 }
154 else
155 {
156 if (!bAlreadyPrintedLost)
157 {
158 bAlreadyPrintedLost = true;
159
160 LOG_WARNING(logging::g_qSharedLogger, "ApproachingMarkerState: No tags detected.");
161 }
162
163
164 if (bHasLastGeolocatedPosition)
165 {
166
169
170
171 dHeadingSetPoint = stLastMeasurement.dStartRelativeBearing;
172 dDistanceFromTag = stLastMeasurement.dDistanceMeters;
173
174 if (!bAlreadyPrintedVisualLostFallback)
175 {
176 LOG_NOTICE(logging::g_qSharedLogger, "ApproachingMarkerState: Visual lost, driving to last known geolocated position.");
177 bAlreadyPrintedVisualLostFallback = true;
178 }
179 }
180 else
181 {
182
184 return;
185 }
186 }
187 }
188 else
189 {
190
191 if (bAlreadyPrintedLost)
192 {
193 LOG_NOTICE(logging::g_qSharedLogger, "ApproachingMarkerState: Tags were detected again.");
194 }
195
196
197 tLastSeenTime = std::chrono::system_clock::now();
198
199 bAlreadyPrintedLost = false;
200 bAlreadyPrintedVisualLostFallback = false;
201
202
203 if (stBestArucoTag.nID != -1)
204 {
205 dDistanceFromTag = stBestArucoTag.dStraightLineDistance;
206
207 if (stBestArucoTag.stGeolocatedPosition.eType != geoops::WaypointType::eUNKNOWN)
208 {
209
212
213 dHeadingSetPoint = stTagMeasurement.dStartRelativeBearing;
214
215
216 stLastGeolocatedPosition = stBestArucoTag.stGeolocatedPosition;
217 bHasLastGeolocatedPosition = true;
218
219
220 m_pRoverPathPlot->AddDot(stBestArucoTag.stGeolocatedPosition.
GetUTMCoordinate(),
"DetectedTags");
221 }
222 else
223 {
224
226 }
227 }
228
229 else if (stBestTorchTag.dConfidence != 0.0)
230 {
231 dDistanceFromTag = stBestTorchTag.dStraightLineDistance;
232
233 if (stBestTorchTag.stGeolocatedPosition.eType != geoops::WaypointType::eUNKNOWN)
234 {
235
238
239 dHeadingSetPoint = stTagMeasurement.dStartRelativeBearing;
240
241
242 stLastGeolocatedPosition = stBestTorchTag.stGeolocatedPosition;
243 bHasLastGeolocatedPosition = true;
244
245
246 m_pRoverPathPlot->AddDot(stBestTorchTag.stGeolocatedPosition.
GetUTMCoordinate(),
"DetectedTags");
247 }
248 else
249 {
250
252 }
253 }
254 }
255
256
258 dHeadingSetPoint,
260 diffdrive::DifferentialControlMethod::eArcadeDrive);
261 globals::g_pDriveBoard->
SendDrive(stDrivePowers);
262
263
264 static std::chrono::system_clock::time_point tmLastLogTime = std::chrono::system_clock::now();
265 std::chrono::system_clock::time_point tmCurrentTime = std::chrono::system_clock::now();
266
267 if (std::chrono::duration_cast<std::chrono::seconds>(tmCurrentTime - tmLastLogTime).count() >= 1)
268 {
269
270 tmLastLogTime = tmCurrentTime;
271
272 if (stBestArucoTag.nID != -1)
273 {
274 LOG_NOTICE(logging::g_qSharedLogger,
275 "ApproachingMarkerState: OpenCV Tag ID: {}, Distance: {:.2f} m, Heading: {:.2f} deg",
276 stBestArucoTag.nID,
277 dDistanceFromTag,
278 dHeadingSetPoint);
279 }
280 else if (stBestTorchTag.dConfidence != 0.0)
281 {
282 LOG_NOTICE(logging::g_qSharedLogger,
283 "ApproachingMarkerState: Torch Tag Confidence: {:.2f}, Distance: {:.2f} m, Heading: {:.2f} deg",
284 stBestTorchTag.dConfidence,
285 dDistanceFromTag,
286 dHeadingSetPoint);
287 }
288 }
289
290
291 if (dDistanceFromTag != 0.0 && dDistanceFromTag < constants::APPROACH_MARKER_PROXIMITY_THRESHOLD)
292 {
293
294 LOG_NOTICE(logging::g_qSharedLogger, "ApproachingMarkerState: Rover has reached the target marker!");
295
296 if (stBestArucoTag.nID != -1 && stBestArucoTag.stGeolocatedPosition.eType == geoops::WaypointType::eTagWaypoint)
297 {
298
299 m_pRoverPathPlot->AddDot(stBestArucoTag.stGeolocatedPosition.
GetUTMCoordinate(),
"FinalTag", 7);
300 }
301
302 if (stBestTorchTag.dConfidence != 0.0 && stBestTorchTag.stGeolocatedPosition.eType == geoops::WaypointType::eTagWaypoint)
303 {
304
305 m_pRoverPathPlot->AddDot(stBestTorchTag.stGeolocatedPosition.
GetUTMCoordinate(),
"FinalTag", 7);
306 }
307
308
309 dHeadingSetPoint = 0.0;
310 dDistanceFromTag = 0.0;
311 bHasLastGeolocatedPosition = false;
312
313
314 globals::g_pStateMachineHandler->
HandleEvent(Event::eReachedMarker,
true);
315
316 return;
317 }
318
320
322
323
324 if (constants::APPROACH_MARKER_ENABLE_STUCK_DETECT &&
325 m_StuckDetector.
CheckIfStuck(globals::g_pStateMachineHandler->SmartRetrieveVelocity(), globals::g_pStateMachineHandler->SmartRetrieveAngularVelocity()))
326 {
327
328 LOG_NOTICE(logging::g_qSharedLogger, "ApproachingMarkerState: Rover has become stuck!");
329
330 globals::g_pStateMachineHandler->
HandleEvent(Event::eStuck,
true);
331
332 return;
333 }
334
335 return;
336 }
void SendDrive(const diffdrive::DrivePowers &stDrivePowers, const bool bEnableVariableDriveEffort=true)
Sets the left and right drive powers of the drive board.
Definition DriveBoard.cpp:118
void SendStop()
Stop the drivetrain of the Rover.
Definition DriveBoard.cpp:195
diffdrive::DrivePowers CalculateMove(const double dGoalSpeed, const double dGoalHeading, const double dActualHeading, const diffdrive::DifferentialControlMethod eKinematicsMethod=diffdrive::DifferentialControlMethod::eArcadeDrive, const bool bAlwaysProgressForward=false)
This method determines drive powers to make the Rover drive towards a given heading at a given speed.
Definition DriveBoard.cpp:88
geoops::RoverPose SmartRetrieveRoverPose(bool bVIOHeading=true, bool bVIOTracking=false)
Retrieve the rover's current position and heading. Automatically picks between getting the position/h...
Definition StateMachineHandler.cpp:445
void HandleEvent(statemachine::Event eEvent, const bool bSaveCurrentState=false)
This method Handles Events that are passed to the State Machine Handler. It will check the current st...
Definition StateMachineHandler.cpp:353
bool CheckIfStuck(double dCurrentVelocity, double dCurrentAngularVelocity)
Checks if the rover meets stuck criteria based in the given parameters.
Definition StuckDetection.hpp:105
GeoMeasurement CalculateGeoMeasurement(const GPSCoordinate &stCoord1, const GPSCoordinate &stCoord2)
The shortest path between two points on an ellipsoid at (lat1, lon1) and (lat2, lon2) is called the g...
Definition GeospatialOperations.hpp:553
constexpr T InputAngleModulus(T tValue, T tMinValue, T tMaxValue)
Calculates the modulus of an input angle.
Definition NumberOperations.hpp:165
int IdentifyTargetMarker(const std::vector< std::shared_ptr< TagDetector > > &vTagDetectors, tagdetectutils::ArucoTag &stArucoTarget, tagdetectutils::ArucoTag &stTorchTarget, const int nTargetTagID=static_cast< int >(manifest::Autonomy::AUTONOMYWAYPOINTTYPES::ANY))
Identify a target marker in the rover's vision, using OpenCV detection.
Definition TagDetectionChecker.hpp:91
This struct is used to store the left and right drive powers for the robot. Storing these values in a...
Definition DifferentialDrive.hpp:73
This struct is used to store the distance, arc length, and relative bearing for a calculated geodesic...
Definition GeospatialOperations.hpp:83
This struct is used by the WaypointHandler to provide an easy way to store all pose data about the ro...
Definition GeospatialOperations.hpp:708
const geoops::GPSCoordinate & GetGPSCoordinate() const
Accessor for the geoops::GPSCoordinate member variable.
Definition GeospatialOperations.hpp:756
double GetCompassHeading() const
Accessor for the Compass Heading private member.
Definition GeospatialOperations.hpp:787
const geoops::UTMCoordinate & GetUTMCoordinate() const
Accessor for the geoops::UTMCoordinate member variable.
Definition GeospatialOperations.hpp:767
This struct is used by the WaypointHandler class to store location, size, and type information about ...
Definition GeospatialOperations.hpp:423
const geoops::GPSCoordinate & GetGPSCoordinate() const
Accessor for the geoops::GPSCoordinate member variable.
Definition GeospatialOperations.hpp:497
const geoops::UTMCoordinate & GetUTMCoordinate() const
Accessor for the geoops::UTMCoordinate member variable.
Definition GeospatialOperations.hpp:508
Represents a single ArUco tag. Combines attributes from TorchTag, TensorflowTag, and the original Aru...
Definition TagDetectionUtilty.hpp:59