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.
 
geoops::RoverPose SmartRetrieveRoverPose (bool bIMUHeading=true)
 This method is used to retrieve the rover's current position and heading. It uses the GPS data from the NavBoard and if enabled, it can also fuse the ZEDCam's IMU heading data for a more accurate heading estimation. The method returns a RoverPose struct that contains the current GPS coordinate and the fused heading of the rover.
 
double SmartRetrieveVelocity ()
 Retrieve the rover's current velocity. Currently there is no easy way to get the velocity of the ZEDCam so this method just returns the GPS-based velocity.
 
double SmartRetrieveAngularVelocity ()
 Retrieve the rover's current velocity. Currently there is no easy way to get the velocity of the ZEDCam so this method just returns the GPS-based velocity.
 
void RealignZEDHeading (const double dNewActualHeading, const double dCurrentZEDHeading)
 This method is used to realign the ZED camera's heading with the actual heading of the rover. This method calculates the difference between the ZED's heading and the actual heading of the rover and applies that difference as an offset to the ZED's heading.
 
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.
 
std::string GetThreadUUID () const
 Accessor for the Thread U U I D private member.
 
IPSGetIPS ()
 Accessor for the Frame I P S private member.
 
void SetMainThreadPriority (AutonomyThreadPriority ePriority)
 Set the OS priority for the main continuous thread.
 
void SetPoolThreadPriority (AutonomyThreadPriority ePriority)
 Set the OS priority for the highly parallelized pool threads.
 
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
 
std::shared_ptr< ZEDCameram_pMainCam
 
std::shared_ptr< ZEDCameram_pRearCam
 
geoops::GPSCoordinate m_stCurrentGPSLocation
 
double m_dZEDHeadingOffset
 
double m_dLastRawZEDHeading
 
double m_dLastFusedHeading
 
bool m_bFirstHeadingLoop
 
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< uint8_t > &, const sockaddr_in &)> ClearWaypointsCallback
 Callback function that is called whenever RoveComm receives new CLEARWAYPOINTS packet.
 
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
 
enum  AutonomyThreadPriority
 

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<uint8_t>(ClearWaypointsCallback, manifest::Autonomy::COMMANDS.find("CLEARWAYPOINTS")->second.DATA_ID);
40 network::g_pRoveCommUDPNode->AddUDPCallback<float>(PMSCellVoltageCallback, manifest::PMS::TELEMETRY.find("CELLVOLTAGE")->second.DATA_ID);
41
42 // Initialize member variables.
43 m_pMainCam = globals::g_pCameraHandler->GetZED(CameraHandler::ZEDCamName::eHeadMainCam);
44 m_pRearCam = globals::g_pCameraHandler->GetZED(CameraHandler::ZEDCamName::eRearCam);
45 m_dZEDHeadingOffset = 0.0;
46 m_dLastRawZEDHeading = 0.0;
47 m_dLastFusedHeading = 0.0;
48 m_bFirstHeadingLoop = true;
49
50 // State machine doesn't need to run at an unlimited speed. Cap main thread to a certain amount of iterations per second.
51 this->SetMainThreadIPSLimit(constants::STATEMACHINE_MAX_IPS);
52}
void SetMainThreadIPSLimit(int nMaxIterationsPerSecond=0)
Mutator for the Main Thread Max I P S private member.
Definition AutonomyThread.hpp:530
std::shared_ptr< ZEDCamera > GetZED(ZEDCamName eCameraName)
Accessor for ZED cameras.
Definition CameraHandler.cpp:215
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:82
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:163
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:104
const std::function< void(const rovecomm::RoveCommPacket< uint8_t > &, const sockaddr_in &)> ClearWaypointsCallback
Callback function that is called whenever RoveComm receives new CLEARWAYPOINTS packet.
Definition StateMachineHandler.h:125
::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
62{
63 // Check if state machine is running.
64 if (this->GetThreadState() == AutonomyThreadState::eRunning)
65 {
66 // Stop state machine.
67 this->StopStateMachine();
68 }
69}
AutonomyThreadState GetThreadState() const
Accessor for the Threads State private member.
Definition AutonomyThread.hpp:237
void StopStateMachine()
This method will stop the state machine. It will signal whatever state is currently running to abort ...
Definition StateMachineHandler.cpp:217
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
81{
82 switch (eState)
83 {
84 case statemachine::States::eIdle: return std::make_shared<statemachine::IdleState>();
85 case statemachine::States::eNavigating: return std::make_shared<statemachine::NavigatingState>();
86 case statemachine::States::eSearchPattern: return std::make_shared<statemachine::SearchPatternState>();
87 case statemachine::States::eApproachingMarker: return std::make_shared<statemachine::ApproachingMarkerState>();
88 case statemachine::States::eApproachingObject: return std::make_shared<statemachine::ApproachingObjectState>();
89 case statemachine::States::eVerifyingPosition: return std::make_shared<statemachine::VerifyingPositionState>();
90 case statemachine::States::eVerifyingMarker: return std::make_shared<statemachine::VerifyingMarkerState>();
91 case statemachine::States::eVerifyingObject: return std::make_shared<statemachine::VerifyingObjectState>();
92 case statemachine::States::eReversing: return std::make_shared<statemachine::ReversingState>();
93 case statemachine::States::eStuck: return std::make_shared<statemachine::StuckState>();
94 default:
95 // Handle the default case or throw an exception if needed
96 LOG_ERROR(logging::g_qSharedLogger, "State {} not found.", static_cast<int>(eState));
97 }
98
99 return nullptr;
100}
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
116{
117 // Acquire write lock for changing states.
118 std::unique_lock<std::shared_mutex> lkStateProcessLock(m_muStateMutex);
119
120 // Check if we are already in this state.
121 if (m_pCurrentState->GetState() != eNextState)
122 {
123 // Set atomic toggle saying we are in the process if switching states.
124 m_bSwitchingStates = true;
125
126 // Save the current state as the previous state
127 m_pPreviousState = m_pCurrentState;
128
129 // Check if we should save this current state so it can be recalled in the future.
130 if (bSaveCurrentState)
131 {
132 // Save the current state before transitioning
134 }
135
136 // Check if the state exists in exitedStates
137 std::unordered_map<statemachine::States, std::shared_ptr<statemachine::State>>::iterator itState = m_umSavedStates.find(eNextState);
138 if (itState != m_umSavedStates.end())
139 {
140 // Load the existing state
141 m_pCurrentState = itState->second;
142 // Remove new current state state from saved states.
143 m_umSavedStates.erase(eNextState);
144
145 // Submit logger message.
146 LOG_INFO(logging::g_qSharedLogger, "Recalling State: {}", m_pCurrentState->ToString());
147 }
148 else
149 {
150 // Create and enter a new state
151 m_pCurrentState = CreateState(eNextState);
152 }
153
154 // Set atomic toggle saying we are done switching states.
155 m_bSwitchingStates = false;
156 }
157
158 // Send current robot state over RoveComm.
159 rovecomm::RoveCommPacket<uint8_t> stPacket;
160 stPacket.unDataId = manifest::Autonomy::TELEMETRY.find("CURRENTSTATE")->second.DATA_ID;
161 stPacket.unDataCount = manifest::Autonomy::TELEMETRY.find("CURRENTSTATE")->second.DATA_COUNT;
162 stPacket.eDataType = manifest::Autonomy::TELEMETRY.find("CURRENTSTATE")->second.DATA_TYPE;
163 stPacket.vData.emplace_back(static_cast<uint8_t>(this->GetCurrentState()));
164 // Send drive command over RoveComm to drive board to all subscribers.
165 network::g_pRoveCommUDPNode->SendUDPPacket(stPacket, "0.0.0.0", constants::ROVECOMM_OUTGOING_UDP_PORT);
166}
statemachine::States GetCurrentState() const
Accessor for the Current State private member.
Definition StateMachineHandler.cpp:345
std::shared_ptr< statemachine::State > CreateState(statemachine::States eState)
Create a State object based of of the State enum.
Definition StateMachineHandler.cpp:80
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:177
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
178{
179 // Submit logger message.
180 LOG_INFO(logging::g_qSharedLogger, "Saving State: {}", m_pCurrentState->ToString());
181 // Add state to map.
182 m_umSavedStates[m_pCurrentState->GetState()] = m_pCurrentState;
183}
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 >.

245{
246 /*
247 Verify that the state machine has been initialized so that it doesn't
248 try to run before a state has been initialized. Also verify that the
249 state machine is not currently switching states. This prevents the
250 state machine from running while it is in the middle of switching
251 states. And verify that the state machine is not exiting. This prevents
252 the state machine from running after it has been stopped.
253 */
254 if (!m_bSwitchingStates)
255 {
256 // Run the current state
257 m_pCurrentState->Run();
258 }
259}

◆ 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 >.

269{}

◆ 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
193{
194 // Initialize the state machine with the initial state
195 m_pCurrentState = CreateState(statemachine::States::eIdle);
196 m_bSwitchingStates = false;
197
198 // Clear any saved states.
199 this->ClearSavedStates();
200
201 // Start the state machine thread
202 Start();
203
204 // Submit logger message.
205 LOG_INFO(logging::g_qSharedLogger, "Started State Machine.");
206}
void Start()
When this method is called, it starts a new thread that runs the code within the ThreadedContinuousCo...
Definition AutonomyThread.hpp:134
void ClearSavedStates()
Clear all saved states.
Definition StateMachineHandler.cpp:311
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
218{
219 // No matter the current state, abort back to idle.
220 this->HandleEvent(statemachine::Event::eAbort);
221
222 // Stop main thread.
223 this->RequestStop();
224 this->Join();
225
226 // Send multimedia command to update state display.
227 globals::g_pMultimediaBoard->SendLightingState(MultimediaBoard::MultimediaBoardLightingState::eOff);
228 // Stop drive.
229 globals::g_pDriveBoard->SendStop();
230
231 // Submit logger message.
232 LOG_INFO(logging::g_qSharedLogger, "Stopped State Machine.");
233}
void Join()
Waits for thread to finish executing and then closes thread. This method will block the calling code ...
Definition AutonomyThread.hpp:203
void RequestStop()
Signals threads to stop executing user code, terminate. DOES NOT JOIN. This method will not force the...
Definition AutonomyThread.hpp:187
void SendStop()
Stop the drivetrain of the Rover.
Definition DriveBoard.cpp:246
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:285
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
286{
287 // Acquire write lock for handling events.
288 std::unique_lock<std::shared_mutex> lkEventProcessLock(m_muEventMutex);
289
290 // Stop the drive.
291 globals::g_pDriveBoard->SendStop();
292
293 // Check if the current state is not null and the state machine is running.
294 if (m_pCurrentState != nullptr && this->GetThreadState() == AutonomyThreadState::eRunning)
295 {
296 // Trigger the event on the current state
297 statemachine::States eNextState = m_pCurrentState->TriggerEvent(eEvent);
298
299 // Transition to the next state
300 ChangeState(eNextState, bSaveCurrentState);
301 }
302}
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:115
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
312{
313 // Acquire write lock for clearing saved states.
314 std::unique_lock<std::shared_mutex> lkStateProcessLock(m_muStateMutex);
315 // Clear all saved states.
316 m_umSavedStates.clear();
317 // Reset previous state to nullptr;
318 m_pPreviousState = std::make_shared<statemachine::IdleState>();
319}
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
330{
331 // Acquire write lock for clearing saved states.
332 std::unique_lock<std::shared_mutex> lkStateProcessLock(m_muStateMutex);
333 // Remove all states that match the given state.
334 m_umSavedStates.erase(eState);
335}

◆ 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
346{
347 return m_pCurrentState->GetState();
348}
Here is the caller graph for this function:

◆ 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
359{
360 // Check if the previous state exists and return it if it does otherwise return Idle
361 return m_pPreviousState ? m_pPreviousState->GetState() : statemachine::States::eIdle;
362}
Here is the caller graph for this function:

◆ SmartRetrieveRoverPose()

geoops::RoverPose StateMachineHandler::SmartRetrieveRoverPose ( bool  bIMUHeading = true)

This method is used to retrieve the rover's current position and heading. It uses the GPS data from the NavBoard and if enabled, it can also fuse the ZEDCam's IMU heading data for a more accurate heading estimation. The method returns a RoverPose struct that contains the current GPS coordinate and the fused heading of the rover.

Parameters
bIMUHeading- Whether to use IMU Heading.
Returns
geoops::RoverPose - The current position and heading (pose) of the rover stored in a RoverPose struct.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-04-06
376{
377 // Get and store the normal GPS position and heading from NavBoard.
378 geoops::GPSCoordinate stCurrentGPSPosition = globals::g_pNavigationBoard->GetGPSData();
379 double dCurrentGPSHeading = globals::g_pNavigationBoard->GetHeading();
380
381 // Create instance variables.
382 double dFusedHeading = dCurrentGPSHeading;
383
384 if ((bIMUHeading) && !constants::MODE_SIM && m_pMainCam->GetCameraIsOpen())
385 {
386 // DYNAMIC REALIGNMENT. (Drift/Lag correction using GPS)
387 double dVelocity = this->SmartRetrieveVelocity();
388 double dAngularVel = this->SmartRetrieveAngularVelocity();
389
390 // Request the current heading from the ZED camera.
391 sl::SensorsData slCurrentCameraSensorData;
392 std::future<bool> fuResultStatus = m_pMainCam->RequestSensorsCopy(slCurrentCameraSensorData);
393 // Wait for future to be fulfilled.
394 if (fuResultStatus.get())
395 {
396 // Get Degrees heading from ZED IMU data.
397 double dCurrentZEDHeading = slCurrentCameraSensorData.imu.pose.getEulerAngles(false).y;
398 // Realign offset.
399 // If driving forward fast enough (> Xm/s) and NOT turning. (angular vel near 0)
400 if ((m_pCurrentState != nullptr && m_pCurrentState->GetState() == statemachine::States::eIdle) ||
401 (std::abs(dVelocity) > constants::ZED_REALIGN_VEL_THRESH && std::abs(dAngularVel) < constants::ZED_REALIGN_ROT_THRESH))
402 {
403 this->RealignZEDHeading(dCurrentGPSHeading, dCurrentZEDHeading);
404 }
405
406 // Update fused heading.
407 dFusedHeading = numops::InputAngleModulus(dCurrentZEDHeading + m_dZEDHeadingOffset, 0.0, 360.0);
408 }
409 }
410
411 // Submit a debug print for the current rover pose.
412 geoops::UTMCoordinate stCurrentUTMPosition = geoops::ConvertGPSToUTM(stCurrentGPSPosition);
413 LOG_DEBUG(logging::g_qSharedLogger,
414 "Rover Pose is currently: {} (easting), {} (northing), {} (alt), {} (degrees), IMUHeading = {}",
415 stCurrentUTMPosition.dEasting,
416 stCurrentUTMPosition.dNorthing,
417 stCurrentUTMPosition.dAltitude,
418 dFusedHeading,
419 bIMUHeading ? "true" : "false");
420
421 return geoops::RoverPose(stCurrentGPSPosition, dFusedHeading);
422}
double GetHeading()
Accessor for the most recent compass heading received from the NavBoard.
Definition NavigationBoard.cpp:182
geoops::GPSCoordinate GetGPSData()
Accessor for most recent GPS data received from NavBoard.
Definition NavigationBoard.cpp:78
void RealignZEDHeading(const double dNewActualHeading, const double dCurrentZEDHeading)
This method is used to realign the ZED camera's heading with the actual heading of the rover....
Definition StateMachineHandler.cpp:467
double SmartRetrieveAngularVelocity()
Retrieve the rover's current velocity. Currently there is no easy way to get the velocity of the ZEDC...
Definition StateMachineHandler.cpp:450
double SmartRetrieveVelocity()
Retrieve the rover's current velocity. Currently there is no easy way to get the velocity of the ZEDC...
Definition StateMachineHandler.cpp:434
UTMCoordinate ConvertGPSToUTM(const GPSCoordinate &stGPSCoord)
Given a GPS coordinate, convert to UTM and create a new UTMCoordinate object.
Definition GeospatialOperations.hpp:333
constexpr T InputAngleModulus(T tValue, T tMinValue, T tMaxValue)
Calculates the modulus of an input angle.
Definition NumberOperations.hpp:162
This struct stores/contains information about a GPS data.
Definition GeospatialOperations.hpp:100
This struct is used by the WaypointHandler to provide an easy way to store all pose data about the ro...
Definition GeospatialOperations.hpp:708
This struct stores/contains information about a UTM coordinate.
Definition GeospatialOperations.hpp:211
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SmartRetrieveVelocity()

double StateMachineHandler::SmartRetrieveVelocity ( )

Retrieve the rover's current velocity. Currently there is no easy way to get the velocity of the ZEDCam so this method just returns the GPS-based velocity.

Returns
double - The current velocity of the rover. (m/s)
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-04-06
435{
436 // Return the GPS-based velocity from the NavBoard.
437 return globals::g_pNavigationBoard->GetVelocity();
438}
double GetVelocity()
The rover's current velocity based off of the distance covered over the last two GPSCoordinates.
Definition NavigationBoard.cpp:265
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SmartRetrieveAngularVelocity()

double StateMachineHandler::SmartRetrieveAngularVelocity ( )

Retrieve the rover's current velocity. Currently there is no easy way to get the velocity of the ZEDCam so this method just returns the GPS-based velocity.

Returns
double - The current angular velocity of the rover. (deg/s)
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-04-06
451{
452 // Return the GPS-based angular velocity from the NavBoard.
453 return globals::g_pNavigationBoard->GetAngularVelocity();
454}
double GetAngularVelocity()
The rover's current angular velocity based off of the change in angle over the last two headings.
Definition NavigationBoard.cpp:307
Here is the call graph for this function:
Here is the caller graph for this function:

◆ RealignZEDHeading()

void StateMachineHandler::RealignZEDHeading ( const double  dNewActualHeading,
const double  dCurrentZEDHeading 
)

This method is used to realign the ZED camera's heading with the actual heading of the rover. This method calculates the difference between the ZED's heading and the actual heading of the rover and applies that difference as an offset to the ZED's heading.

Parameters
dNewActualHeading- The new actual heading of the rover that the ZED's heading should be aligned to.
dCurrentZEDHeading- The current heading of the zed.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-04-17
468{
469 // Convert -180/180 to 0/360 Standard. (Keep 0 as 0)
470 // If ZED is -90 (West), this makes it 270.
471 double dCurrentHeading = dCurrentZEDHeading;
472 if (dCurrentHeading < 0)
473 {
474 dCurrentHeading += 360.0;
475 }
476
477 // Calculate the difference required to turn Raw ZED into Actual Heading.
478 // Logic: Actual = Raw + Offset => Offset = Actual - Raw
479 double dOffset = dNewActualHeading - dCurrentHeading;
480
481 // Wrap the offset to 0-360 positive range
482 dOffset = numops::InputAngleModulus(dOffset, 0.0, 360.0);
483
484 // Normalize the signed offset to the range [-180, 180] so we report the smallest correction.
485 double dSignedOffset = numops::AngularDifference(m_dZEDHeadingOffset, dOffset);
486 // Only print a notice when the correction exceeds the configured significant threshold.
487 if (std::abs(dSignedOffset) >= constants::ZED_REALIGN_ROT_THRESH)
488 {
489 LOG_NOTICE(logging::g_qSharedLogger,
490 "Significant ZED heading correction detected. Raw ZED: {} deg, Target GPS: {} deg, Signed Offset: {} deg, New Offset: {} deg",
491 dCurrentHeading,
492 dNewActualHeading,
493 dSignedOffset,
494 m_dZEDHeadingOffset);
495 }
496
497 // Update zed offset.
498 m_dZEDHeadingOffset = dOffset;
499}
constexpr T AngularDifference(T tFirstValue, T tSecondValue)
Calculates the distance in degrees between two angles. This function accounts for wrap around so that...
Definition NumberOperations.hpp:201
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
257{ 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
84 {
85 // Not using this.
86 (void) stPacket;
87 (void) stdAddr;
88
89 // Submit logger message.
90 LOG_INFO(logging::g_qSharedLogger, "Incoming Packet: Start Autonomy!");
91
92 // Signal statemachine handler with Start event.
93 this->HandleEvent(statemachine::Event::eStart);
94 };

◆ 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
106 {
107 // Not using this.
108 (void) stPacket;
109 (void) stdAddr;
110
111 // Submit logger message.
112 LOG_INFO(logging::g_qSharedLogger, "Incoming Packet: Abort Autonomy!");
113
114 // Signal statemachine handler with stop event.
115 this->HandleEvent(statemachine::Event::eAbort, true);
116 };

◆ ClearWaypointsCallback

const std::function<void(const rovecomm::RoveCommPacket<uint8_t>&, const sockaddr_in&)> StateMachineHandler::ClearWaypointsCallback
private
Initial value:
=
[this](const rovecomm::RoveCommPacket<uint8_t>& stPacket, const sockaddr_in& stdAddr)
{
(void) stPacket;
(void) stdAddr;
if (this->GetCurrentState() == statemachine::States::eIdle)
{
LOG_NOTICE(logging::g_qSharedLogger, "Incoming Clear Waypoints packet: Deleting all saved states in StateMachineHandler...");
}
else
{
LOG_WARNING(logging::g_qSharedLogger,
"Incoming Clear Waypoints packet: Cannot clear saved states in StateMachineHandler unless in Idle state. Current state is {}.",
static_cast<int>(this->GetCurrentState()));
}
}

Callback function that is called whenever RoveComm receives new CLEARWAYPOINTS packet.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-03-03
127 {
128 // Not using this.
129 (void) stPacket;
130 (void) stdAddr;
131
132 /*
133 The clear waypoints command will clear all waypoints in the WaypointHandler, but it also clears all saved states in the StateMachineHandler
134 to prevent any conflicts when restarting autonomy with previously saved states that may have waypoints associated with them.
135 However, we only want to delete our saved states if we are currently in IdleState.
136 */
137
138 // Check if the current state is IdleState.
139 if (this->GetCurrentState() == statemachine::States::eIdle)
140 {
141 // Submit logger message.
142 LOG_NOTICE(logging::g_qSharedLogger, "Incoming Clear Waypoints packet: Deleting all saved states in StateMachineHandler...");
143 // Clear the saved states.
144 this->ClearSavedStates();
145 }
146 else
147 {
148 // Submit logger message.
149 LOG_WARNING(logging::g_qSharedLogger,
150 "Incoming Clear Waypoints packet: Cannot clear saved states in StateMachineHandler unless in Idle state. Current state is {}.",
151 static_cast<int>(this->GetCurrentState()));
152 }
153 };

◆ 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
165 {
166 // Not using this.
167 (void) stdAddr;
168
169 // Create instance variables.
170 double dTotalCellVoltages = 0.0;
171 int nValidCellVoltageValues = 0;
172
173 // Loop through voltage values and average all of the valid ones.
174 for (int nIter = 0; nIter < stPacket.unDataCount; ++nIter)
175 {
176 // Check if the voltage values is greater than at least 0.1.
177 if (stPacket.vData[nIter] >= 0.1)
178 {
179 // Add cell voltage value to total.
180 dTotalCellVoltages += stPacket.vData[nIter];
181 // Increment voltage voltage counter.
182 ++nValidCellVoltageValues;
183 }
184 }
185 // Calculate average cell voltage.
186 double dAverageCellVoltage = dTotalCellVoltages / nValidCellVoltageValues;
187
188 // Submit logger message.
189 LOG_DEBUG(logging::g_qSharedLogger, "Incoming Packet: PMS Cell Voltages. Average voltage is: {}", dAverageCellVoltage);
190
191 // Check if voltage is above the safe minimum for lithium ion batteries.
192 if (constants::BATTERY_CHECKS_ENABLED && dAverageCellVoltage < constants::BATTERY_MINIMUM_CELL_VOLTAGE &&
193 this->GetCurrentState() != statemachine::States::eIdle)
194 {
195 // Submit logger message.
196 LOG_CRITICAL(logging::g_qSharedLogger,
197 "Incoming PMS Packet: Average cell voltage is {} which is below the safe minimum of {}. Entering Idle state...",
198 dAverageCellVoltage,
199 constants::BATTERY_MINIMUM_CELL_VOLTAGE);
200
201 // Signal statemachine handler with stop event.
202 this->HandleEvent(statemachine::Event::eAbort, true);
203 }
204 };

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