View on GitHub

Flight Software & Embedded Systems Framework

Hello World Tutorial

Introduction and F´ Terminology

The Hello World tutorial is designed to teach new users the basics of F´ usage, instruct existing users on new command that help in F´ development, and act as the canonical “Hello World” example for F´.

[!TIP] The source for this tutorial is located here: https://github.com/fprime-community/fprime-tutorial-hello-world. If you are stuck at some point during the tutorial, you may refer to that reference as the “solution”.

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_HELLO command, 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 containing 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.


1. Creating an F´ Project

This section will walk you through creating a new F´ project. First, ensure you meet the F´ System Requirements.

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

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:

  1. 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 others
  2. settings.ini: allows users to set various settings to control the build
  3. CMakeList.txt and project.cmake: CMake files defining the build system
  4. Components/: directory to place user components in
  5. fprime-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

[!TIP] 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

[!NOTE] fprime-util generate sets up the build environment for a project/deployment. It only needs to be done once.

[!NOTE] 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

Project creation recap

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
. fprime-venv/bin/activate

[!NOTE] Use this command if your virtual environment is not already running.


2. Creating an F´ Hello World Component

This section will walk new users through creating a basic F´ component. Rember that you need a shell that has activated the virtual environment above.

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, which are covered in-depth in the MathComponent tutorial.

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 behaviour:

  1. A command called SAY_HELLO that will command the component to send a greeting
  2. An event called Hello that is the greeting sent in response to the SAY_HELLO command
  3. A telemetry channel called GreetingCount that will count each Hello 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

[!NOTE] 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:

  1. HelloWorld.fpp: design model for the component
  2. HelloWorld.hpp and HelloWorld.cpp: C++ implementation files for the component, currently empty.
  3. CMakeList.txt: build definitions for the component.
  4. docs folder to place component documentation

To build this component run fprime-util build in the current folder.

[!NOTE] 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 and replace the 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

[!NOTE] You should ensure to 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.template.hpp and HelloWorld.template.cpp 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 for implementing 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 is done by adding the following code inside the class definition in HelloWorld.hpp:

HelloWorld.hpp: Adding New Member Variable

PRIVATE:
    U32 m_greetingCount = 0;

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.


3. Integration and Testing with the HelloWorld Deployment

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 above 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

[!NOTE] 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.

Edit HelloWorldDeployment/Top/topology.fpp:

...
    topology HelloWorldDeployment {
        # ----------------------------------------------------------------------
        # Instances used in the topology
        # ----------------------------------------------------------------------
        
        instance ...
        instance ...
        instance helloWorld

[!WARNING] ... are placeholders for other component names - do not remove or modify 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:


  # ----------------------------------------------------------------------
  # Active component instances
  # ----------------------------------------------------------------------

  instance helloWorld: Components.HelloWorld base id 0x0F00 \
    queue size Default.QUEUE_SIZE \
    stack size Default.STACK_SIZE \
    priority 50

[!NOTE] 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.

[!NOTE] Make sure to use the same instance name (i.e. helloWorld) as defined in the instance definition just added to topology.fpp.

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/HelloWorldDeployment
fprime-util build -j4

[!WARNING] 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 validated successfully the command will send. Resolve all errors and ensure the command has sent.

[!NOTE] 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 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.

Conclusion

Congratulations, you have now set up a project, component, and deployment in F´, and ran the Flight Software application as well as control it through the F´ GDS!

This concludes the HelloWorld tutorial.