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
statemachine::ApproachingObjectState Class Reference

The ApproachingObjectState class implements the Approaching Object state for the Autonomy State Machine. More...

#include <ApproachingObjectState.h>

Inheritance diagram for statemachine::ApproachingObjectState:
Collaboration diagram for statemachine::ApproachingObjectState:

Public Member Functions

 ApproachingObjectState ()
 Construct a new State object.
 
void Run () override
 Run the state machine. Returns the next state.
 
States TriggerEvent (Event eEvent) override
 Trigger an event in the state machine. Returns the next state.
 
- Public Member Functions inherited from statemachine::State
 State (States eState)
 Construct a new State object.
 
virtual ~State ()=default
 Destroy the State object.
 
States GetState () const
 Accessor for the State private member.
 
virtual std::string ToString () const
 Accessor for the State private member. Returns the state as a string.
 
virtual bool operator== (const State &other) const
 Checks to see if the current state is equal to the passed state.
 
virtual bool operator!= (const State &other) const
 Checks to see if the current state is not equal to the passed state.
 

Protected Member Functions

void Start () override
 This method is called when the state is first started. It is used to initialize the state.
 
void Exit () override
 This method is called when the state is exited. It is used to clean up the state.
 

Private Attributes

std::vector< std::shared_ptr< ObjectDetector > > m_vObjectDetectors
 
statemachine::TimeIntervalBasedStuckDetector m_StuckDetector
 
States m_eTriggeringState
 
bool m_bInitialized
 
geoops::Waypoint m_stGoalWaypoint
 
std::unique_ptr< logging::graphing::PathTracerm_pRoverPathPlot
 

Detailed Description

The ApproachingObjectState class implements the Approaching Object state for the Autonomy State Machine.

Author
Eli Byrd (edbgk.nosp@m.k@ms.nosp@m.t.edu), Sam Hajdukiewicz (saman.nosp@m.thah.nosp@m.ajduk.nosp@m.iewi.nosp@m.cz@gm.nosp@m.ail..nosp@m.com)
Date
2024-01-17

Constructor & Destructor Documentation

◆ ApproachingObjectState()

statemachine::ApproachingObjectState::ApproachingObjectState ( )

Construct a new State object.

Author
Sam Hajdukiewicz (saman.nosp@m.thah.nosp@m.ajduk.nosp@m.iewi.nosp@m.cz@gm.nosp@m.ail..nosp@m.com)
Date
2024-01-17
73 : State(States::eApproachingObject)
74 {
75 LOG_INFO(logging::g_qConsoleLogger, "Entering State: {}", ToString());
76
77 m_bInitialized = false;
78
79 m_StuckDetector = statemachine::TimeIntervalBasedStuckDetector(constants::STUCK_CHECK_ATTEMPTS,
80 constants::STUCK_CHECK_INTERVAL,
81 constants::STUCK_CHECK_VEL_THRESH,
82 constants::STUCK_CHECK_ROT_THRESH);
83 m_pRoverPathPlot = std::make_unique<logging::graphing::PathTracer>("ApproachingObjectRoverPath");
84
85 if (!m_bInitialized)
86 {
87 Start();
88 m_bInitialized = true;
89 }
90 }
void Start() override
This method is called when the state is first started. It is used to initialize the state.
Definition ApproachingObjectState.cpp:33
virtual std::string ToString() const
Accessor for the State private member. Returns the state as a string.
Definition State.hpp:202
State(States eState)
Construct a new State object.
Definition State.hpp:145
This class should be instantiated within another state to be used for detection of if the rover is st...
Definition StuckDetection.hpp:43
Here is the call graph for this function:

Member Function Documentation

◆ Start()

void statemachine::ApproachingObjectState::Start ( )
overrideprotectedvirtual

This method is called when the state is first started. It is used to initialize the state.

Author
Sam Hajdukiewicz (saman.nosp@m.thah.nosp@m.ajduk.nosp@m.iewi.nosp@m.cz@gm.nosp@m.ail..nosp@m.com)
Date
2024-01-17

Reimplemented from statemachine::State.

34 {
35 // Schedule the next run of the state's logic
36 LOG_INFO(logging::g_qSharedLogger, "ApproachingObjectState: Scheduling next run of state logic.");
37
38 // Initialize member variables.
39 m_stGoalWaypoint = globals::g_pWaypointHandler->PeekNextWaypoint();
40
41 // Store the state that got stuck and triggered an ObjectSeen event.
42 m_eTriggeringState = globals::g_pStateMachineHandler->GetPreviousState();
43
44 // Add the search and rover path layers to the plot.
45 m_pRoverPathPlot->CreateDotLayer("DetectedObjects", "blue");
46 m_pRoverPathPlot->CreateDotLayer("FinalObject", "green");
47 m_pRoverPathPlot->CreatePathLayer("RoverPath", "-k");
48
49 m_vObjectDetectors = {globals::g_pObjectDetectionHandler->GetObjectDetector(ObjectDetectionHandler::ObjectDetectors::eHeadMainCam)};
50 }
std::shared_ptr< ObjectDetector > GetObjectDetector(ObjectDetectors eDetectorName)
Accessor for ObjectDetector detectors.
Definition ObjectDetectionHandler.cpp:127
statemachine::States GetPreviousState() const
Accessor for the Previous State private member.
Definition StateMachineHandler.cpp:426
const geoops::Waypoint PeekNextWaypoint()
Returns an immutable reference to the geoops::Waypoint struct at the front of the list without removi...
Definition WaypointHandler.cpp:540
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Exit()

void statemachine::ApproachingObjectState::Exit ( )
overrideprotectedvirtual

This method is called when the state is exited. It is used to clean up the state.

Author
Eli Byrd (edbgk.nosp@m.k@ms.nosp@m.t.edu)
Date
2024-01-17

Reimplemented from statemachine::State.

61 {
62 // Clean up the state before exiting
63 LOG_INFO(logging::g_qSharedLogger, "ApproachingObjectState: Exiting state.");
64 }
Here is the caller graph for this function:

◆ Run()

void statemachine::ApproachingObjectState::Run ( )
overridevirtual

Run the state machine. Returns the next state.

Author
Sam Hajdukiewicz (saman.nosp@m.thah.nosp@m.ajduk.nosp@m.iewi.nosp@m.cz@gm.nosp@m.ail..nosp@m.com)
Date
2024-01-17

Implements statemachine::State.

99 {
100 // Submit logger message.
101 LOG_DEBUG(logging::g_qSharedLogger, "ApproachingObjectState: Running state-specific behavior.");
102
103 // Get the current rover pose.
104 geoops::RoverPose stCurrentRoverPose = globals::g_pStateMachineHandler->SmartRetrieveRoverPose();
105
106 // Add the current rover pose to the path plot.
107 m_pRoverPathPlot->AddPathPoint(stCurrentRoverPose.GetUTMCoordinate(), "RoverPath");
108
109 // Check Rover radius from object waypoint.
110 geoops::GeoMeasurement stCurrentMeasurement = geoops::CalculateGeoMeasurement(m_stGoalWaypoint.GetGPSCoordinate(), stCurrentRoverPose.GetGPSCoordinate());
111 if (stCurrentMeasurement.dDistanceMeters > m_stGoalWaypoint.dRadius)
112 {
113 // Submit logger message.
114 LOG_WARNING(logging::g_qSharedLogger,
115 "ApproachingObjectState: Rover is too far from the original waypoint! Waypoint radius is {} meters, current distance is {} meters.",
116 m_stGoalWaypoint.dRadius,
117 stCurrentMeasurement.dDistanceMeters);
118 globals::g_pStateMachineHandler->HandleEvent(Event::eObjectUnseen);
119 return;
120 }
121
122 // Identify target object.
123 objectdetectutils::Object stBestObject;
124 statemachine::IdentifyTargetObject(m_vObjectDetectors, stBestObject, m_stGoalWaypoint.eType);
125
126 // Persistent variables to track target across frames
127 static double dHeadingSetPoint = 0.0;
128 static double dDistanceFromObject = 0.0;
129 static geoops::Waypoint stLastGeolocatedPosition;
130 static bool bHasLastGeolocatedPosition = false;
131 static std::chrono::system_clock::time_point tLastSeenTime = std::chrono::system_clock::now();
132 static bool bAlreadyPrintedLost = false;
133 static bool bAlreadyPrintedVisualLostFallback = false;
134
135 // Check for stale session data (if we re-entered this state after a long time).
136 if (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - tLastSeenTime).count() >
137 constants::APPROACH_OBJECT_LOST_GIVE_UP_TIME + 5.0)
138 {
139 bHasLastGeolocatedPosition = false;
140 }
141
142 // Check if object is unseen.
143 if (stBestObject.dConfidence == 0.0)
144 {
145 std::chrono::system_clock::time_point tmCurrentTime = std::chrono::system_clock::now();
146 if ((std::chrono::duration_cast<std::chrono::milliseconds>(tmCurrentTime - tLastSeenTime).count() / 1000.0) > constants::APPROACH_OBJECT_LOST_GIVE_UP_TIME)
147 {
148 // Submit logger message.
149 globals::g_pStateMachineHandler->HandleEvent(Event::eObjectUnseen);
150 return;
151 }
152 else
153 {
154 if (!bAlreadyPrintedLost)
155 {
156 bAlreadyPrintedLost = true;
157 // Submit logger message.
158 LOG_WARNING(logging::g_qSharedLogger, "ApproachingObjectState: No objects detected.");
159 }
160
161 // If we have a valid last known geolocated position, keep driving to it.
162 if (bHasLastGeolocatedPosition)
163 {
164 // Calculate the geomeasurement to the last known position.
165 geoops::GeoMeasurement stLastMeasurement =
166 geoops::CalculateGeoMeasurement(stCurrentRoverPose.GetUTMCoordinate(), stLastGeolocatedPosition.GetUTMCoordinate());
167
168 // Update setpoints to track the last known location.
169 dHeadingSetPoint = stLastMeasurement.dStartRelativeBearing;
170 dDistanceFromObject = stLastMeasurement.dDistanceMeters;
171
172 if (!bAlreadyPrintedVisualLostFallback)
173 {
174 LOG_NOTICE(logging::g_qSharedLogger, "ApproachingObjectState: Visual lost, driving to last known geolocated position.");
175 bAlreadyPrintedVisualLostFallback = true;
176 }
177 }
178 else
179 {
180 // Stop the drive.
181 globals::g_pDriveBoard->SendStop();
182 return;
183 }
184 }
185 }
186 else // Object Detected
187 {
188 // Submit logger message.
189 if (bAlreadyPrintedLost)
190 {
191 LOG_NOTICE(logging::g_qSharedLogger, "ApproachingObjectState: Objects were detected again.");
192 }
193
194 // Reset the last seen time if a tag is detected.
195 tLastSeenTime = std::chrono::system_clock::now();
196 // Reset printed flags when tags are detected again.
197 bAlreadyPrintedLost = false;
198 bAlreadyPrintedVisualLostFallback = false;
199
200 // Check if we got a good object.
201 if (stBestObject.dConfidence != 0.0)
202 {
203 dDistanceFromObject = stBestObject.dStraightLineDistance;
204 // Check if the object has an absolute coordinate populated.
205 if (stBestObject.stGeolocatedPosition.eType != geoops::WaypointType::eUNKNOWN)
206 {
207 // Calculate the geomeasurement to the object.
208 geoops::GeoMeasurement stObjectMeasurement =
209 geoops::CalculateGeoMeasurement(stCurrentRoverPose.GetUTMCoordinate(), stBestObject.stGeolocatedPosition.GetUTMCoordinate());
210 // Update static variables.
211 dHeadingSetPoint = stObjectMeasurement.dStartRelativeBearing;
212
213 // Save geolocated position for fallback.
214 stLastGeolocatedPosition = stBestObject.stGeolocatedPosition;
215 bHasLastGeolocatedPosition = true;
216
217 // Add the most recent geolocated object to the path plot.
218 m_pRoverPathPlot->AddDot(stBestObject.stGeolocatedPosition.GetUTMCoordinate(), "DetectedObjects");
219 }
220 else
221 {
222 // Fallback to relative tracking (Current Heading + Yaw Angle).
223 dHeadingSetPoint = numops::InputAngleModulus(stBestObject.dYawAngle + stCurrentRoverPose.GetCompassHeading(), 0.0, 360.0);
224 }
225 }
226 }
227
228 // Move the rover to the target's estimated position.
229 diffdrive::DrivePowers stDrivePowers = globals::g_pDriveBoard->CalculateMove(constants::APPROACH_OBJECT_MOTOR_POWER,
230 dHeadingSetPoint,
231 stCurrentRoverPose.GetCompassHeading(),
232 diffdrive::DifferentialControlMethod::eArcadeDrive);
233 globals::g_pDriveBoard->SendDrive(stDrivePowers);
234
235 // Static variable to track last log time.
236 static std::chrono::system_clock::time_point tmLastOLogTime = std::chrono::system_clock::now();
237 std::chrono::system_clock::time_point tmCurrentTime = std::chrono::system_clock::now();
238 if (std::chrono::duration_cast<std::chrono::seconds>(tmCurrentTime - tmLastOLogTime).count() >= 1)
239 {
240 // Update the last log time.
241 tmLastOLogTime = tmCurrentTime;
242
243 if (stBestObject.dConfidence != 0.0)
244 {
245 LOG_NOTICE(logging::g_qSharedLogger,
246 "ApproachingObjectState: Object confidence: {:.2f}, Distance: {:.2f} m, Heading: {:.2f} deg",
247 stBestObject.dConfidence,
248 dDistanceFromObject,
249 dHeadingSetPoint);
250 }
251 }
252
253 // Check if tag is reached.
254 if (dDistanceFromObject != 0.0 && dDistanceFromObject < constants::APPROACH_OBJECT_PROXIMITY_THRESHOLD)
255 {
256 // Submit logger message.
257 LOG_NOTICE(logging::g_qSharedLogger, "ApproachingObjectState: Rover has reached the target object!");
258 // Check if the object has a good absolute position.
259 if (stBestObject.dConfidence != 0.0 && stBestObject.stGeolocatedPosition.eType == geoops::WaypointType::eObjectWaypoint)
260 {
261 // Add the object to the path plot.
262 m_pRoverPathPlot->AddDot(stBestObject.stGeolocatedPosition.GetUTMCoordinate(), "FinalObject", 7);
263 }
264
265 // Reset the object heading and distance.
266 dHeadingSetPoint = 0.0;
267 dDistanceFromObject = 0.0;
268 bHasLastGeolocatedPosition = false;
269
270 // Handle state transition and save the current search pattern state.
271 globals::g_pStateMachineHandler->HandleEvent(Event::eReachedObject, true);
272 // Don't execute the rest of the state.
273 return;
274 }
275
277 // --- Check if the rover is stuck --- //
279
280 // Check if stuck.
281 if (constants::APPROACH_OBJECT_ENABLE_STUCK_DETECT &&
282 m_StuckDetector.CheckIfStuck(globals::g_pStateMachineHandler->SmartRetrieveVelocity(), globals::g_pStateMachineHandler->SmartRetrieveAngularVelocity()))
283 {
284 // Submit logger message.
285 LOG_NOTICE(logging::g_qSharedLogger, "ApproachingObjectState: Rover has become stuck!");
286 // Handle state transition and save the current search pattern state.
287 globals::g_pStateMachineHandler->HandleEvent(Event::eStuck, true);
288 // Don't execute the rest of the state.
289 return;
290 }
291
292 return;
293 }
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 IdentifyTargetObject(const std::vector< std::shared_ptr< ObjectDetector > > &vObjectDetectors, objectdetectutils::Object &stObjectTarget, const geoops::WaypointType &eDesiredDetectionType=geoops::WaypointType::eUNKNOWN)
Identify a target object in the rover's vision, using Torch detection.
Definition ObjectDetectionChecker.hpp:90
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 detected object. Combines attributes from TorchObject and TensorflowObject struct...
Definition ObjectDetectionUtility.hpp:74
Here is the call graph for this function:

◆ TriggerEvent()

States statemachine::ApproachingObjectState::TriggerEvent ( Event  eEvent)
overridevirtual

Trigger an event in the state machine. Returns the next state.

Parameters
eEvent- The event to trigger.
Returns
std::shared_ptr<State> - The next state.
Author
Sam Hajdukiewicz (saman.nosp@m.thah.nosp@m.ajduk.nosp@m.iewi.nosp@m.cz@gm.nosp@m.ail..nosp@m.com)
Date
2024-01-17

Implements statemachine::State.

305 {
306 // Create instance variables.
307 States eNextState = States::eApproachingObject;
308 bool bCompleteStateExit = true;
309
310 switch (eEvent)
311 {
312 case Event::eReachedObject:
313 {
314 // Submit logger message.
315 LOG_INFO(logging::g_qSharedLogger, "ApproachingObjectState: Handling ReachedObject event.");
316
317 // Check if verifying object state is enabled.
318 if (constants::APPROACH_OBJECT_VERIFY_POSITION)
319 {
320 // Change states.
321 eNextState = States::eVerifyingObject;
322 }
323 else
324 {
325 // Send multimedia command to update state display.
326 globals::g_pMultimediaBoard->SendLightingState(MultimediaBoard::MultimediaBoardLightingState::eReachedGoal);
327 // Pop old waypoint out of queue.
328 globals::g_pWaypointHandler->PopNextWaypoint();
329 // Clear saved search pattern state.
330 globals::g_pStateMachineHandler->ClearSavedStates();
331 // Submit logger message.
332 LOG_NOTICE(logging::g_qSharedLogger, "ApproachingObjectState: Cleared old search pattern state and approaching object state from saved states.");
333 // Change state.
334 eNextState = States::eIdle;
335 }
336 break;
337 }
338 case Event::eStart:
339 {
340 // Submit logger message.
341 LOG_INFO(logging::g_qSharedLogger, "ApproachingObjectState: Handling Start event.");
342 // Send multimedia command to update state display.
343 globals::g_pMultimediaBoard->SendLightingState(MultimediaBoard::MultimediaBoardLightingState::eAutonomy);
344 break;
345 }
346 case Event::eObjectUnseen:
347 {
348 // Submit logger message.
349 LOG_INFO(logging::g_qSharedLogger, "ApproachingObjectState: Handling ObjectUnseen event.");
350 // Change states.
351 eNextState = m_eTriggeringState;
352 break;
353 }
354 case Event::eAbort:
355 {
356 // Submit logger message.
357 LOG_INFO(logging::g_qSharedLogger, "ApproachingObjectState: Handling Abort event.");
358 // Send multimedia command to update state display.
359 globals::g_pMultimediaBoard->SendLightingState(MultimediaBoard::MultimediaBoardLightingState::eOff);
360 // Change state.
361 eNextState = States::eIdle;
362 break;
363 }
364 default:
365 {
366 LOG_WARNING(logging::g_qSharedLogger, "ApproachingObjectState: Handling unknown event.");
367 eNextState = States::eIdle;
368 break;
369 }
370 }
371
372 if (eNextState != States::eApproachingMarker)
373 {
374 LOG_INFO(logging::g_qSharedLogger, "ApproachingObjectState: Transitioning to {} State.", StateToString(eNextState));
375
376 // Exit the current state
377 if (bCompleteStateExit)
378 {
379 Exit();
380 }
381 }
382
383 return eNextState;
384 }
void SendLightingState(MultimediaBoardLightingState eState)
Sends a predetermined color pattern to board.
Definition MultimediaBoard.cpp:55
void ClearSavedStates()
Clear all saved states.
Definition StateMachineHandler.cpp:379
geoops::Waypoint PopNextWaypoint()
Removes and returns the next waypoint at the front of the list.
Definition WaypointHandler.cpp:500
void Exit() override
This method is called when the state is exited. It is used to clean up the state.
Definition ApproachingObjectState.cpp:60
std::string StateToString(States eState)
Converts a state object to a string.
Definition State.hpp:85
States
The states that the state machine can be in.
Definition State.hpp:31
Here is the call graph for this function:

The documentation for this class was generated from the following files: