Impl of Command Sequence Logic #2575
Replies: 4 comments 17 replies
-
@timcanham, @Joshua-Anderson did you see this? |
Beta Was this translation helpful? Give feedback.
-
Oh God! Not a GOTO command please. Just a thought.
Leonard J. Reder
…On Thu, Mar 7, 2024, 8:39 AM Zimri Leisher ***@***.***> wrote:
Hey all,
A couple weeks ago I posted asking about whether logic could be
implemented in command sequences (#2537
<#2537>). Well, I went ahead
and implemented it. Now command sequences can be Turing-complete 😆
Here's the first 10 Fibonacci numbers, calculated in a command sequence:
image.png (view on web)
<https://github.com/nasa/fprime/assets/25469876/c749ce23-d0ee-4d66-a6e6-6f2d521bc4c2>
Here's the command sequence:
R00:00:00 logic.SET_BOOL "loop_done", false
R00:00:00 logic.SET_INT "a", 0 ; (n-1)th fib number
R00:00:00 logic.SET_INT "b", 1 ; nth fib number
R00:00:00 logic.SET_INT "c", 0 ; temporary storage
R00:00:00 logic.SET_INT "iter", 0 ; current iteration of loop
R00:00:00 logic.SET_INT "max_iters", 10 ; number of iterations of loop we want to run
R00:00:00 logic.TRACK_VAR "b" ; output b in telemetry as "loggedVarInt"
R00:00:00 logic.GEQ "iter", "max_iters", "loop_done"; loop_done = (iter >= max_iters)
R00:00:00 logic.IF "loop_done", 10 ; if the loop is done, proceed, else go to cmd idx 10 where we continue the loop
R00:00:00 cmdSeq.CS_GOTO 15 ; go to the end
R00:00:00 logic.ADD "a", "b", "c" ; c = a + b
R00:00:00 logic.ASSIGN "a", "b" ; a = b
R00:00:00 logic.ASSIGN "b", "c" ; b = c
R00:00:00 logic.INCREMENT "iter"
R00:00:01 cmdSeq.CS_GOTO 7 ; go back to greater than or equal to after 1 second
R00:00:00 logic.STOP_TRACKING_VAR ; stop tracking b in telemetry
Here is how this is implemented:
1. CmdSequencer has a CS_GOTO command, and a goto port, which goes to
a command index in the currently running sequence. I implemented this in a
pretty simple way, it just resets the deserializer for the sequence binary
file and deserializes from the start until it reaches the desired command
index. With large values for cmdIndex I'm worried this could be
inefficient, but this was the best way I could think of.
void CmdSequencerComponentImpl::performCmd_Goto(const U32 cmdIndex) {
// reset the command sequence to start from the beginning
this->m_sequence->reset();
// we want to skip i number of commands
// e.g. if cmdIdx is 1, then we want to skip cmd at idx 0
int i = cmdIndex;
while(i > 0) {
if (!this->m_sequence->hasMoreRecords()) {
this->log_WARNING_HI_CS_InvalidCommandIndex(cmdIndex);
return;
}
this->m_sequence->nextRecord(m_record);
i--;
}
if (!this->m_sequence->hasMoreRecords()) {
this->log_WARNING_HI_CS_InvalidCommandIndex(cmdIndex);
return;
}
this->log_ACTIVITY_LO_CS_GotoSuccess(cmdIndex, this->m_sequence->getLogFileName());
}
1. A new component called CommandLogicManager was made, which has
three things: a variable database, logic and arithmetic functions which
operate on that database, and an if command which allows for non-trivial
control flow.
*Variable database*: I chose to use a new variable database rather than
the ParamDb or telemetry stream because both of those are really meant for
separate purposes. ParamDb is not supposed to be updated super frequently,
and telemetry is just an output of the system. The new database is dead
simple, it's just three std::maps of std::string to U8 (for bools), I32
(for ints), and F64 (for floats). You can set values in it with commands,
so command sequences can have their own workspace, and also with ports, so
that arbitrary code can set values for command sequences to use.
*Logic and arithmetic functions*: Standard stuff like &&, ||, +, -, pow,
sqrt, log are all commands which take in names of variables and store their
result in another variable. This means you can't do stuff like x = y + 1,
you have to do z = 1; x = y + z. Not sure how best to solve this, it
seems like I'd need a new command for each situation of argument type.
*If command*: If a boolean variable is true, it doesn't do anything and
the command sequencer goes to the next command. If the boolean variable is
false, it uses the CmdSequencer goto port to go to a specific command index
(the 'else' case).
Use cases
Our original intent with this is to allow for fault detection and response
to be implemented in command sequences, so that they can be modified from
the ground. However, this could also be useful if there is a situation in
which a decision will have to be made autonomously, and this situation was
not foreseen when developing the FSW.
I would love to hear your thoughts on this. I know that @timcanham
<https://github.com/timcanham> is going to post something soon about
this, so I'm looking forward to reading it. Next, I'm looking at adding
support for running multiple sequences at once.
—
Reply to this email directly, view it on GitHub
<#2575>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AASN3AH2QN3ISOKKYID6DLDYXCJ3VAVCNFSM6AAAAABELKY37CVHI2DSMVQWIX3LMV43ERDJONRXK43TNFXW4OZWGMZTONRZHA>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
If we were going to continue developing this into a more usable system, we would want it to look like ASI's FlightJAS: https://max.rocketlabusa.com/docs#MAX/Sequencing/FlightJAS.md |
Beta Was this translation helpful? Give feedback.
-
This is fantastic @zimri-leisher - I can't believe y'all have gotten conditional sequencing all up and running! I haven't looked at flightJAS before, will definitely be reviewing as well. This was definitely along the lines of what I was thinking. Here are some of the trade space discussions I've been thinking about as we move forward with conditional logic in fprime:
These are just some of the things I'm thinking about, and I fully expect that we'll all have different opinions on them - let me know what your thoughts are as well. Just want to make sure we consider that larger architectural decisions as we start to come up with an architecture. |
Beta Was this translation helpful? Give feedback.
-
Hey all,
A couple weeks ago I posted asking about whether logic could be implemented in command sequences (#2537). Well, I went ahead and implemented it. Now command sequences can be Turing-complete 😆
Here are the first 10 Fibonacci numbers, calculated in a command sequence:
Here's the command sequence:
Here is how this is implemented:
Variable database: I chose to use a new variable database rather than the ParamDb or telemetry stream because both of those are really meant for separate purposes. ParamDb is not supposed to be updated super frequently, and telemetry is just an output of the system. The new database is dead simple, it's just three
std::map
s ofstd::string
toU8
(for bools),I32
(for ints), andF64
(for floats). You can set values in it with commands, so command sequences can have their own workspace, and also with ports, so that arbitrary code can set values for command sequences to use.Logic and arithmetic functions: Standard stuff like &&, ||, +, -, pow, sqrt, log are all commands which take in names of variables and store their result in another variable. This means you can't do stuff like
x = y + 1
, you have to doz = 1; x = y + z
. Not sure how best to solve this, it seems like I'd need a new command for each situation of argument type.If command: If a boolean variable is true, it doesn't do anything and the command sequencer goes to the next command. If the boolean variable is false, it uses the CmdSequencer goto port to go to a specific command index (the 'else' case).
Use cases
Our original intent with this is to allow for fault detection and response to be implemented in command sequences, so that they can be modified from the ground. However, this could also be useful if there is a situation in which a decision will have to be made autonomously, and this situation was not foreseen when developing the FSW.
I would love to hear your thoughts on this. I know that @timcanham is going to post something soon about this, so I'm looking forward to reading it. Next, I'm looking at adding support for running multiple sequences at once.
Beta Was this translation helpful? Give feedback.
All reactions