2021-12-06 22:49:35 -08:00

9.9 KiB

1. Introduction

This tutorial shows how to develop, test, and deploy a simple topology consisting of two components:

  1. MathSender: A component that receives commands and forwards work to MathReceiver.

  2. MathReceiver: A component that carries out arithmetic operations and returns the results to MathSender.

See the diagram below.

A simple topology for arithmetic computation

What is covered: The tutorial covers the following concepts:

  1. Using the FPP modeling language to specify the types and ports used by the components.

  2. Using the F Prime build system to build the types and ports.

  3. Developing the MathSender component: Specifying the component, building the component, completing the C++ component implementation, and writing component unit tests.

  4. Developing the MathReceiver component.

  5. Adding the new components and connections to the F Prime Ref application.

  6. Using the F Prime Ground Data System (GDS) to run the updated Ref application.

Prerequisites: This tutorial assumes the following:

  1. Basic knowledge of Unix: How to navigate in a shell and execute programs.

  2. Basic knowledge of git: How to create a branch.

  3. Basic knowledge of C++, including class declarations, inheritance, and virtual functions.

If you have not yet installed F Prime on your system, do so now. Follow the installation guide at INSTALL.md in the F Prime git repository. You may also wish to work through the Getting Started tutorial at docs/GettingStarted/Tutorial.md.

Git branch: This tutorial is designed to work on the branch release/v3.0.0.

Working on this tutorial will modify some files under version control in the F Prime git repository. Therefore it is a good idea to do this work on a new branch. For example:

git checkout release/v3.0.0
git checkout -b math-tutorial

If you wish, you can save your work by committing to this branch.

2. The MathOp Type

In F Prime, a type definition defines a kind of data that you can pass between components or use in commands and telemetry.

For this tutorial, we need one type definition. It defines an enumeration called MathOp, which represents a mathematical operation.

We will add the specification for the MathOp type to the Ref topology. We will do this in three stages:

  1. Construct the FPP model.

  2. Add the model to the project.

  3. Build the model.

2.1. Construct the FPP Model

Create the MathTypes directory: Go to the directory Ref at the top-level of the F Prime repository and run mkdir MathTypes. This step creates a new directory Ref/MathTypes. This directory will contain our new type.

Create the FPP model file: Now go into the directory Ref/MathTypes. In that directory, create a file MathTypes.fpp with the following contents:

module Ref {

  @ A math operation
  enum MathOp {
    ADD @< Addition
    SUB @< Subtraction
    MUL @< Multiplication
    DIV @< Division
  }

}

You can do this by typing, or by copy-paste.

This file defines an enumeration or enum with enumerated constants ADD, SUB, MUL, and DIV. These four constants represent the operations of addition, subtraction, multiplication, and division. The enum also defines a type MathOp; the enumerated constants are the values of this type. For more information on enums, see The FPP User's Guide.

The enum MathTypes resides in an FPP module Ref.

An FPP module is like a C++ namespace: it encloses several definitions, each of which is qualified with the name of the module. For more information on FPP modules, see The FPP User's Guide.

The text following a symbol @ or @< is called an annotation. These annotations are carried through the parsing and become comments in the generated code. For more information, see The FPP User's Guide.

2.2. Add the Model to the Project

Create Ref/MathTypes/CMakeLists.txt: Create a file Ref/MathTypes/CMakeLists.txt with the following contents:

set(SOURCE_FILES
  "${CMAKE_CURRENT_LIST_DIR}/MathTypes.fpp"
)

register_fprime_module()

This code will tell the build system how to build the FPP model.

Update Ref/CMakeLists.txt: Now we need to add the new directory to the Ref project. To do that, open the file Ref/CMakeLists.txt. This file should already exist; it was put there by the developers of the Ref topology. In this file, you should see several lines starting with add_fprime_subdirectory. Immediately after the last of those lines, add the following new line:

add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/MathTypes/")

2.3. Build the Model

Run the build: Do the following:

  1. Go to the directory Ref/MathTypes.

  2. If you have not already run fprime-util generate, then do so now.

  3. Run the command fprime-util build.

The output should indicate that the model built without any errors. If not, try to identify and correct what is wrong, either by deciphering the error output, or by going over the steps again. If you get stuck, you can look at the reference implementation.

Inspect the generated code: Now go to the directory Ref/build-fprime-automatic-native/Ref/MathTypes (you may want to use pushd, or do this in a separate shell, so you don't lose your current working directory). The directory build-fprime-automatic-native is where all the generated code lives for the "automatic native" build of the Ref project. Within that directory is a directory tree that mirrors the project structure. In particular, Ref/build-fprime-automatic-native/Ref/MathTypes contains the generated code for Ref/MathTypes.

Run ls. You should see something like this:

CMakeFiles            MathOpEnumAc.cpp      MathOpEnumAi.xml.prev cmake_install.cmake
Makefile              MathOpEnumAc.hpp      autocoder

The files MathOpEnumAc.hpp and MathOpEnumAc.cpp are the auto-generated C++ files corresponding to the MathOp enum. You may wish to study the file MathOpEnumAc.hpp. This file gives the interface to the C++ class Ref::MathOp. All enum types have a similar auto-generated class interface.

2.4. Reference Implementation

A reference implementation for this section is available at docs/Tutorials/MathComponent/MathTypes. To build this implementation from a clean repository, do the following:

  1. Go to the Ref directory.

  2. Run cp -R ../docs/Tutorials/MathComponent/MathTypes .

  3. Update Ref/CMakeLists.txt as stated above.

  4. Follow the steps for building the model.

If you have modified the repo, revise the steps accordingly. For example, switch git branches, use git stash to stash your changes, or move MathTypes to another directory such as MathTypes-saved.

3. The MathOp and MathResult Ports

A port is the endpoint of a connection between two components. A port definition is like a function signature; it defines the type of the data carried on a port.

For this tutorial, we need two port definitions:

  • MathOp for sending an arithmetic operation request from MathSender to MathReceiver.

  • MathResult for sending the result of an arithmetic operation from MathReceiver to MathSender.

We follow the same three steps as in the previous section.

3.1. Construct the FPP Model

Create the MathPorts directory: Go to the directory Ref at the top-level of the F Prime repository and run mkdir MathPorts. This directory will contain our new ports.

Create the FPP model file: Now go into the directory Ref/MathPorts. Create a file MathPorts.fpp with the following contents:

module Ref {

  @ Port for requesting an operation on two numbers
  port MathOp(
               val1: F32 @< The first operand
               op: MathOp @< The operation
               val2: F32 @< The second operand
             )

  @ Port for returning the result of a math operation
  port MathResult(
                   result: F32 @< the result of the operation
                 )

}

This file defines the ports MathOp and MathResult. MathOp has three formal parameters: a first operand, an operation, and a second operand. The operands have type F32, which represents a 32-bit floating-point number. The operation has type MathOp, which is the enum type we defined in the previous section. MathResult has a single formal parameter, the value of type F32 returned as the result of the operation.

For more information about port definitions, see The FPP User's Guide.

3.2. Add the Model to the Project

Add add the model Ref/MathPorts/MathPorts.fpp to the Ref project. Carry out the steps in the previous section, after substituting MathPorts for MathTypes.

3.3. Build the Model

Carry out the steps in the previous section, in directory MathPorts instead of MathTypes. The generated code will go in Ref/build-fprime-automatic-native/Ref/MathPorts. For port definitions, the names of the auto-generated C++ files end in PortAc.hpp and PortAc.cpp. You can look at this code if you wish. However, the auto-generated C++ port files are used by the autocoded component implementations (described below); you won't ever program directly against their interfaces.

3.4. Reference Implementation

A reference implementation for this section is available at docs/Tutorials/MathComponent/MathPorts. To build this implementation, follow the steps described for MathTypes.