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, andFixoMapping(the oldStanzaBook+ bareStanzatypes are gone). Stanza sets — groups of mutually-exclusive stanzas derived automatically from actuator overlap — are first-class viaFixoPreset::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.
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.
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 |
Stanzas allow users to quickly switch between operational "modes":
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);
};
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
};
{
"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"
}
}
]
}
Consider a quadruped robot with two operational modes:
The walking stanza:
The interaction stanza:
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"
}
}
]
}
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";
The mapping editor provides an automap feature:
// Switch to a different stanza
stanzaBook->setActive("interaction");
// Get current stanza
Stanza* current = stanzaBook->active();
qDebug() << "Current mode:" << current->name;
// Switch stanza in a Plan
stanza.switch("walking")
// Query current stanza
if stanza.current == "interaction" {
stanza.switch("walking")
}
// Plan that switches stanzas based on situation
if proximity.obstacle_detected {
stanza.switch("interaction")
manipulator.poke()
} else {
stanza.switch("walking")
locomotion.move_forward()
}