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
StateMachineHandler Class Reference

The StateMachineHandler class serves as the main state machine for Autonomy Software. It will handle all state transitions and run the logic for each state. More...

#include <StateMachineHandler.h>

Inheritance diagram for StateMachineHandler:
Collaboration diagram for StateMachineHandler:

Public Member Functions

 StateMachineHandler ()
 Construct a new State Machine Handler object.
 
 ~StateMachineHandler ()
 Destroy the State Machine Handler:: State Machine Handler object.
 
void StartStateMachine ()
 This method will start the state machine. It will set the first state to Idle and start the thread pool.
 
void StopStateMachine ()
 This method will stop the state machine. It will signal whatever state is currently running to abort back to idle and then stop the main code running in the ThreadedContinuousCode() method.
 
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 state and run the state's HandleEvent() method. It will then check the state's transition conditions and transition to the next state if the conditions are met.
 
void ClearSavedStates ()
 Clear all saved states.
 
void ClearSavedState (statemachine::States eState)
 Clear a saved state based on the given state.
 
statemachine::States GetCurrentState () const
 Accessor for the Current State private member.
 
statemachine::States GetPreviousState () const
 Accessor for the Previous State private member.
 
void RealignZEDPosition (CameraHandler::ZEDCamName eCameraName, const geoops::UTMCoordinate &stNewCameraPosition, const double dNewCameraHeading)
 This is used to realign the ZEDs forward direction with the rover's current compass heading. Realigning GPS latlon is not necessary since we're using the ZEDSDK's Fusion module. The heading of the camera's GeoPose is actually automatically realigned too depending on what direction We are headed, but this is just to be safe.
 
IPSGetIPS ()
 Accessor for the Frame I P S private member.
 

Private Member Functions

std::shared_ptr< statemachine::StateCreateState (statemachine::States eState)
 Create a State object based of of the State enum.
 
void ChangeState (statemachine::States eNextState, const bool bSaveCurrentState=false)
 Transition to a new state. This function is called by the HandleEvent and checks to see if this state is already stored in the map of exited states. If it is, it loads the state from the map. If not, it creates a new state and stores it in the map.
 
void SaveCurrentState ()
 Save the current state to the map of exited states. This is used to store the state when the state machine is transitioning to a new state. And prevents the state from being deleted when the state machine transitions to a new state.
 
void ThreadedContinuousCode () override
 This code will run continuously in a separate thread. The State Machine Handler will check the current state and run the state's logic. It will then check the state's transition conditions and transition to the next state if the conditions are met.
 
void PooledLinearCode () override
 This method holds the code that is ran in the thread pool started by the ThreadedLinearCode() method. It currently does nothing and is not needed in the current implementation of the StateMachineHandler.
 
- Private Member Functions inherited from AutonomyThread< void >
 AutonomyThread ()
 Construct a new Autonomy Thread object.
 
virtual ~AutonomyThread ()
 Destroy the Autonomy Thread object. If the parent object or main thread is destroyed or exited while this thread is still running, a race condition will occur. Stopping and joining the thread here insures that the main program can't exit if the user forgot to stop and join the thread.
 
void Start ()
 When this method is called, it starts a new thread that runs the code within the ThreadedContinuousCode method. This is the users main code that will run the important and continuous code for the class.
 
void RequestStop ()
 Signals threads to stop executing user code, terminate. DOES NOT JOIN. This method will not force the thread to exit, if the user code is not written properly and contains WHILE statement or any other long-executing or blocking code, then the thread will not exit until the next iteration.
 
void Join ()
 Waits for thread to finish executing and then closes thread. This method will block the calling code until thread is finished.
 
bool Joinable () const
 Check if the code within the thread and all pools created by it are finished executing and the thread is ready to be closed.
 
AutonomyThreadState GetThreadState () const
 Accessor for the Threads State private member.
 
IPSGetIPS ()
 Accessor for the Frame I P S private member.
 
void RunPool (const unsigned int nNumTasksToQueue, const unsigned int nNumThreads=2, const bool bForceStopCurrentThreads=false)
 When this method is called, it starts/adds tasks to a thread pool that runs nNumTasksToQueue copies of the code within the PooledLinearCode() method using nNumThreads number of threads. This is meant to be used as an internal utility of the child class to further improve parallelization. Default value for nNumThreads is 2.
 
void RunDetachedPool (const unsigned int nNumTasksToQueue, const unsigned int nNumThreads=2, const bool bForceStopCurrentThreads=false)
 When this method is called, it starts a thread pool full of threads that don't return std::futures (like a placeholder for the thread return type). This means the thread will not have a return type and there is no way to determine if the thread has finished other than calling the Join() method. Only use this if you want to 'set and forget'. It will be faster as it doesn't return futures. Runs PooledLinearCode() method code. This is meant to be used as an internal utility of the child class to further improve parallelization.
 
void ParallelizeLoop (const int nNumThreads, const N tTotalIterations, F &&tLoopFunction)
 Given a ref-qualified looping function and an arbitrary number of iterations, this method will divide up the loop and run each section in a thread pool. This function must not return anything. This method will block until the loop has completed.
 
void ClearPoolQueue ()
 Clears any tasks waiting to be ran in the queue, tasks currently running will remain running.
 
void JoinPool ()
 Waits for pool to finish executing tasks. This method will block the calling code until thread is finished.
 
bool PoolJoinable () const
 Check if the internal pool threads are done executing code and the queue is empty.
 
void SetMainThreadIPSLimit (int nMaxIterationsPerSecond=0)
 Mutator for the Main Thread Max I P S private member.
 
int GetPoolNumOfThreads ()
 Accessor for the Pool Num Of Threads private member.
 
int GetPoolQueueLength ()
 Accessor for the Pool Queue Size private member.
 
std::vector< void > GetPoolResults ()
 Accessor for the Pool Results private member. The action of getting results will destroy and remove them from this object. This method blocks if the thread is not finished, so no need to call JoinPool() before getting results.
 
int GetMainThreadMaxIPS () const
 Accessor for the Main Thread Max I P S private member.
 

Private Attributes

std::shared_ptr< statemachine::Statem_pCurrentState
 
std::shared_ptr< statemachine::Statem_pPreviousState
 
std::unordered_map< statemachine::States, std::shared_ptr< statemachine::State > > m_umSavedStates
 
std::shared_mutex m_muStateMutex
 
std::shared_mutex m_muEventMutex
 
std::atomic_bool m_bSwitchingStates
 
ZEDCameram_pMainCam
 
geoops::GPSCoordinate m_stCurrentGPSLocation
 
const std::function< void(const rovecomm::RoveCommPacket< uint8_t > &, const sockaddr_in &)> AutonomyStartCallback
 Callback function used to trigger the start of autonomy. No matter what state we are in, signal a StartAutonomy Event.
 
const std::function< void(const rovecomm::RoveCommPacket< uint8_t > &, const sockaddr_in &)> AutonomyStopCallback
 Callback function used to trigger autonomy to stop. No matter what state we are in, signal an Abort Event.
 
const std::function< void(const rovecomm::RoveCommPacket< float > &, const sockaddr_in &)> PMSCellVoltageCallback
 Callback function used to force autonomy into Idle state if battery voltage gets too low. No matter what state we are in, signal an Abort Event.
 
- Private Attributes inherited from AutonomyThread< void >
IPS m_IPS
 

Additional Inherited Members

- Private Types inherited from AutonomyThread< void >
enum  AutonomyThreadState
 

Detailed Description

The StateMachineHandler class serves as the main state machine for Autonomy Software. It will handle all state transitions and run the logic for each state.

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

Constructor & Destructor Documentation

◆ StateMachineHandler()

StateMachineHandler::StateMachineHandler ( )

Construct a new State Machine Handler object.

Author
Eli Byrd (edbgk.nosp@m.k@ms.nosp@m.t.edu)
Date
2024-01-17
24{
25 // Submit logger message.
26 LOG_INFO(logging::g_qSharedLogger, "Initializing State Machine.");
27
28 // Subscribe to PMS packets.
29 rovecomm::RoveCommPacket<u_int8_t> stSubscribePacket;
30 stSubscribePacket.unDataId = manifest::System::SUBSCRIBE_DATA_ID;
31 stSubscribePacket.unDataCount = 0;
32 stSubscribePacket.eDataType = manifest::DataTypes::UINT8_T;
33 stSubscribePacket.vData = std::vector<uint8_t>{};
34 network::g_pRoveCommUDPNode->SendUDPPacket(stSubscribePacket, manifest::PMS::IP_ADDRESS.IP_STR.c_str(), constants::ROVECOMM_OUTGOING_UDP_PORT);
35
36 // Set RoveComm Node callbacks.
37 network::g_pRoveCommUDPNode->AddUDPCallback<uint8_t>(AutonomyStartCallback, manifest::Autonomy::COMMANDS.find("STARTAUTONOMY")->second.DATA_ID);
38 network::g_pRoveCommUDPNode->AddUDPCallback<uint8_t>(AutonomyStopCallback, manifest::Autonomy::COMMANDS.find("DISABLEAUTONOMY")->second.DATA_ID);
39 network::g_pRoveCommUDPNode->AddUDPCallback<float>(PMSCellVoltageCallback, manifest::PMS::TELEMETRY.find("CELLVOLTAGE")->second.DATA_ID);
40
41 // Initialize member variables.
42 m_pMainCam = globals::g_pCameraHandler->GetZED(CameraHandler::ZEDCamName::eHeadMainCam);
43
44 // State machine doesn't need to run at an unlimited speed. Cap main thread to a certain amount of iterations per second.
45 this->SetMainThreadIPSLimit(constants::STATEMACHINE_MAX_IPS);
46}
void SetMainThreadIPSLimit(int nMaxIterationsPerSecond=0)
Mutator for the Main Thread Max I P S private member.
Definition AutonomyThread.hpp:467
ZEDCamera * GetZED(ZEDCamName eCameraName)
Accessor for ZED cameras.
Definition CameraHandler.cpp:210
const std::function< void(const rovecomm::RoveCommPacket< uint8_t > &, const sockaddr_in &)> AutonomyStartCallback
Callback function used to trigger the start of autonomy. No matter what state we are in,...
Definition StateMachineHandler.h:77
const std::function< void(const rovecomm::RoveCommPacket< float > &, const sockaddr_in &)> PMSCellVoltageCallback
Callback function used to force autonomy into Idle state if battery voltage gets too low....
Definition StateMachineHandler.h:121
const std::function< void(const rovecomm::RoveCommPacket< uint8_t > &, const sockaddr_in &)> AutonomyStopCallback
Callback function used to trigger autonomy to stop. No matter what state we are in,...
Definition StateMachineHandler.h:99
::uint8_t uint8_t
Here is the call graph for this function:

◆ ~StateMachineHandler()

StateMachineHandler::~StateMachineHandler ( )

Destroy the State Machine Handler:: State Machine Handler object.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-03-15
56{
57 // Check if state machine is running.
58 if (this->GetThreadState() == AutonomyThreadState::eRunning)
59 {
60 // Stop state machine.
61 this->StopStateMachine();
62 }
63}
AutonomyThreadState GetThreadState() const
Accessor for the Threads State private member.
Definition AutonomyThread.hpp:214
void StopStateMachine()
This method will stop the state machine. It will signal whatever state is currently running to abort ...
Definition StateMachineHandler.cpp:200
Here is the call graph for this function:

Member Function Documentation

◆ CreateState()

std::shared_ptr< statemachine::State > StateMachineHandler::CreateState ( statemachine::States  eState)
private

Create a State object based of of the State enum.

Parameters
eState- The State enum to create a State object from.
Returns
std::shared_ptr<State> - The State object created from the State enum.
Author
Eli Byrd (edbgk.nosp@m.k@ms.nosp@m.t.edu)
Date
2024-01-17
75{
76 switch (eState)
77 {
78 case statemachine::States::eIdle: return std::make_shared<statemachine::IdleState>();
79 case statemachine::States::eNavigating: return std::make_shared<statemachine::NavigatingState>();
80 case statemachine::States::eSearchPattern: return std::make_shared<statemachine::SearchPatternState>();
81 case statemachine::States::eApproachingMarker: return std::make_shared<statemachine::ApproachingMarkerState>();
82 case statemachine::States::eApproachingObject: return std::make_shared<statemachine::ApproachingObjectState>();
83 case statemachine::States::eVerifyingPosition: return std::make_shared<statemachine::VerifyingPositionState>();
84 case statemachine::States::eVerifyingMarker: return std::make_shared<statemachine::VerifyingMarkerState>();
85 case statemachine::States::eVerifyingObject: return std::make_shared<statemachine::VerifyingObjectState>();
86 case statemachine::States::eAvoidance: return std::make_shared<statemachine::AvoidanceState>();
87 case statemachine::States::eReversing: return std::make_shared<statemachine::ReversingState>();
88 case statemachine::States::eStuck: return std::make_shared<statemachine::StuckState>();
89 default:
90 // Handle the default case or throw an exception if needed
91 LOG_ERROR(logging::g_qSharedLogger, "State {} not found.", static_cast<int>(eState));
92 }
93
94 return nullptr;
95}
Here is the caller graph for this function:

◆ ChangeState()

void StateMachineHandler::ChangeState ( statemachine::States  eNextState,
const bool  bSaveCurrentState = false 
)
private

Transition to a new state. This function is called by the HandleEvent and checks to see if this state is already stored in the map of exited states. If it is, it loads the state from the map. If not, it creates a new state and stores it in the map.

Parameters
eNextState- The State enum to transition to.
bSaveCurrentState- Whether or not to save the current state so it can be recalled next time it is triggered. Default value is false.
Author
Eli Byrd (edbgk.nosp@m.k@ms.nosp@m.t.edu), clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-01-17
111{
112 // Acquire write lock for changing states.
113 std::unique_lock<std::shared_mutex> lkStateProcessLock(m_muStateMutex);
114
115 // Check if we are already in this state.
116 if (m_pCurrentState->GetState() != eNextState)
117 {
118 // Set atomic toggle saying we are in the process if switching states.
119 m_bSwitchingStates = true;
120
121 // Save the current state as the previous state
122 m_pPreviousState = m_pCurrentState;
123
124 // Check if we should save this current state so it can be recalled in the future.
125 if (bSaveCurrentState)
126 {
127 // Save the current state before transitioning
129 }
130
131 // Check if the state exists in exitedStates
132 std::unordered_map<statemachine::States, std::shared_ptr<statemachine::State>>::iterator itState = m_umSavedStates.find(eNextState);
133 if (itState != m_umSavedStates.end())
134 {
135 // Load the existing state
136 m_pCurrentState = itState->second;
137 // Remove new current state state from saved states.
138 m_umSavedStates.erase(eNextState);
139
140 // Submit logger message.
141 LOG_INFO(logging::g_qSharedLogger, "Recalling State: {}", m_pCurrentState->ToString());
142 }
143 else
144 {
145 // Create and enter a new state
146 m_pCurrentState = CreateState(eNextState);
147 }
148
149 // Set atomic toggle saying we are done switching states.
150 m_bSwitchingStates = false;
151 }
152}
std::shared_ptr< statemachine::State > CreateState(statemachine::States eState)
Create a State object based of of the State enum.
Definition StateMachineHandler.cpp:74
void SaveCurrentState()
Save the current state to the map of exited states. This is used to store the state when the state ma...
Definition StateMachineHandler.cpp:163
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SaveCurrentState()

void StateMachineHandler::SaveCurrentState ( )
private

Save the current state to the map of exited states. This is used to store the state when the state machine is transitioning to a new state. And prevents the state from being deleted when the state machine transitions to a new state.

Author
Eli Byrd (edbgk.nosp@m.k@ms.nosp@m.t.edu)
Date
2024-01-17
164{
165 // Submit logger message.
166 LOG_INFO(logging::g_qSharedLogger, "Saving State: {}", m_pCurrentState->ToString());
167 // Add state to map.
168 m_umSavedStates[m_pCurrentState->GetState()] = m_pCurrentState;
169}
Here is the caller graph for this function:

◆ ThreadedContinuousCode()

void StateMachineHandler::ThreadedContinuousCode ( )
overrideprivatevirtual

This code will run continuously in a separate thread. The State Machine Handler will check the current state and run the state's logic. It will then check the state's transition conditions and transition to the next state if the conditions are met.

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

Implements AutonomyThread< void >.

228{
229 /*
230 Verify that the state machine has been initialized so that it doesn't
231 try to run before a state has been initialized. Also verify that the
232 state machine is not currently switching states. This prevents the
233 state machine from running while it is in the middle of switching
234 states. And verify that the state machine is not exiting. This prevents
235 the state machine from running after it has been stopped.
236 */
237 if (!m_bSwitchingStates)
238 {
239 // Run the current state
240 m_pCurrentState->Run();
241 }
242
243 // Create instance variable.
244 static geoops::GPSCoordinate stNewGPSLocation;
245 // Check if GPS data is recent and updated.
246 if (std::chrono::duration_cast<std::chrono::milliseconds>(globals::g_pNavigationBoard->GetGPSLastUpdateTime()).count() <= 100 ||
247 (stNewGPSLocation.dLatitude == 0.0 && stNewGPSLocation.dLongitude == 0.0))
248 {
249 // Get the current NavBoard GPS data.
250 stNewGPSLocation = globals::g_pNavigationBoard->GetGPSData();
251 }
252
253 // Create static boolean value for toggling DiffGPS warning log print.
254 static bool bAlreadyPrintedDiffGPSWarning = false;
255 // Check if the current GPS data is different from the old.
256 if (stNewGPSLocation.dLatitude != m_stCurrentGPSLocation.dLatitude && stNewGPSLocation.dLongitude != m_stCurrentGPSLocation.dLongitude &&
257 stNewGPSLocation.dAltitude != m_stCurrentGPSLocation.dAltitude)
258 {
259 // Check GNSS Fusion is enabled and the main ZED camera is a fusion master.
260 if (constants::FUSION_ENABLE_GNSS_FUSION && stNewGPSLocation.bIsDifferential)
261 {
262 // Check if main ZED camera is setup to use GPS fusion.
263 if (m_pMainCam->GetIsFusionMaster() && m_pMainCam->GetPositionalTrackingEnabled())
264 {
265 // Update current GPS position.
266 m_stCurrentGPSLocation = stNewGPSLocation;
267 // Feed current GPS location to main ZED camera.
268 m_pMainCam->IngestGPSDataToFusion(m_stCurrentGPSLocation);
269 }
270
271 // Reset DiffGPS warning print toggle.
272 if (bAlreadyPrintedDiffGPSWarning)
273 {
274 // Submit logger message.
275 LOG_NOTICE(logging::g_qSharedLogger,
276 "Incoming GPS position to NavBoard now has differential accuracy! Autonomy will switch to using GPS Fusion for high accuracy navigation!");
277
278 // Rest toggle.
279 bAlreadyPrintedDiffGPSWarning = false;
280 }
281 }
282 // Check if GPS coordinate from NavBoard is not differential and print warning log.
283 else if (!bAlreadyPrintedDiffGPSWarning)
284 {
285 // Submit logger message.
286 LOG_NOTICE(logging::g_qSharedLogger,
287 "Incoming GPS position to NavBoard does not have differential accuracy! Autonomy will not use GPS Fusion but instead fallback to aligning "
288 "the ZED pose while the rover is in Idle state and not moving. Autonomous navigation performance of the rover will be degraded...");
289
290 // Set already printed toggle.
291 bAlreadyPrintedDiffGPSWarning = true;
292 }
293
294 // Realign the camera's relative position to current GPS position when in Idle. This does not affect fusion, but makes sure we can fallback to the camera pose for
295 // positioning.
296 if (m_pCurrentState->GetState() == statemachine::States::eIdle && m_pMainCam->GetPositionalTrackingEnabled())
297 {
298 // Check if the rover is currently not driving of turning. Use only GPS based and use stuck state parameters for checking.
299 if (globals::g_pNavigationBoard->GetVelocity() <= constants::STUCK_CHECK_VEL_THRESH &&
300 globals::g_pNavigationBoard->GetAngularVelocity() <= constants::STUCK_CHECK_ROT_THRESH)
301 {
302 // Update current GPS position.
303 m_stCurrentGPSLocation = stNewGPSLocation;
304 // Get current compass heading.
305 double dCurrentCompassHeading = globals::g_pNavigationBoard->GetHeading();
306 // Realign the main ZED cameras pose with current GPS-based position and heading.
307 this->RealignZEDPosition(CameraHandler::ZEDCamName::eHeadMainCam, geoops::ConvertGPSToUTM(m_stCurrentGPSLocation), dCurrentCompassHeading);
308 }
309 }
310 }
311}
double GetHeading()
Accessor for the most recent compass heading received from the NavBoard.
Definition NavigationBoard.cpp:161
geoops::GPSCoordinate GetGPSData()
Accessor for most recent GPS data received from NavBoard.
Definition NavigationBoard.cpp:78
void RealignZEDPosition(CameraHandler::ZEDCamName eCameraName, const geoops::UTMCoordinate &stNewCameraPosition, const double dNewCameraHeading)
This is used to realign the ZEDs forward direction with the rover's current compass heading....
Definition StateMachineHandler.cpp:427
virtual bool GetIsFusionMaster() const
Accessor for if this ZED is running a fusion instance.
Definition ZEDCamera.hpp:528
virtual sl::FUSION_ERROR_CODE IngestGPSDataToFusion(geoops::GPSCoordinate stNewGPSLocation)
Ingests GPS data into the fusion object.
Definition ZEDCamera.hpp:392
virtual bool GetPositionalTrackingEnabled()=0
Accessor for the Positional Tracking Enabled private member.
UTMCoordinate ConvertGPSToUTM(const GPSCoordinate &stGPSCoord)
Given a GPS coordinate, convert to UTM and create a new UTMCoordinate object.
Definition GeospatialOperations.hpp:351
This struct stores/contains information about a GPS data.
Definition GeospatialOperations.hpp:148
Here is the call graph for this function:

◆ PooledLinearCode()

void StateMachineHandler::PooledLinearCode ( )
overrideprivatevirtual

This method holds the code that is ran in the thread pool started by the ThreadedLinearCode() method. It currently does nothing and is not needed in the current implementation of the StateMachineHandler.

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

Implements AutonomyThread< void >.

321{}

◆ StartStateMachine()

void StateMachineHandler::StartStateMachine ( )

This method will start the state machine. It will set the first state to Idle and start the thread pool.

Author
Eli Byrd (edbgk.nosp@m.k@ms.nosp@m.t.edu)
Date
2024-01-17
179{
180 // Initialize the state machine with the initial state
181 m_pCurrentState = CreateState(statemachine::States::eIdle);
182 m_bSwitchingStates = false;
183
184 // Start the state machine thread
185 Start();
186
187 // Submit logger message.
188 LOG_INFO(logging::g_qSharedLogger, "Started State Machine.");
189}
void Start()
When this method is called, it starts a new thread that runs the code within the ThreadedContinuousCo...
Definition AutonomyThread.hpp:117
Here is the call graph for this function:
Here is the caller graph for this function:

◆ StopStateMachine()

void StateMachineHandler::StopStateMachine ( )

This method will stop the state machine. It will signal whatever state is currently running to abort back to idle and then stop the main code running in the ThreadedContinuousCode() method.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-01-19
201{
202 // No matter the current state, abort back to idle.
203 this->HandleEvent(statemachine::Event::eAbort);
204
205 // Stop main thread.
206 this->RequestStop();
207 this->Join();
208
209 // Send multimedia command to update state display.
210 globals::g_pMultimediaBoard->SendLightingState(MultimediaBoard::MultimediaBoardLightingState::eOff);
211 // Stop drive.
212 globals::g_pDriveBoard->SendStop();
213
214 // Submit logger message.
215 LOG_INFO(logging::g_qSharedLogger, "Stopped State Machine.");
216}
void Join()
Waits for thread to finish executing and then closes thread. This method will block the calling code ...
Definition AutonomyThread.hpp:180
void RequestStop()
Signals threads to stop executing user code, terminate. DOES NOT JOIN. This method will not force the...
Definition AutonomyThread.hpp:164
void SendStop()
Stop the drivetrain of the Rover.
Definition DriveBoard.cpp:162
void SendLightingState(MultimediaBoardLightingState eState)
Sends a predetermined color pattern to board.
Definition MultimediaBoard.cpp:55
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:337
Here is the call graph for this function:
Here is the caller graph for this function:

◆ HandleEvent()

void StateMachineHandler::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 state and run the state's HandleEvent() method. It will then check the state's transition conditions and transition to the next state if the conditions are met.

Parameters
eEvent- The Event enum to handle.
bSaveCurrentState- Whether or not to save the current state so it can be recalled next time it is triggered. Default value is false.
Author
Eli Byrd (edbgk.nosp@m.k@ms.nosp@m.t.edu)
Date
2024-01-17
338{
339 // Acquire write lock for handling events.
340 std::unique_lock<std::shared_mutex> lkEventProcessLock(m_muEventMutex);
341
342 // Check if the current state is not null and the state machine is running.
343 if (m_pCurrentState != nullptr && this->GetThreadState() == AutonomyThreadState::eRunning)
344 {
345 // Trigger the event on the current state
346 statemachine::States eNextState = m_pCurrentState->TriggerEvent(eEvent);
347
348 // Transition to the next state
349 ChangeState(eNextState, bSaveCurrentState);
350 }
351}
void ChangeState(statemachine::States eNextState, const bool bSaveCurrentState=false)
Transition to a new state. This function is called by the HandleEvent and checks to see if this state...
Definition StateMachineHandler.cpp:110
States
The states that the state machine can be in.
Definition State.hpp:31
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ClearSavedStates()

void StateMachineHandler::ClearSavedStates ( )

Clear all saved states.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-04-01
361{
362 // Acquire write lock for clearing saved states.
363 std::unique_lock<std::shared_mutex> lkStateProcessLock(m_muStateMutex);
364 // Clear all saved states.
365 m_umSavedStates.clear();
366 // Reset previous state to nullptr;
367 m_pPreviousState = std::make_shared<statemachine::IdleState>();
368}
Here is the caller graph for this function:

◆ ClearSavedState()

void StateMachineHandler::ClearSavedState ( statemachine::States  eState)

Clear a saved state based on the given state.

Parameters
eState- The state to clear from the saved states.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2025-01-06
379{
380 // Acquire write lock for clearing saved states.
381 std::unique_lock<std::shared_mutex> lkStateProcessLock(m_muStateMutex);
382 // Remove all states that match the given state.
383 m_umSavedStates.erase(eState);
384}
Here is the caller graph for this function:

◆ GetCurrentState()

statemachine::States StateMachineHandler::GetCurrentState ( ) const

Accessor for the Current State private member.

Returns
States - The current state of the state machine.
Author
Eli Byrd (edbgk.nosp@m.k@ms.nosp@m.t.edu)
Date
2024-01-17
395{
396 return m_pCurrentState->GetState();
397}

◆ GetPreviousState()

statemachine::States StateMachineHandler::GetPreviousState ( ) const

Accessor for the Previous State private member.

Returns
States - The previous state of the state machine.
Author
Eli Byrd (edbgk.nosp@m.k@ms.nosp@m.t.edu)
Date
2024-01-17
408{
409 // Check if the previous state exists and return it if it does otherwise return Idle
410 return m_pPreviousState ? m_pPreviousState->GetState() : statemachine::States::eIdle;
411}
Here is the caller graph for this function:

◆ RealignZEDPosition()

void StateMachineHandler::RealignZEDPosition ( CameraHandler::ZEDCamName  eCameraName,
const geoops::UTMCoordinate stNewCameraPosition,
const double  dNewCameraHeading 
)

This is used to realign the ZEDs forward direction with the rover's current compass heading. Realigning GPS latlon is not necessary since we're using the ZEDSDK's Fusion module. The heading of the camera's GeoPose is actually automatically realigned too depending on what direction We are headed, but this is just to be safe.

Parameters
eCameraName- The camera name represented as an enum from the CameraHandler class.
stNewCameraPosition- The new UTM position of the ZED camera.
dNewCameraHeading- The new compass heading of the ZED camera.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-04-17
428{
429 // Get main ZEDCam.
430 ZEDCamera* pMainCam = globals::g_pCameraHandler->GetZED(eCameraName);
431
432 // Check if main ZEDCam is opened and positional tracking is enabled.
433 if (pMainCam->GetCameraIsOpen() && pMainCam->GetPositionalTrackingEnabled())
434 {
435 // Request for the cameras current pose.
436 ZEDCam::Pose stCurrentCameraPose;
437 std::future<bool> fuPoseReturnStatus = pMainCam->RequestPositionalPoseCopy(stCurrentCameraPose);
438 // Wait for pose to be copied.
439 if (fuPoseReturnStatus.get())
440 {
441 // Pack the current camera pose into UTM coordinate.
442 geoops::UTMCoordinate stCurrentCameraUTM = geoops::UTMCoordinate(stCurrentCameraPose.stTranslation.dX,
443 stCurrentCameraPose.stTranslation.dZ,
444 stNewCameraPosition.nZone,
445 stNewCameraPosition.bWithinNorthernHemisphere,
446 stCurrentCameraPose.stTranslation.dY);
447 // Calculate the distance between the current and new camera position.
448 geoops::GeoMeasurement stError = geoops::CalculateGeoMeasurement(stCurrentCameraUTM, stNewCameraPosition);
449
450 // Check if the camera's current pose is close to the new position.
451 if (stError.dDistanceMeters >= constants::STATEMACHINE_ZED_REALIGN_THRESHOLD)
452 {
453 // Update camera Y heading with GPSs current heading.
454 pMainCam->SetPositionalPose(stNewCameraPosition.dEasting,
455 stNewCameraPosition.dAltitude,
456 stNewCameraPosition.dNorthing,
457 stCurrentCameraPose.stEulerAngles.dXO,
458 dNewCameraHeading,
459 stCurrentCameraPose.stEulerAngles.dZO);
460
461 // Submit logger message.
462 LOG_INFO(logging::g_qSharedLogger, "Realigned ZED stereo camera to current GPS position. Error was: {} meters.", stError.dDistanceMeters);
463 }
464 }
465 else
466 {
467 // Submit logger message.
468 LOG_ERROR(logging::g_qSharedLogger, "Failed to realign the ZEDCam's pose with the given UTM position and compass heading.");
469 }
470 }
471 else
472 {
473 // Submit logger message.
474 LOG_ERROR(logging::g_qSharedLogger,
475 "Failed to realign the ZEDCam's pose with the given UTM position and compass heading. The camera is not open yet or positional tracking status is "
476 "suboptimal!");
477 }
478}
virtual bool GetCameraIsOpen()=0
Accessor for the Camera Is Open private member.
This class serves as a middle inheritor between the Camera interface and the ZEDCam class....
Definition ZEDCamera.hpp:33
virtual void SetPositionalPose(const double dX, const double dY, const double dZ, const double dXO, const double dYO, const double dZO)=0
Mutator for the Positional Pose private member.
virtual std::future< bool > RequestPositionalPoseCopy(Pose &stPose)=0
Puts a Pose pointer into a queue so a copy of a Pose from the camera can be written to it.
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:445
This struct is used within the ZEDCam class to store the camera pose with high precision....
Definition ZEDCamera.hpp:97
This struct is used to store the distance, arc length, and relative bearing for a calculated geodesic...
Definition GeospatialOperations.hpp:82
This struct stores/contains information about a UTM coordinate.
Definition GeospatialOperations.hpp:244
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetIPS()

IPS & AutonomyThread< T >::GetIPS ( )
inline

Accessor for the Frame I P S private member.

Returns
IPS& - The iteration per second counter for the ThreadedContinuousCode()
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-08-20
224{ return m_IPS; }

Member Data Documentation

◆ AutonomyStartCallback

const std::function<void(const rovecomm::RoveCommPacket<uint8_t>&, const sockaddr_in&)> StateMachineHandler::AutonomyStartCallback
private
Initial value:
=
[this](const rovecomm::RoveCommPacket<uint8_t>& stPacket, const sockaddr_in& stdAddr)
{
(void) stPacket;
(void) stdAddr;
LOG_INFO(logging::g_qSharedLogger, "Incoming Packet: Start Autonomy!");
this->HandleEvent(statemachine::Event::eStart);
}

Callback function used to trigger the start of autonomy. No matter what state we are in, signal a StartAutonomy Event.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-03-15
79 {
80 // Not using this.
81 (void) stPacket;
82 (void) stdAddr;
83
84 // Submit logger message.
85 LOG_INFO(logging::g_qSharedLogger, "Incoming Packet: Start Autonomy!");
86
87 // Signal statemachine handler with Start event.
88 this->HandleEvent(statemachine::Event::eStart);
89 };

◆ AutonomyStopCallback

const std::function<void(const rovecomm::RoveCommPacket<uint8_t>&, const sockaddr_in&)> StateMachineHandler::AutonomyStopCallback
private
Initial value:
=
[this](const rovecomm::RoveCommPacket<uint8_t>& stPacket, const sockaddr_in& stdAddr)
{
(void) stPacket;
(void) stdAddr;
LOG_INFO(logging::g_qSharedLogger, "Incoming Packet: Abort Autonomy!");
this->HandleEvent(statemachine::Event::eAbort, true);
}

Callback function used to trigger autonomy to stop. No matter what state we are in, signal an Abort Event.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-03-15
101 {
102 // Not using this.
103 (void) stPacket;
104 (void) stdAddr;
105
106 // Submit logger message.
107 LOG_INFO(logging::g_qSharedLogger, "Incoming Packet: Abort Autonomy!");
108
109 // Signal statemachine handler with stop event.
110 this->HandleEvent(statemachine::Event::eAbort, true);
111 };

◆ PMSCellVoltageCallback

const std::function<void(const rovecomm::RoveCommPacket<float>&, const sockaddr_in&)> StateMachineHandler::PMSCellVoltageCallback
private

Callback function used to force autonomy into Idle state if battery voltage gets too low. No matter what state we are in, signal an Abort Event.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-04-04
123 {
124 // Not using this.
125 (void) stdAddr;
126
127 // Create instance variables.
128 double dTotalCellVoltages = 0.0;
129 int nValidCellVoltageValues = 0;
130
131 // Loop through voltage values and average all of the valid ones.
132 for (int nIter = 0; nIter < stPacket.unDataCount; ++nIter)
133 {
134 // Check if the voltage values is greater than at least 0.1.
135 if (stPacket.vData[nIter] >= 0.1)
136 {
137 // Add cell voltage value to total.
138 dTotalCellVoltages += stPacket.vData[nIter];
139 // Increment voltage voltage counter.
140 ++nValidCellVoltageValues;
141 }
142 }
143 // Calculate average cell voltage.
144 double dAverageCellVoltage = dTotalCellVoltages / nValidCellVoltageValues;
145
146 // Submit logger message.
147 LOG_DEBUG(logging::g_qSharedLogger, "Incoming Packet: PMS Cell Voltages. Average voltage is: {}", dAverageCellVoltage);
148
149 // Check if voltage is above the safe minimum for lithium ion batteries.
150 if (constants::BATTERY_CHECKS_ENABLED && dAverageCellVoltage < constants::BATTERY_MINIMUM_CELL_VOLTAGE &&
151 this->GetCurrentState() != statemachine::States::eIdle)
152 {
153 // Submit logger message.
154 LOG_CRITICAL(logging::g_qSharedLogger,
155 "Incoming PMS Packet: Average cell voltage is {} which is below the safe minimum of {}. Entering Idle state...",
156 dAverageCellVoltage,
157 constants::BATTERY_MINIMUM_CELL_VOLTAGE);
158
159 // Signal statemachine handler with stop event.
160 this->HandleEvent(statemachine::Event::eAbort, true);
161 }
162 };
statemachine::States GetCurrentState() const
Accessor for the Current State private member.
Definition StateMachineHandler.cpp:394

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