10. Software
Hello World Software Lab – F’
Luke Clements
Note: This lab can be browsed through the textbook or through the F Prime website and GitHub repository:
-> Go to the website
-> Go to the GitHub repository
Note: Please be aware that the most current information can be found on the F Prime website and GitHub repository versions.
This lab was tested using F Prime release v3.4.1.
Table of Contents:
- Lab Description
- Prerequisites
- F´ Terminology
- Creating an F´ Project
- Creating an F´ Hello World Component
- Integration and Testing With F´ Deployments
Lab Description
Welcome to the Hello World Lab, an introductory tutorial designed to familiarize users with the basics of F´, a powerful framework for developing flight software. Whether you are a newcomer looking to grasp fundamental F´ usage or an experienced developer seeking insights into new commands, this lab serves as the canonical “Hello World” example for F´.
- A computer running Linux, MacOS, or WSL 1 on Windows (see installation steps below).
- Note: If you have a windows machine you must use WSL1 and not WSL2
- Open PowerShell or Windows Command Prompt in administrator mode by right-clicking and selecting “Run as administrator”, enter the wsl –install command.
wsl --install
- Then restart your machine, open PowerShell or Windows Command Prompt in administrator mode by right-clicking and selecting “Run as administrator”, and run the following command:
wsl --set-default-version 1
- Note: If you get the error message “WSL 1 is not supported with your current Machine Configuration. Please enable the “Windows Subsystem for Linux” optional component to use WSL 1″
- Go to your Windows machines Control Panel -> Programs -> Programs and Features -> Turn Windows features on or off -> Select the check box for Windows Subsystem for Linux -> Press OK -> Restart Now -> the rerun the “wsl –set-default-version 1” command
- Finally, run the following command to update your WSL distribution:
sudo apt update && sudo apt upgrade
Important: If you are utilizing a Windows Computer for this lab, continue with the remaining prerequisites and lab steps in the WSL App.
- Git
- MacOS:
git --version
- If you don’t have it installed already, it will prompt you to install it.
- Linux/WSL:
sudo apt install git
- MacOS:
- CMake 3.16 or newer. CLI tools must be available on the system path.
- MacOS:
- Linux/WSL:
sudo apt install cmake
- Note: macOS users must ensure the CMake command line utility is on their path
- MacOS:
- CLang
- MacOS:
xcode-select --install
- Linux/WSL:
sudo apt install clang
- MacOS:
- Python 3.8+
- Mac
- Linux/WSL
- Ubuntu should come with python already installed you can make sure by running:
-
python3 --version
-
- Ubuntu should come with python already installed you can make sure by running:
- PIP
- Linux/WSL:
sudo apt install python3-pip
- Linux/WSL:
- Python Virtual Environments
- MacOS:
pip install virtualenv
- Linux/WSL:
sudo apt install python3-venv
- MacOS:
- Note: WSL and Linux users should see notes on Python installation if they are running into any issues with Python.
- Visual Studio, an integrated development environment (IDE). With the F’ plugin and WSL extension if you are using WSL1 for this lab.
F´ Terminology
F´ uses specific terminology to refer to specific parts of the system. This section dives into the basic F´ terminology used in this tutorial and an explanation of how the terminology is used.
Project
An F´ project is a collection of files and folders used to work with F´. At its core, a project is just a folder that can be used to hold F´ code. Projects should specifically exclude the core F´ library to avoid the “clone and own” problem. Rather projects should link-to a version of F´.
This tutorial will create a new MyProject project used to contain the other things created by the tutorial.
Component
An F´ component encapsulates a unit of system behavior. Components use ports to communicate with other components and define commands, events, telemetry channels, and parameters.
This tutorial will create a new HelloWorld component that defines a SAY_HELLOcommand, Hello event, and GreetingCount telemetry channel. The component only used built-in ports. It does not use custom ports nor parameters.
Port
A port is an interface used to communicate between components. This tutorial only uses built-in ports.
Command
Commands represent actions that a component can execute. Commands can be sent from the ground or via command sequences. Command behavior is defined in a command handler defined in the component’s implementation.
This tutorial defines one command SAY_HELLO with a single argument greeting. This command will be sent via the ground system and will echo the greeting back via the Hello event.
Event
Events represent actions that a component has performed. Events are akin to software log messages. Events are received and displayed by the ground system.
This tutorial defines one event Hello emitted in response to the SAY_HELLO command and contains the same greeting that the command had.
Telemetry Channel
Telemetry channels provide the active state of the component. Each channel represents a single item of state that will be sent to the ground system.
This tutorial defines a single channel GreetingCount that contains the count of the number of SAY_HELLO greeting commands received.
Deployment
Deployments are a single build of F´ software. Each deployment results in one software executable that can be run along with other associated files. Each deployment has a topology that defines the system.
This tutorial will create the HelloWorldDeployment deployment, run this deployment, and test it through the F´ GDS.
Topology
Topologies are networks of connected components that define the software. Multiple instances of a component may be added to the topology.
This tutorial will use a standard command and data handling topology. A single HelloWorld component instance called helloWorld will be added to the standard topology.
Creating an F´ Project
This tutorial will walk new users through creating a new F´ project.
Start by opening the appropriate command line interface for your operating system.
Note: If you are utilizing WSL1, please ensure that you have the VS Code WSL extension installed. Next, launch VS Code, look for this icon in the bottom left ><, and choose “WSL: Connect to WSL” from the menu.
Bootstrapping F´
An F´ project ties to a specific version of tools to work with F´. In order to create this project and install the correct version of tools, you should perform a bootstrap of F´.
1. Install the F´ Bootstrap tool
The F´ Bootstrap tool is responsible for creating a new F´ project and installing the Python dependencies within the project’s virtual environment. Install the fprime-bootstrap tool with:
pip install fprime-bootstrap
Note: If you get this warning after installing the bootstrap “WARNING: The script fprime-bootstrap is installed in ‘/home/evank/.local/bin’ which is not on PATH. Consider adding this directory to PATH or, if you prefer to suppress this warning, use –no-warn-script-location.” Run the following command to add the bootstrap to you PATH.
export PATH=$PATH:/home/your_username/.local/bin
- Make sure to change “your_username” to the username you chose when installing WSL.
2. Create a new project
The entrypoint to developing with F´ is creating a new project. This will clone the F´ repository and install the full tool suite of the specified version for working with the selected version of F´. To create a new project, run:
fprime-bootstrap project
This command will ask for a project name. We will use the default: MyProject
[1/1] Project name (MyProject): MyProject
3. Understanding the project structure
Bootstrapping your F´ project created a folder called MyProject
(or any name you chose) containing the standard F´ project structure as well as the virtual environment containing the tools to work with F´.
We should navigate to the project’s directory and look around:
cd MyProject
ls
This will show the following files:
fprime/
: F´ repository, this is a git submodule that points to https://github.com/nasa/fprime. Contains core F´ components, the API for the build system, among otherssettings.ini
: allows users to set various settings to control the buildCMakeList.txt
andproject.cmake
: CMake files defining the build systemComponents/
: directory to place user components infprime-venv/
: this directory is the virtual environment containing the Python tools to work with F´
4. Activate the virtual environment
Activate the virtual environment to use the F´ tool suite.
# in MyProject/
. fprime-venv/bin/activate
Note: Always remember to activate the virtual environment whenever you work with this F´ project.
Building the New F´ Project
The next step is to set up and build the newly created project. This will serve as a build environment for any newly created components, and will build the F´ framework supplied components.
cd MyProject
fprime-util generate
fprime-util build
fprime-util build can be sped up by building in parrallel on multiple cores, using the -j <N> option. For example, fprime-util build -j16
Conclusion
A new project has been created with the name MyProject
and has been placed in a new folder called MyProject
in the current directory. It includes the initial build system setup, and F´ version. It is still empty in that the user will still need to create components and deployments.
For the remainder of this Hello World tutorial we should use the tools installed for our project and issue commands within this new project’s folder:
# In: MyProject
. venv/bin/activate
Use this command if your virtual environment is not already running.
Creating an F´ Hello World Component
This tutorial will walk new users through creating a basic F´ component. Users should have completed the new project tutorial and have the tools sourced as shown in the conclusion portion of that tutorial.
F´ components encapsulate the various parts of system behavior. These components can interact with the ground system through commands, events, and telemetry channels. Components communicate with other components through ports.
Hello World Component Requirements
The first step for creating a new component is understanding what it is that we wish to implement. This is called defining requirements. In the spirit of “Hello World” this component will encapsulate greeting behavior. The component will define three items to implement greeting behavior:
- A command called
SAY_HELLO
that will command the component to send a greeting - An event called
Hello
that is the greeting sent in response to theSAY_HELLO
command - A telemetry channel called
GreetingCount
that will count eachHello
event sent
These are a simple set of requirements for this component.
Creating the Hello World Component
The next step is to create the new component. The project contains a Components/
directory to create components in.
# In: MyProject
cd Components
Creating a new component is accomplished with the following command:
# In: MyProject/Components
fprime-util new --component
This command will ask for some input. You should respond with the following answers:
[INFO] Cookiecutter source: using builtin
Component name [MyComponent]: HelloWorld
Component short description [Component for F Prime FSW framework.]: Hello World Tutorial Component
Component namespace [Components]: Components
Select component kind:
1 - active
2 - passive
3 - queued
Choose from 1, 2, 3 [1]: 1
Enable Commands?:
1 - yes
2 - no
Choose from 1, 2 [1]: 1
Enable telemetry?:
1 - yes
2 - no
Choose from 1, 2 [1]: 1
Enable Events:
1 - yes
2 - no
Choose from 1, 2 [1]: 1
Enable Parameters:
1 - yes
2 - no
Choose from 1, 2 [1]: 1
[INFO] Found CMake file at 'Components/CMakeLists.txt'
Add component Components/HelloWorld to Components/CMakeLists.txt at end of file (yes/no)? yes
Generate implementation files (yes/no)? yes
For any other questions, select the default response.
This will create a new component called “HelloWorld” in the “Components” namespace. This new component will be able to define commands, events, telemetry channels, and parameters.
We should navigate to the component’s directory and look around:
# In: MyProject/Components
cd HelloWorld
ls
This will show the following files:
HelloWorld.fpp
: design model for the componentHelloWorld.hpp
andHelloWorld.cpp
: C++ implementation files for the component, currently empty.CMakeList.txt
: build definitions for the component.docs
folder to place component documentation
To build this component run fprime-util build
in the current folder.
Any component in F´ can be built by navigating to the component’s folder and running fprime-util build
.
Editing the Component Model
A component model defines the interface of the component with the rest of the F´ system and with the ground system F´ communicates with. In this case we intend to define a command, an event, and a telemetry channel as specified above.
Open the model file HelloWorld.fpp
in Visual Studio Code or your preferred IDE and replace this line:
async command TODO opcode 0
with the following:
@ Command to issue greeting with maximum length of 20 characters
async command SAY_HELLO(
greeting: string size 20 @< Greeting to repeat in the Hello event
)
@ Greeting event with maximum greeting length of 20 characters
event Hello(
greeting: string size 20 @< Greeting supplied from the SAY_HELLO command
) severity activity high format "I say: {}"
@ A count of the number of greetings issued
telemetry GreetingCount: U32
You should replace any existing command, event, and channel definitions with those supplied above but leave the ‘Standard AC Ports’ section untouched.
With this step completed you can generate a basic implementation with the following command:
# In: MyProject/Components/HelloWorld
fprime-util impl
fprime-util impl
creates HelloWorld.hpp-template
and HelloWorld.cpp-template
which contain empty functions based on what we have written in the FPP file. While normally one would merge new templates with the existing code, we will instead overwrite the existing implementations as we have not edited those files yet. To do this:
mv HelloWorld.template.hpp HelloWorld.hpp
mv HelloWorld.template.cpp HelloWorld.cpp
We are now ready to implement component behavior.
Implementing Component Behavior
F´ behavior is implemented in two types of methods: command handler functions to implement command behavior and handler functions to implement port behavior (as described in the next tutorial). For this tutorial we need to implement the SAY_HELLO
command, so we need to edit the SAY_HELLO_cmdHandler
function in the HelloWorld.cpp
file. Ensure its contents look like:
void HelloWorld:: SAY_HELLO_cmdHandler(FwOpcodeType opCode, U32 cmdSeq, const Fw::CmdStringArg& greeting) {
// Copy the command string input into an event string for the Hello event
Fw::LogStringArg eventGreeting(greeting.toChar());
// Emit the Hello event with the copied string
this->log_ACTIVITY_HI_Hello(eventGreeting);
this->tlmWrite_GreetingCount(++this->m_greetingCount);
// Tell the fprime command system that we have completed the processing of the supplied command with OK status
this->cmdResponse_out(opCode, cmdSeq, Fw::CmdResponse::OK);
}
We must also add the m_greetingCount member variable to the class defined in HelloWorld.hpp
and the constructor defined in HelloWorld.cpp
. This looks like:
HelloWorld.hpp: Adding New Member Variable
PRIVATE:
U32 m_greetingCount;
Should be added inside the class
definition in HelloWorld.hpp
.
HelloWorld.cpp: Updating Constructor
HelloWorld:: HelloWorld(const char *const compName) : HelloWorldComponentBase(compName),
m_greetingCount(0)
{
}
Should be added to the HelloWorld
constructor at the top of the file.
The component should build without errors by running fprime-util build
. Resolve any errors that occur before proceeding to the next section. Remember to always save before you build, unsaved changes will not be included in the build.
Conclusion
This tutorial has walked through the creation of a component that implements a “Hello World” style greeting behavior for our F´ system. In the next tutorial, this component will be hooked-up to an F´ deployment and tested!
Integration and Testing With F´ Deployments
This section will walk new users through creating a new F´ deployment. This deployment will build a topology containing the standard F´ stack of components and a single HelloWorld component instance. The HelloWorld was created in the last section. The tutorial will close by testing the deployment and HelloWorld component through the fprime-gds.
Creating A New Deployment
F´ deployments represent one flight software executable. All the components we develop for F´ run within a deployment. The deployment created here will contain the standard command and data handling stack. This stack enables ground control and data collection of the deployment.
To create a deployment, run the following commands:
# In: MyProject
fprime-util new --deployment
This command will ask for some input. Respond with the following answers:
Deployment name [MyDeployment]: HelloWorldDeployment
For any other questions, select the default response.
At this point, the HelloWorldDeployment
has been created, but our HelloWorld
component has not been added to the deployment.
Adding The Hello World Component
In this section the HelloWorld
component will be added to the HelloWorldDeployment
deployment. This can be done by adding the component to the topology defined in HelloWorldDeployment/Top
.
Topologies instantiate all the components in a running system and link them together. For some port types, like the commanding, event, and telemetry ports used by HelloWorld
, the connections are made automatically. In addition, the topology specifies how to construct the component instance. This is also done automatically unless the component has specific configuration.
In order to add a component to the topology, it must be added to the topology model. An instance definition and an instance initializer must both be added.
To add an instance definition, add instance helloWorld
to the instance definition list in the topology HelloWorldDeployment
section of HelloWorldDeployment/Top/topology.fpp
. This is shown below.
In HelloWorldDeployment/Top/topology.fpp, under this section:
topology HelloWorldDeployment {
# ———————————————————————-
# Instances used in the topology
# ———————————————————————-
Add a new instance for your helloWorld component:
instance helloWorld
Be careful to not remove any other instances from the list.
helloWorld
is the name of the component instance. Like variable names, component instance names should be descriptive and are typically named in camel or snake case.
Next, an instance initializer must be added to topology instances defined in MyDeploymment/Top/instances.fpp
file. Since the HelloWorld
component is an active component it should be added to the active
components section and should define a priority and queue depth options. This is shown below.
Add to MyDeploymment/Top/instances.fpp under this section:
# ----------------------------------------------------------------------
# Active component instances
# ----------------------------------------------------------------------
Add a new instance for your helloWorld component:
instance helloWorld: Components.HelloWorld base id 0x0F00 \
queue size Default.QUEUE_SIZE \
stack size Default.STACK_SIZE \
priority 50
The user must ensure that the base id (0x0F00) does not conflict with any other base ids in the topology. 0x0F00 should be safe for deployments created with fprime-util new --deployment
.
Make sure to use the same instance name (i.e. helloWorld) as defined in the instance definition just added to topology.fpp
.
Finally, our new telemetry channel should be added to our telemetry packet specification. For this tutorial the channel can be ignored as the deployment will not use the telemetry packetizer. Add the following to the ignore
section of HelloWorldDeployment/Top/HelloWorldDeploymentPackets.xml
.
Edit HelloWorldDeployment/Top/HelloWorldDeploymentPackets.xml, under this section:
<ignore>
Add the following line:
<channel name="helloWorld.GreetingCount"/>
Since this component has no custom ports nor does it require special configuration, our addition to the topology is completed. The deployment can now be set up and built using the following commands:
# In: MyProject
fprime-util build -j4
Resolve any errors that occur before continuing to the running section.
Running With fprime-gds
It is now time to test the HelloWorld
component by running the deployment created in this section. This can be accomplished by running the fprime-gds
command in the deployment, verifying connection, sending the new SEND_HELLO command and verifying that the Hello
event and GreetingCount
channel appears.
To start the deployment with default settings, run:
fprime-gds
The F´ GDS control page should open up in your web browser. If it does not open up, navigate to http://127.0.0.1:5000.
Once the F´ GDS page is visible, look for a green circle icon in the upper right corner. This shows that the flight software deployment has connected to the GDS system. If a red X appears instead, navigate to the Logs tab and look for errors in the various logs.
Now that communication is verified, navigate to the “Commanding” tab and select helloWorld.SAY_HELLO
from the dropdown list. Type a greeting into the argument input box and click the button “Send Command”. If the argument has been validated successfully the command will send. Resolve all errors and ensure the command has been sent.
Notice commands are instance specific. Had several HelloWorld component instances been used, there would be multiple SAY_HELLO
listings, one for each component instance.
Now that the command has been sent, navigate to the “Events” tab. Ensure that the event list contains the Hello event with the text entered when sending the command.
Lastly, navigate to the “Channels” tab. Look for “helloWorld.GreetingCount” in the channel list. Ensure it has recorded the number of times a helloWorld.SAY_HELLO
was sent.
Congratulations, you have now set up a project, component, and deployment in F´.
Conclusion
This concludes both the adding deployment section of the Hello World tutorial and the tutorial itself. The user has been able to perform the following actions:
- Create a new F´ project
- Create a new F´ components
- Create a new F´ deployment and add components to it