STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
PressureStateMachine.hpp
Go to the documentation of this file.
1#ifndef PRESSURE_STATE_MACHINE_HPP
2#define PRESSURE_STATE_MACHINE_HPP
3
4#include <atomic>
5#include <chrono>
6#include <map>
7#include <memory>
8#include <mutex>
9#include <string>
10#include <thread>
11
16
17namespace fsw {
18namespace control {
19
20/**
21 * @brief Pressure-based State Machine for Propulsion System
22 *
23 * Reads pressure data from Elodin and sends actuator commands based on state transitions.
24 * Implements the propulsion system state machine with pressure-based transitions.
25 */
27public:
28 /**
29 * @brief System states matching the state machine diagram
30 */
31 enum class SystemState {
32 DEBUG_STATE, // Debug mode
33 IDLE, // Idle state (central resting state)
34 ARMED, // System armed
35 FUEL_FILL, // Fuel fill state
36 OX_FILL, // Oxidizer fill state
37 GN2_LOW_PRESS, // GN2 low pressure pressurization
38 GN2_VENT, // GN2 vent state
39 FUEL_PRESS, // Fuel pressurization
40 FUEL_VENT, // Fuel vent state
41 OX_PRESS, // Oxidizer pressurization
42 OX_VENT, // Oxidizer vent state
43 GN2_HIGH_PRESS, // GN2 high pressure pressurization
44 GN2_HIGH_VENT, // GN2 high vent state
45 VENT, // General vent state (safety)
46 CALIBRATE, // Calibration state
47 READY, // Ready for fire
48 FIRE, // Fire state
49 ABORT // Abort state
50 };
51
52 /**
53 * @brief Actuator identifiers matching config
54 */
55 enum class ActuatorID {
56 LOX_MAIN = 0, // ACTUATOR_LOX_MAIN (message_id 0x5060)
57 FUEL_MAIN = 1, // ACTUATOR_FUEL_MAIN (message_id 0x5061)
58 LOX_VENT = 2, // ACTUATOR_LOX_VENT (message_id 0x5062)
59 FUEL_VENT = 3, // ACTUATOR_FUEL_VENT (message_id 0x5063)
60 LOX_PRESS = 4, // ACTUATOR_LOX_PRESS (message_id 0x5064)
61 FUEL_PRESS = 5, // ACTUATOR_FUEL_PRESS (message_id 0x5065)
62 PRESSURE_VENT = 6 // Pressure vent valve (GN2)
63 };
64
65 /**
66 * @brief Command types for actuators
67 */
68 enum class CommandType : uint8_t { OPEN = 1, CLOSE = 2, PULSE = 3, SET_POSITION = 4 };
69
70 /**
71 * @brief Pressure sensor readings
72 */
74 double gn2_pressure_psi = 0.0; // GN2 pressure (from PT_HP or PT_LP)
75 double fuel_pressure_psi = 0.0; // Fuel pressure (from PT_FUP or PT_FDP)
76 double ox_pressure_psi = 0.0; // Oxidizer pressure (from PT_OUP or PT_ODP)
77 std::chrono::steady_clock::time_point timestamp;
78 bool valid = false;
79 };
80
81 /**
82 * @brief Configuration for pressure thresholds
83 */
85 double gn2_low_target_psi = 2000.0; // Target for GN2 low press
86 double gn2_low_max_psi = 2500.0; // Max before vent
87 double gn2_high_target_psi = 4500.0; // Target for GN2 high press
88 double gn2_high_max_psi = 4600.0; // Max before vent
89 double fuel_target_psi = 1000.0; // Target for fuel press
90 double fuel_max_psi = 850.0; // Max before vent (note: seems inverted in diagram)
91 double fuel_min_psi = 750.0; // Min before vent closes
92 double ox_target_psi = 1000.0; // Target for ox press
93 double ox_max_psi = 1100.0; // Max before vent
94 double ox_min_psi = 950.0; // Min before vent closes
95 };
96
99
100 /**
101 * @brief Initialize the state machine
102 * @param elodin_client Connected Elodin client for reading pressure data
103 * @param board_discovery Board discovery instance for getting board IPs
104 * @param thresholds Pressure thresholds configuration
105 * @return true if initialization successful
106 */
107 bool initialize(std::shared_ptr<elodin::ElodinClient> elodin_client,
108 std::shared_ptr<config::BoardDiscovery> board_discovery,
109 const PressureThresholds& thresholds);
110
111 /**
112 * @brief Start the state machine
113 */
114 void start();
115
116 /**
117 * @brief Stop the state machine
118 */
119 void stop();
120
121 /**
122 * @brief Get current state
123 */
125
126 /**
127 * @brief Get current state name as string
128 */
129 std::string getCurrentStateName() const;
130
131 /**
132 * @brief Request transition to a specific state (manual override)
133 */
134 bool requestTransition(SystemState target_state);
135
136 /**
137 * @brief Request abort
138 */
139 void requestAbort();
140
141 /**
142 * @brief Get latest pressure readings
143 */
145
146private:
147 /**
148 * @brief Main state machine loop
149 */
150 void stateMachineLoop();
151
152 /**
153 * @brief Read pressure data from Elodin
154 */
155 void readPressureData();
156
157 /**
158 * @brief Check transition conditions based on current state and pressures
159 */
160 void checkTransitions();
161
162 /**
163 * @brief Execute state entry actions
164 */
166
167 /**
168 * @brief Execute state actions (while in state)
169 */
171
172 /**
173 * @brief Send actuator command
174 */
175 void sendActuatorCommand(ActuatorID actuator, CommandType command, float value = 0.0f);
176
177 /**
178 * @brief Convert actuator ID to message ID from config
179 */
180 uint16_t actuatorToMessageID(ActuatorID actuator) const;
181
182 /**
183 * @brief Send actuator command via UDP to board
184 */
185 void sendActuatorCommandUDP(ActuatorID actuator, CommandType command, float value = 0.0f);
186
187 /** @brief Register Elodin VTables for PSM actuator commands and state transitions. */
188 void registerPSMVTables();
189
190 /**
191 * @brief Get board IP and port for actuator
192 */
193 std::pair<std::string, uint16_t> getActuatorBoardAddress(ActuatorID actuator) const;
194
195 // State variables
196 std::atomic<bool> running_;
197 std::atomic<SystemState> current_state_;
198 std::atomic<bool> abort_requested_;
199 std::chrono::steady_clock::time_point state_entry_time_;
200
201 // Elodin client for reading pressure data
202 std::shared_ptr<elodin::ElodinClient> elodin_client_;
203
204 // Board discovery for getting board IPs
205 std::shared_ptr<config::BoardDiscovery> board_discovery_;
206
207 // UDP socket for sending commands (reused, like DiabloAvionics GUI)
208 std::unique_ptr<daq_comms::transport::UDPSocket> command_socket_;
209
210 // Actuator board IP and port (from config or discovery)
213
214 // Pressure readings (thread-safe)
215 mutable std::mutex pressure_mutex_;
217
218 // Configuration
220
221 // Sensor message IDs — calibrated PT packets ([0x20, 0x10 + channel])
222 // Calibration server writes these; they carry float32 PSI at payload offset 12.
223 // Channel assignments match sensor_roles_pt_board in config.toml.
224 uint16_t pt_hp_message_id_ = 0x2016; // Calibrated PT CH6 = GN2 Regulated
225 uint16_t pt_lp_message_id_ = 0x2011; // Calibrated PT CH1 = Fuel Upstream (low-P reference)
226 uint16_t pt_fup_message_id_ = 0x2011; // Calibrated PT CH1 = Fuel Upstream
227 uint16_t pt_fdp_message_id_ = 0x2013; // Calibrated PT CH3 = Fuel Downstream
228 uint16_t pt_oup_message_id_ = 0x2015; // Calibrated PT CH5 = Ox Upstream
229 uint16_t pt_odp_message_id_ = 0x2017; // Calibrated PT CH7 = Ox Downstream
230
231 // Actuator message IDs from config
232 std::map<ActuatorID, uint16_t> actuator_message_ids_;
233
234 // Threading
236 std::mutex state_mutex_;
237
238 // Timing
239 std::chrono::milliseconds state_machine_period_{100}; // 10 Hz state machine
240 std::chrono::milliseconds pressure_read_period_{50}; // 20 Hz pressure reading
241};
242
243} // namespace control
244} // namespace fsw
245
246#endif // PRESSURE_STATE_MACHINE_HPP
const std::string ABORT
void readPressureData()
Read pressure data from Elodin.
void registerPSMVTables()
Register Elodin VTables for PSM actuator commands and state transitions.
std::chrono::milliseconds pressure_read_period_
bool requestTransition(SystemState target_state)
Request transition to a specific state (manual override).
uint16_t actuatorToMessageID(ActuatorID actuator) const
Convert actuator ID to message ID from config.
void stateMachineLoop()
Main state machine loop.
SystemState
System states matching the state machine diagram.
void sendActuatorCommand(ActuatorID actuator, CommandType command, float value=0.0f)
Send actuator command.
bool initialize(std::shared_ptr< elodin::ElodinClient > elodin_client, std::shared_ptr< config::BoardDiscovery > board_discovery, const PressureThresholds &thresholds)
Initialize the state machine.
std::string getCurrentStateName() const
Get current state name as string.
std::chrono::steady_clock::time_point state_entry_time_
std::atomic< SystemState > current_state_
CommandType
Command types for actuators.
void executeStateActions(SystemState state)
Execute state actions (while in state).
void executeStateEntryActions(SystemState state)
Execute state entry actions.
SystemState getCurrentState() const
Get current state.
std::map< ActuatorID, uint16_t > actuator_message_ids_
PressureReadings getLatestPressures() const
Get latest pressure readings.
std::chrono::milliseconds state_machine_period_
std::pair< std::string, uint16_t > getActuatorBoardAddress(ActuatorID actuator) const
Get board IP and port for actuator.
void start()
Start the state machine.
void sendActuatorCommandUDP(ActuatorID actuator, CommandType command, float value=0.0f)
Send actuator command via UDP to board.
ActuatorID
Actuator identifiers matching config.
std::shared_ptr< elodin::ElodinClient > elodin_client_
std::unique_ptr< daq_comms::transport::UDPSocket > command_socket_
std::shared_ptr< config::BoardDiscovery > board_discovery_
void checkTransitions()
Check transition conditions based on current state and pressures.
static ActuatorControllerState state
Definition main.cpp:57
@ IDLE
Definition gnss_frame.c:6
Motorized ball valve position: raw ADC counts -> % open.