Stanzas

Reference for OctoMY™ stanzas, which define logical groupings of lobes, actuators, and sensors that configure an agent for specific behavior modes.

Heads up — type names

Since Phase 1 of the unified-firmware-system rework, the canonical type names are FixoStanza, FixoLobe, FixoActuator, FixoSensor, and FixoMapping (the old StanzaBook + bare Stanza types are gone). Stanza sets — groups of mutually-exclusive stanzas derived automatically from actuator overlap — are first-class via FixoPreset::computeStanzaSets(). The new ground-truth references are Fixo Data Model and Stanza Templates; this page describes the conceptual model that survives across both worlds.

Pro Tip

Think of stanzas as "modes" for your robot. A quadruped might have a "walking" stanza that links all leg servos to a gait lobe, and an "interaction" stanza that gives fine control of front legs for manipulating objects while the back legs maintain balance. Switching stanzas inside the same set is instant; switching across sets requires picking the new set first because two stanzas that share an actuator can't run together.


What is a Stanza?

A stanza is a logical constellation of lobes, actuators, and sensors that makes an agent act in a certain way. Stanzas enable mode-switching, allowing a single robot to be reconfigured for different operational modes without physical changes.

Stanza System


Key concepts

Exclusive actuator control

Each actuator can only be controlled by one lobe at a time. When switching stanzas, the control of actuators transfers from one lobe configuration to another.

Stanza Actuators Controlled Lobe Type
Walking All leg servos Gait Lobe
Interaction Front two legs Fine Control Lobe
Driving Throttle + steering Wheeled Lobe

Mode switching

Stanzas allow users to quickly switch between operational "modes":


Stanza structure

StanzaBook

A collection of stanzas configured for an agent:

class StanzaBook {
public:
    // Stanza management
    void addStanza(const Stanza& stanza);
    void removeStanza(const QString& name);
    Stanza* stanza(const QString& name);

    // Active stanza
    void setActive(const QString& name);
    Stanza* active();

    // Serialization
    QByteArray serialize() const;
    bool deserialize(const QByteArray& data);
};

Stanza definition

struct Stanza {
    QString name;                    // Stanza identifier
    QString description;             // Human-readable description
    QMap<QString, LobeConfig> lobes; // Lobes in this stanza
    QMap<QString, QString> mapping;  // Actuator-to-lobe mappings
};

Configuration format

JSON configuration

{
  "stanzas": [
    {
      "name": "walking",
      "description": "Quadruped walking mode",
      "lobes": [
        {
          "name": "gait",
          "type": "walking",
          "config": {
            "gaitStyle": "crawl",
            "stepHeight": 30,
            "cycleTime": 1000
          }
        }
      ],
      "mapping": {
        "leg_fl_hip": "gait",
        "leg_fl_knee": "gait",
        "leg_fr_hip": "gait",
        "leg_fr_knee": "gait",
        "leg_bl_hip": "gait",
        "leg_bl_knee": "gait",
        "leg_br_hip": "gait",
        "leg_br_knee": "gait"
      }
    },
    {
      "name": "interaction",
      "description": "Fine control of front limbs",
      "lobes": [
        {
          "name": "fine_control",
          "type": "manipulator",
          "config": {
            "precision": "high",
            "feedback": true
          }
        },
        {
          "name": "balance",
          "type": "static_balance",
          "config": {}
        }
      ],
      "mapping": {
        "leg_fl_hip": "fine_control",
        "leg_fl_knee": "fine_control",
        "leg_fr_hip": "fine_control",
        "leg_fr_knee": "fine_control",
        "leg_bl_hip": "balance",
        "leg_bl_knee": "balance",
        "leg_br_hip": "balance",
        "leg_br_knee": "balance"
      }
    }
  ]
}

Legged robot example

Consider a quadruped robot with two operational modes:

Walking stanza

Walking Stanza

The walking stanza:

Interaction stanza

Interaction Stanza

The interaction stanza:


Wheeled robot example

For a wheeled robot like the Traxxas example:

{
  "stanzas": [
    {
      "name": "driving",
      "description": "Standard driving mode",
      "lobes": [
        {
          "name": "wheeled",
          "type": "wheeled_locomotion",
          "config": {
            "steeringStyle": "ackermann"
          }
        }
      ],
      "mapping": {
        "throttle": "wheeled",
        "steering": "wheeled"
      }
    }
  ]
}

Actuator mapping

Name-based mapping

Actuators and lobes are connected via name mappings:

// Mapping format: actuator_name -> lobe_name
QMap<QString, QString> mapping;
mapping["throttle"] = "wheeled";
mapping["steering"] = "wheeled";
mapping["pan_servo"] = "camera";
mapping["tilt_servo"] = "camera";

Auto-mapping

The mapping editor provides an automap feature:


Stanza operations

Switching stanzas

// Switch to a different stanza
stanzaBook->setActive("interaction");

// Get current stanza
Stanza* current = stanzaBook->active();
qDebug() << "Current mode:" << current->name;

From OPAL plans

// Switch stanza in a Plan
stanza.switch("walking")

// Query current stanza
if stanza.current == "interaction" {
    stanza.switch("walking")
}

Relationship to other concepts

Stanzas and lobes

Stanzas and plans

// Plan that switches stanzas based on situation
if proximity.obstacle_detected {
    stanza.switch("interaction")
    manipulator.poke()
} else {
    stanza.switch("walking")
    locomotion.move_forward()
}