STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
state_machine.cpp
Go to the documentation of this file.
1
#include <iostream>
2
#include <map>
3
#include <memory>
4
#include <string>
5
#include <vector>
6
7
// ============================================================================
8
// DATA STRUCTURES
9
// ============================================================================
10
11
// Sensor readings and system state parameters
12
struct
SystemParameters
{
13
// Pressures (psi)
14
float
PT_HP
= 0.0f;
15
float
PT_LP
= 0.0f;
16
float
PT_F
= 0.0f;
17
float
PT_O
= 0.0f;
18
19
float
RTD_O1
= 0.0f;
20
float
RTD_O2
= 0.0f;
21
float
RTD_O3
= 0.0f;
22
23
float
PT_I
= 0.0f;
24
float
TC_I
= 0.0f;
25
float
PT_C1
= 0.0f;
26
float
TC_C1
= 0.0f;
27
float
TC_C3
= 0.0f;
28
float
TC_C2
= 0.0f;
29
float
PT_C2
= 0.0f;
30
float
TC_C4
= 0.0f;
31
32
// Solenoid states (true = open/energized, false = closed/de-energized)
33
bool
SOL_PV
=
false
;
34
bool
SOL_FUP
=
false
;
35
bool
SOL_FV
=
false
;
36
bool
SOL_OUP
=
false
;
37
bool
SOL_OV
=
false
;
38
bool
SOL_FDP
=
false
;
39
bool
MOT_ODP
=
false
;
40
41
bool
ROT_MF
=
false
;
42
bool
ROT_MO
=
false
;
43
44
// Valve states (true = open, false = closed)
45
};
46
47
// ============================================================================
48
// STATE MACHINE BASE CLASS
49
// ============================================================================
50
51
class
EngineState
{
52
public
:
53
virtual
~EngineState
() =
default
;
54
virtual
void
on_enter
(
55
SystemParameters
& params) = 0;
// Called when entering the state
56
virtual
bool
update
(
57
SystemParameters
&
58
params) = 0;
// Called repeatedly while in the state// Returns true
59
// if state should automatically transition to next
60
// state
61
virtual
void
on_exit
(
62
SystemParameters
& params) = 0;
// Called when exiting the state
63
virtual
std::string
get_name
()
const
= 0;
// Get human-readable state name
64
virtual
bool
validate_entry
(
const
SystemParameters
& params)
65
const
= 0;
// Define what conditions must be met to enter this state//
66
// Each state checks the current SystemParameters and
67
// returns whether entry is valid
68
virtual
std::vector<std::string>
get_allowed_transitions
()
69
const
// Return an empty vector if no manual transitions are allowed //
70
// Define which states can be transitioned to FROM this state
71
{
72
return
{};
73
}
74
virtual
std::string
get_next_state_name
()
const
{
75
return
""
;
76
}
77
virtual
bool
is_automatic
()
78
const
// If true, this state automatically checks transition
79
// requirements for get_next_state_name()
80
{
81
return
false
;
82
}
83
};
84
85
// ============================================================================
86
// STATE MACHINE MANAGER
87
// ============================================================================
88
89
class
EngineFSM
{
90
public
:
91
EngineFSM
();
92
93
void
register_state
(
const
std::string& state_name,
94
std::shared_ptr<EngineState>
state
);
95
bool
request_transition
(
const
std::string& target_state,
96
SystemParameters
& params);
// manual transition
97
void
update
(
SystemParameters
& params);
98
std::string
get_current_state
()
const
;
99
std::vector<std::string>
get_available_transitions
(
100
const
SystemParameters
& params)
101
const
;
// Get all states that can be transitioned to from the current
102
// state// Includes only states whose validation criteria are
103
// currently met
104
105
private
:
106
void
transition_to_state
(
const
std::string& state_name,
107
SystemParameters
& params);
108
bool
can_enter_state
(
const
std::string& state_name,
109
const
SystemParameters
& params)
const
;
110
111
std::map<std::string, std::shared_ptr<EngineState>>
states
;
112
std::string
current_state
;
113
};
114
115
// ============================================================================
116
// IMPLEMENTATION
117
// ============================================================================
118
119
EngineFSM::EngineFSM
() :
current_state
(
""
) {
120
}
121
122
void
EngineFSM::register_state
(
const
std::string& state_name,
123
std::shared_ptr<EngineState>
state
) {
124
if
(
states
.find(state_name) !=
states
.end()) {
125
std::cerr <<
"Warning: State '"
<< state_name
126
<<
"' already registered\n"
;
127
return
;
128
}
129
states
[state_name] =
state
;
130
131
// Initialize to first registered state
132
if
(
current_state
.empty()) {
133
current_state
= state_name;
134
}
135
}
136
137
void
EngineFSM::update
(
SystemParameters
& params) {
138
if
(
states
.find(
current_state
) ==
states
.end()) {
139
return
;
140
}
141
142
auto
current =
states
[
current_state
];
143
144
// Update the current state
145
current->update(params);
146
147
// If this is an automatic state, check if we should transition
148
if
(current->is_automatic()) {
149
std::string next_state_name = current->get_next_state_name();
150
151
if
(!next_state_name.empty() &&
152
states
.find(next_state_name) !=
states
.end()) {
153
// Check if the next state's validation criteria are met
154
if
(
can_enter_state
(next_state_name, params)) {
155
transition_to_state
(next_state_name, params);
156
}
157
}
158
}
159
}
160
161
bool
EngineFSM::request_transition
(
const
std::string& target_state,
162
SystemParameters
& params) {
163
// Check if target state exists
164
if
(
states
.find(target_state) ==
states
.end()) {
165
std::cerr <<
"Error: Target state '"
<< target_state
166
<<
"' not registered\n"
;
167
return
false
;
168
}
169
170
// Check if target state's validation criteria are met
171
if
(!
can_enter_state
(target_state, params)) {
172
std::cerr <<
"Error: Cannot enter state '"
<< target_state
173
<<
"' - validation criteria not met\n"
;
174
return
false
;
175
}
176
177
transition_to_state
(target_state, params);
178
return
true
;
179
}
180
181
void
EngineFSM::transition_to_state
(
const
std::string& state_name,
182
SystemParameters
& params) {
183
// Exit current state
184
if
(
states
.find(
current_state
) !=
states
.end()) {
185
states
[
current_state
]->on_exit(params);
186
std::cout <<
"Exiting state: "
<<
states
[
current_state
]->get_name()
187
<<
"\n"
;
188
}
189
190
// Enter new state
191
current_state
= state_name;
192
states
[
current_state
]->on_enter(params);
193
std::cout <<
"Entering state: "
<<
states
[
current_state
]->get_name()
194
<<
"\n"
;
195
}
196
197
std::string
EngineFSM::get_current_state
()
const
{
198
return
current_state
;
199
}
200
201
bool
EngineFSM::can_enter_state
(
const
std::string& state_name,
202
const
SystemParameters
& params)
const
{
203
if
(
states
.find(state_name) ==
states
.end()) {
204
return
false
;
205
}
206
auto
allowed =
states
.at(
current_state
)->get_allowed_transitions();
207
if
(std::find(allowed.begin(), allowed.end(), state_name) ==
208
allowed.end()) {
209
return
false
;
// Not an allowed transition from current state
210
}
211
return
states
.at(state_name)->validate_entry(params);
212
}
213
214
std::vector<std::string>
EngineFSM::get_available_transitions
(
215
const
SystemParameters
& params)
const
{
216
std::vector<std::string> available;
217
218
// Get the list of allowed transitions from the current state
219
if
(
states
.find(
current_state
) ==
states
.end()) {
220
return
available;
221
}
222
223
auto
allowed =
states
.at(
current_state
)->get_allowed_transitions();
224
225
// Filter to only those whose validation criteria are met
226
for
(
const
auto
& target_state : allowed) {
227
if
(
can_enter_state
(target_state, params)) {
228
available.push_back(target_state);
229
}
230
}
231
232
return
available;
233
}
234
235
// ============================================================================
236
// EXAMPLE USAGE (SKELETON - ADD YOUR STATES HERE)
237
// ============================================================================
238
239
/*
240
// Example: Manual state (requires user command to transition)
241
class IdleState : public EngineState {
242
public:
243
void on_enter(const SystemParameters& params) override {
244
std::cout << " Idle: All systems standing by\n";
245
}
246
247
bool update(const SystemParameters& params) override {
248
return false; // No automatic behavior
249
}
250
251
void on_exit(const SystemParameters& params) override {
252
std::cout << " Idle: Leaving idle state\n";
253
}
254
255
std::string get_name() const override {
256
return "Idle";
257
}
258
259
bool validate_entry(const SystemParameters& params) const override {
260
// Idle can always be entered (e.g., abort state)
261
return true;
262
}
263
264
std::vector<std::string> get_allowed_transitions() const override {
265
return {"Pressurize", "Abort"};
266
}
267
};
268
269
// Example: Automatic state (transitions automatically when next state's
270
conditions are met) class PressurizeState : public EngineState { private:
271
// Track state duration or progress
272
int iteration_count = 0;
273
274
public:
275
void on_enter(const SystemParameters& params) override {
276
std::cout << " Pressurize: Starting pressurization sequence\n";
277
iteration_count = 0;
278
// In real code: open GN2 solenoid, monitor pressures, etc.
279
}
280
281
bool update(const SystemParameters& params) override {
282
iteration_count++;
283
// Simulate pressure building
284
if (iteration_count % 10 == 0) {
285
std::cout << " Pressurize: Pressurizing tanks...\n";
286
}
287
return false; // Don't return true; let is_automatic() handle
288
transitions
289
}
290
291
void on_exit(const SystemParameters& params) override {
292
std::cout << " Pressurize: Pressurization complete\n";
293
}
294
295
std::string get_name() const override {
296
return "Pressurize";
297
}
298
299
bool validate_entry(const SystemParameters& params) const override {
300
// Can only enter if initial state is acceptable
301
return true; // Define real conditions based on your system
302
}
303
304
std::vector<std::string> get_allowed_transitions() const override {
305
return {"Idle", "Abort"};
306
}
307
308
bool is_automatic() const override {
309
return true;
310
}
311
312
std::string get_next_state_name() const override {
313
return "ReadyToFire";
314
}
315
};
316
317
// Example: Target state for automatic transition
318
class ReadyToFireState : public EngineState {
319
public:
320
void on_enter(const SystemParameters& params) override {
321
std::cout << " ReadyToFire: All systems pressurized and ready\n";
322
}
323
324
bool update(const SystemParameters& params) override {
325
return false;
326
}
327
328
void on_exit(const SystemParameters& params) override {
329
std::cout << " ReadyToFire: Leaving ready state\n";
330
}
331
332
std::string get_name() const override {
333
return "ReadyToFire";
334
}
335
336
bool validate_entry(const SystemParameters& params) const override {
337
// Define conditions that must be met to enter ready state
338
// For example: all pressures in acceptable range
339
return params.fuel_pressure > 100.0f &&
340
params.ox_pressure > 100.0f &&
341
params.gn2_pressure > 50.0f;
342
}
343
344
std::vector<std::string> get_allowed_transitions() const override {
345
return {"Fire", "Abort"};
346
}
347
};
348
349
// In main():
350
EngineFSM fsm;
351
fsm.register_state("Idle", std::make_shared<IdleState>());
352
fsm.register_state("Pressurize", std::make_shared<PressurizeState>());
353
fsm.register_state("ReadyToFire", std::make_shared<ReadyToFireState>());
354
// Register more states...
355
356
SystemParameters params;
357
358
// Main loop
359
while (true) {
360
// Read sensor data into params...
361
// params.fuel_pressure = read_fuel_pressure();
362
// params.ox_pressure = read_ox_pressure();
363
// etc.
364
365
// Display available transitions to user
366
auto available = fsm.get_available_transitions(params);
367
std::cout << "Available transitions from " << fsm.get_current_state() <<
368
":\n"; for (const auto& state : available) { std::cout << " - " << state <<
369
"\n";
370
}
371
372
// Update state machine (handles automatic transitions)
373
fsm.update(params);
374
375
// User can request manual transitions
376
// if (user_wants_pressurize) {
377
// fsm.request_transition("Pressurize", params);
378
// }
379
}
380
*/
EngineFSM::get_current_state
std::string get_current_state() const
Definition
state_machine.cpp:197
EngineFSM::get_available_transitions
std::vector< std::string > get_available_transitions(const SystemParameters ¶ms) const
Definition
state_machine.cpp:214
EngineFSM::states
std::map< std::string, std::shared_ptr< EngineState > > states
Definition
state_machine.cpp:111
EngineFSM::register_state
void register_state(const std::string &state_name, std::shared_ptr< EngineState > state)
Definition
state_machine.cpp:122
EngineFSM::request_transition
bool request_transition(const std::string &target_state, SystemParameters ¶ms)
Definition
state_machine.cpp:161
EngineFSM::can_enter_state
bool can_enter_state(const std::string &state_name, const SystemParameters ¶ms) const
Definition
state_machine.cpp:201
EngineFSM::current_state
std::string current_state
Definition
state_machine.cpp:112
EngineFSM::transition_to_state
void transition_to_state(const std::string &state_name, SystemParameters ¶ms)
Definition
state_machine.cpp:181
EngineFSM::EngineFSM
EngineFSM()
Definition
state_machine.cpp:119
EngineFSM::update
void update(SystemParameters ¶ms)
Definition
state_machine.cpp:137
EngineState
Definition
state_machine.cpp:51
EngineState::is_automatic
virtual bool is_automatic() const
Definition
state_machine.cpp:77
EngineState::validate_entry
virtual bool validate_entry(const SystemParameters ¶ms) const =0
EngineState::get_name
virtual std::string get_name() const =0
EngineState::get_next_state_name
virtual std::string get_next_state_name() const
Definition
state_machine.cpp:74
EngineState::get_allowed_transitions
virtual std::vector< std::string > get_allowed_transitions() const
Definition
state_machine.cpp:68
EngineState::on_exit
virtual void on_exit(SystemParameters ¶ms)=0
EngineState::on_enter
virtual void on_enter(SystemParameters ¶ms)=0
EngineState::update
virtual bool update(SystemParameters ¶ms)=0
EngineState::~EngineState
virtual ~EngineState()=default
state
static ActuatorControllerState state
Definition
main.cpp:57
SystemParameters
Definition
state_machine.cpp:12
SystemParameters::PT_HP
float PT_HP
Definition
state_machine.cpp:14
SystemParameters::SOL_OV
bool SOL_OV
Definition
state_machine.cpp:37
SystemParameters::SOL_PV
bool SOL_PV
Definition
state_machine.cpp:33
SystemParameters::SOL_FDP
bool SOL_FDP
Definition
state_machine.cpp:38
SystemParameters::RTD_O1
float RTD_O1
Definition
state_machine.cpp:19
SystemParameters::ROT_MO
bool ROT_MO
Definition
state_machine.cpp:42
SystemParameters::ROT_MF
bool ROT_MF
Definition
state_machine.cpp:41
SystemParameters::TC_I
float TC_I
Definition
state_machine.cpp:24
SystemParameters::PT_C1
float PT_C1
Definition
state_machine.cpp:25
SystemParameters::PT_F
float PT_F
Definition
state_machine.cpp:16
SystemParameters::PT_O
float PT_O
Definition
state_machine.cpp:17
SystemParameters::TC_C3
float TC_C3
Definition
state_machine.cpp:27
SystemParameters::SOL_OUP
bool SOL_OUP
Definition
state_machine.cpp:36
SystemParameters::SOL_FV
bool SOL_FV
Definition
state_machine.cpp:35
SystemParameters::RTD_O3
float RTD_O3
Definition
state_machine.cpp:21
SystemParameters::TC_C2
float TC_C2
Definition
state_machine.cpp:28
SystemParameters::SOL_FUP
bool SOL_FUP
Definition
state_machine.cpp:34
SystemParameters::RTD_O2
float RTD_O2
Definition
state_machine.cpp:20
SystemParameters::TC_C1
float TC_C1
Definition
state_machine.cpp:26
SystemParameters::PT_C2
float PT_C2
Definition
state_machine.cpp:29
SystemParameters::TC_C4
float TC_C4
Definition
state_machine.cpp:30
SystemParameters::PT_LP
float PT_LP
Definition
state_machine.cpp:15
SystemParameters::MOT_ODP
bool MOT_ODP
Definition
state_machine.cpp:39
SystemParameters::PT_I
float PT_I
Definition
state_machine.cpp:23
firmware
State Machine
state_machine.cpp
Generated by
1.15.0