Concepts#

The Restaurant Analogy#

Parasect employs a restaurant analogy to encode its functionality.

When you interact with Parasect, you define a Menu of Meals that Parasect can prepare for you.

The Menu contains multiple Meals. Each Meal represents a distinct parameter set, a configuration that should be unique and reflect a unique unmanned vehicle. The Menu is defined in the meals.yaml file where each Meal is named and represented by a dictionary.

Example meals.yaml file:

snack:
  fruit: single
  header: ~
  footer: ~

breakfast:
  dairy: cereal
  header: ~
  footer: ~

light_meal:
  salad: ~
  meat_and_potatoes: ~
  remove_calibration: True
  remove_operator: True
  header: ~
  footer: ~

spicy_meal:
  salad: ~
  meat_and_potatoes: spicy/extra
  remove_calibration: True
  remove_operator: True
  header: ~
  footer: ~

full_meal:
  salad: ~
  meat_and_potatoes: ~
  bread: baguette
  desert: ~
  header: ~
  footer: full_meal

christmass_at_grandmas:
  parent: full_meal
  salad: village
  extra_quantities: ~
  add_new: True

dangerous_combinations:
  parent: breakfast
  coffee: filter
  add_new: True

The Meal is made up of Dishes. Each Dish represents a notional subset of the autopilot’s parameters, which makes it easier to define and manage. In this case light_meal contains the Dishes salad, meat_and_potatoes, header and footer. The rest of the key-value pairs will be explained later.

Each Dish is defined in a separate file and contains a common Recipe, which specifies which Ingredients make up the Dish, as well as a list of Allergens that should not exist in the Dish.

Furthermore, one or more Dish Variants can be specified in the Dish file, which are specializations of the common Recipe. They define more Ingredients and more Allergens. The Variants can be infinitely nested.

In the Meal dictionary, the Dish names are defined in the dictionary key, while the dictionary value specifies the Dish Variant that should be used for that meal. If no Variant is specified (the value is set to ~, i.e. None) then the common Recipe is used. On the contrary, a value of variant_1/subvariant_a signifies that the Meals needs to be specialized with Variant Recipes.

Example: salad Dish file:

common:
  ingredients:
    - [CUCUMBER, 2, ~]
    - [OIL, 0.5, ~]
    - [SALT, 0.01, ~]
  allergens:
    substances:
      - [VINEGAR, ~, Mom doesn't like it]

variants:
  village:
    common:
      ingredients:
        - [TOMATO, 3, ~]
        - [WHITE_CHEESE, 0.5, ~]

The user is free to create as many Custom Dishes he wants under the custom_dishes folder and then refer to them in meals.yaml. Not all Meals need to refer to all available Dishes. However, there are Staple Dishes that serve special purposes and are defined in the staple_dishes folder; their filenames are significant and should not be altered. Still the user is expected to fill in their content.

Such Dishes are:

  • calibration.yaml: The calibration parameters can be defined there.

  • operator.yaml: The operator parameters can be defined there.

  • header.yaml: The header text of the generated parameter files can be defined there.

  • footer.yaml: The footer text of the generated parameter files can be defined there.

Functional Requirements#

Parasect builds parameter sets while satisfying and enforcing these requirements:

  1. If a Default Parameters set is provided, it will form the basis of the Meal Ingredients. These default parameters are often autogenerated by the autopilot toolchain.

    Why?: It is highly recommended to build upon a default parameters set, because you can thus enforce the default value in all of the parameters you don’t wish to alter.

  2. If you provide a default parameters set, it is an illegal operation to define and set an Ingredient that doesn’t exist in it.

    Why?: This is to catch spelling mistakes in the parameter names. However, this functionality can be disabled to enable specific workflows.

  3. The Variant Recipes should not re-define an Ingredient that their parent Common Recipe already defined.

    Why?: This is to make it easier to trace which part of the Dish file ends up in the Meal. If you need a Dish Variant to alter the value of an Ingredient found in the Common Dish, you can create another Variant and define your Ingredients there.

  4. Each Ingredient should be set at most once across all Dishes:

    Why?: Remember that in the end, the whole Meal is exported as a flat list of parameters. You don’t want the same parameter being defined more than once.

These requirements allow the parameter set generated by Parasect to be idempotent:

  1. You can apply it on your autopilot and be sure that it is configured exactly to your intent.

  2. You can reapply it as many times as you wish, without affecting the existing calibration or the operator configuration.

You can also compare it to the current autopilot parameter set. The calibration and operator parameters can be ignored so only meaningful changes will surface.

It is recommended, but not enforced to:

  1. Define calibration parameters as Ingredients in the calibration.yaml Dish and remove them from the Meal, using the remove_calibration flag.

    Why?: Each vehicle has its own unique calibration. Overwriting this calibration values is not appropriate.

  2. Define operation-related parameters as Ingredients in the operator.yaml Dish and remove them from the Meal, using the remove_operator flag.

    Why?: Each operator should have the freedom to choose the values of certain parameters. Overwriting them is not appropriate.