lanyard.flight.ControlSurfaces.1.0¶
Post-mixer actuator commands, discriminated by airframe class.
| Full name | lanyard.flight.ControlSurfaces |
| Version | 1.0 |
| Kind | Message |
| Fixed port ID | 6212 |
| Least supported transport | CAN FD |
Wire layout¶
| Section | Extent (bytes) | Max serialized (bytes) |
|---|---|---|
| Message | 64 | 26 |
A sealed type reports its extent as its exact serialized size; a delimited type reports the declared @extent, which bounds what a reader must be prepared to receive.
Definition¶
# Post-mixer actuator commands, discriminated by airframe class.
#
# LEAST SUPPORTED TRANSPORT: CAN FD.
#
# WHY A UNION: the three airframe classes in the fleet need disjoint
# actuator sets, and a message that carried all of them would waste
# bandwidth on every flight and would leave a receiver guessing which
# half of the payload is meaningful. A @union serializes a tag plus
# exactly one option, so the wire cost is that of the selected variant
# rather than the sum of all three.
#
# A union's fields are options, not members: exactly one is present in
# any given value. The tag is implicit in the definition and is emitted
# ahead of the selected option.
#
# WHAT THE GENERATED CODE LOOKS LIKE: this is the one construct whose
# rendering genuinely differs between backends, so it is worth comparing
# them side by side in the showroom.
#
# - C, C++, Rust, and Go emit a plain aggregate holding all three
# options at once, plus a tag field naming the active one. It needs
# no allocation and its layout does not depend on which option is
# set, but the aggregate is as large as its largest option and
# reading the wrong one is a runtime mistake, not a compile-time
# one: consumers must branch on the tag first.
# - Python emits the same shape with the inactive options typed as
# None, so an unset option at least reads as absent rather than as a
# zeroed value.
# - TypeScript emits a true discriminated union -- three object types
# joined by `|`, each carrying its own `_tag` literal -- so the
# compiler refuses to let you read an option you have not narrowed
# to.
#
# None of this changes the wire format, which is a tag followed by the
# selected option in every case.
@union
lanyard.flight.MultirotorMix.1.0 multirotor
# Selected for quadrotor, hexrotor, and coaxial airframes.
lanyard.flight.FixedWingSurfaces.1.0 fixed_wing
# Selected for conventional and flying-wing airframes.
lanyard.flight.MultirotorMix.1.0 vtol_hover
# Selected for the hover phase of a VTOL transition. Structurally
# identical to the multirotor option but semantically distinct: a
# receiver uses the tag to decide whether the forward-flight surfaces
# should be held at their transition schedule or released to the
# autopilot.
@extent 64 * 8
Generated code¶
Declaration excerpts only -- the serialization bodies are omitted for length. Build the showroom target for the complete output in every language and profile.
C¶
/* Post-mixer actuator commands, discriminated by airframe class. */
/* */
/* LEAST SUPPORTED TRANSPORT: CAN FD. */
/* */
/* WHY A UNION: the three airframe classes in the fleet need disjoint */
/* actuator sets, and a message that carried all of them would waste */
/* bandwidth on every flight and would leave a receiver guessing which */
/* half of the payload is meaningful. A @union serializes a tag plus */
/* exactly one option, so the wire cost is that of the selected variant */
/* rather than the sum of all three. */
/* */
/* A union's fields are options, not members: exactly one is present in */
/* any given value. The tag is implicit in the definition and is emitted */
/* ahead of the selected option. */
/* */
/* WHAT THE GENERATED CODE LOOKS LIKE: this is the one construct whose */
/* rendering genuinely differs between backends, so it is worth comparing */
/* them side by side in the showroom. */
/* */
/* - C, C++, Rust, and Go emit a plain aggregate holding all three */
/* options at once, plus a tag field naming the active one. It needs */
/* no allocation and its layout does not depend on which option is */
/* set, but the aggregate is as large as its largest option and */
/* reading the wrong one is a runtime mistake, not a compile-time */
/* one: consumers must branch on the tag first. */
/* - Python emits the same shape with the inactive options typed as */
/* None, so an unset option at least reads as absent rather than as a */
/* zeroed value. */
/* - TypeScript emits a true discriminated union -- three object types */
/* joined by `|`, each carrying its own `_tag` literal -- so the */
/* compiler refuses to let you read an option you have not narrowed */
/* to. */
/* */
/* None of this changes the wire format, which is a tag followed by the */
/* selected option in every case. */
typedef struct lanyard__flight__ControlSurfaces {
/* Selected for quadrotor, hexrotor, and coaxial airframes. */
lanyard__flight__MultirotorMix multirotor;
/* Selected for conventional and flying-wing airframes. */
lanyard__flight__FixedWingSurfaces fixed_wing;
/* Selected for the hover phase of a VTOL transition. Structurally */
/* identical to the multirotor option but semantically distinct: a */
/* receiver uses the tag to decide whether the forward-flight surfaces */
/* should be held at their transition schedule or released to the */
/* autopilot. */
lanyard__flight__MultirotorMix vtol_hover;
uint8_t _tag_;
} lanyard__flight__ControlSurfaces;
C++ (std)¶
// Post-mixer actuator commands, discriminated by airframe class.
//
// LEAST SUPPORTED TRANSPORT: CAN FD.
//
// WHY A UNION: the three airframe classes in the fleet need disjoint
// actuator sets, and a message that carried all of them would waste
// bandwidth on every flight and would leave a receiver guessing which
// half of the payload is meaningful. A @union serializes a tag plus
// exactly one option, so the wire cost is that of the selected variant
// rather than the sum of all three.
//
// A union's fields are options, not members: exactly one is present in
// any given value. The tag is implicit in the definition and is emitted
// ahead of the selected option.
//
// WHAT THE GENERATED CODE LOOKS LIKE: this is the one construct whose
// rendering genuinely differs between backends, so it is worth comparing
// them side by side in the showroom.
//
// - C, C++, Rust, and Go emit a plain aggregate holding all three
// options at once, plus a tag field naming the active one. It needs
// no allocation and its layout does not depend on which option is
// set, but the aggregate is as large as its largest option and
// reading the wrong one is a runtime mistake, not a compile-time
// one: consumers must branch on the tag first.
// - Python emits the same shape with the inactive options typed as
// None, so an unset option at least reads as absent rather than as a
// zeroed value.
// - TypeScript emits a true discriminated union -- three object types
// joined by `|`, each carrying its own `_tag` literal -- so the
// compiler refuses to let you read an option you have not narrowed
// to.
//
// None of this changes the wire format, which is a tag followed by the
// selected option in every case.
struct ControlSurfaces {
// Selected for quadrotor, hexrotor, and coaxial airframes.
::lanyard::flight::MultirotorMix multirotor{};
// Selected for conventional and flying-wing airframes.
::lanyard::flight::FixedWingSurfaces fixed_wing{};
// Selected for the hover phase of a VTOL transition. Structurally
// identical to the multirotor option but semantically distinct: a
// receiver uses the tag to decide whether the forward-flight surfaces
// should be held at their transition schedule or released to the
// autopilot.
::lanyard::flight::MultirotorMix vtol_hover{};
std::uint8_t _tag_{0U};
static constexpr const char* FULL_NAME = "lanyard.flight.ControlSurfaces";
static constexpr bool IS_DEPRECATED = false;
static constexpr const char* FULL_NAME_AND_VERSION = "lanyard.flight.ControlSurfaces.1.0";
static constexpr std::size_t EXTENT_BYTES = 64U;
static constexpr std::size_t SERIALIZATION_BUFFER_SIZE_BYTES = 26U;
static constexpr bool ZOH_ALIAS_ELIGIBLE = false;
static constexpr const char* ZOH_ALIAS_REASON = "invalid-bit-length";
static constexpr std::size_t UNION_OPTION_COUNT = 3U;
LLVMDSDL_NODISCARD inline std::int8_t serialize(std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes) const {
return ControlSurfaces__serialize_(this, buffer, inout_buffer_size_bytes);
}
LLVMDSDL_NODISCARD inline std::int8_t deserialize(const std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes) {
return ControlSurfaces__deserialize_(this, buffer, inout_buffer_size_bytes);
}
LLVMDSDL_NODISCARD static inline std::int8_t try_deserialize_view(const std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes, const std::uint8_t** out_view_bytes) {
return ControlSurfaces__try_deserialize_view_(buffer, inout_buffer_size_bytes, out_view_bytes);
}
LLVMDSDL_NODISCARD static inline std::int8_t try_serialize_view(const std::uint8_t* view_bytes, std::size_t view_size_bytes, std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes) {
return ControlSurfaces__try_serialize_view_(view_bytes, view_size_bytes, buffer, inout_buffer_size_bytes);
}
};
C++ (pmr)¶
Polymorphic-allocator profile: variable-length fields route through std::pmr.
// Post-mixer actuator commands, discriminated by airframe class.
//
// LEAST SUPPORTED TRANSPORT: CAN FD.
//
// WHY A UNION: the three airframe classes in the fleet need disjoint
// actuator sets, and a message that carried all of them would waste
// bandwidth on every flight and would leave a receiver guessing which
// half of the payload is meaningful. A @union serializes a tag plus
// exactly one option, so the wire cost is that of the selected variant
// rather than the sum of all three.
//
// A union's fields are options, not members: exactly one is present in
// any given value. The tag is implicit in the definition and is emitted
// ahead of the selected option.
//
// WHAT THE GENERATED CODE LOOKS LIKE: this is the one construct whose
// rendering genuinely differs between backends, so it is worth comparing
// them side by side in the showroom.
//
// - C, C++, Rust, and Go emit a plain aggregate holding all three
// options at once, plus a tag field naming the active one. It needs
// no allocation and its layout does not depend on which option is
// set, but the aggregate is as large as its largest option and
// reading the wrong one is a runtime mistake, not a compile-time
// one: consumers must branch on the tag first.
// - Python emits the same shape with the inactive options typed as
// None, so an unset option at least reads as absent rather than as a
// zeroed value.
// - TypeScript emits a true discriminated union -- three object types
// joined by `|`, each carrying its own `_tag` literal -- so the
// compiler refuses to let you read an option you have not narrowed
// to.
//
// None of this changes the wire format, which is a tag followed by the
// selected option in every case.
struct ControlSurfaces {
// Selected for quadrotor, hexrotor, and coaxial airframes.
::lanyard::flight::MultirotorMix multirotor{};
// Selected for conventional and flying-wing airframes.
::lanyard::flight::FixedWingSurfaces fixed_wing{};
// Selected for the hover phase of a VTOL transition. Structurally
// identical to the multirotor option but semantically distinct: a
// receiver uses the tag to decide whether the forward-flight surfaces
// should be held at their transition schedule or released to the
// autopilot.
::lanyard::flight::MultirotorMix vtol_hover{};
std::uint8_t _tag_{0U};
::llvmdsdl::cpp::MemoryResource* _memory_resource{::llvmdsdl::cpp::default_memory_resource()};
ControlSurfaces() = default;
explicit ControlSurfaces(::llvmdsdl::cpp::MemoryResource* memory_resource) { set_memory_resource(memory_resource); }
void set_memory_resource(::llvmdsdl::cpp::MemoryResource* memory_resource) {
_memory_resource = (memory_resource != nullptr) ? memory_resource : ::llvmdsdl::cpp::default_memory_resource();
multirotor.set_memory_resource(_memory_resource);
fixed_wing.set_memory_resource(_memory_resource);
vtol_hover.set_memory_resource(_memory_resource);
}
static constexpr const char* FULL_NAME = "lanyard.flight.ControlSurfaces";
static constexpr bool IS_DEPRECATED = false;
static constexpr const char* FULL_NAME_AND_VERSION = "lanyard.flight.ControlSurfaces.1.0";
static constexpr std::size_t EXTENT_BYTES = 64U;
static constexpr std::size_t SERIALIZATION_BUFFER_SIZE_BYTES = 26U;
static constexpr bool ZOH_ALIAS_ELIGIBLE = false;
static constexpr const char* ZOH_ALIAS_REASON = "invalid-bit-length";
static constexpr std::size_t UNION_OPTION_COUNT = 3U;
LLVMDSDL_NODISCARD inline std::int8_t serialize(std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes) const {
return ControlSurfaces__serialize_(this, buffer, inout_buffer_size_bytes, _memory_resource);
}
LLVMDSDL_NODISCARD inline std::int8_t deserialize(const std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes) {
return ControlSurfaces__deserialize_(this, buffer, inout_buffer_size_bytes, _memory_resource);
}
LLVMDSDL_NODISCARD static inline std::int8_t try_deserialize_view(const std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes, const std::uint8_t** out_view_bytes) {
return ControlSurfaces__try_deserialize_view_(buffer, inout_buffer_size_bytes, out_view_bytes);
}
LLVMDSDL_NODISCARD static inline std::int8_t try_serialize_view(const std::uint8_t* view_bytes, std::size_t view_size_bytes, std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes) {
return ControlSurfaces__try_serialize_view_(view_bytes, view_size_bytes, buffer, inout_buffer_size_bytes);
}
LLVMDSDL_NODISCARD inline std::int8_t serialize(std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes, ::llvmdsdl::cpp::MemoryResource* memory_resource) const {
return ControlSurfaces__serialize_(this, buffer, inout_buffer_size_bytes, memory_resource);
}
LLVMDSDL_NODISCARD inline std::int8_t deserialize(const std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes, ::llvmdsdl::cpp::MemoryResource* memory_resource) {
return ControlSurfaces__deserialize_(this, buffer, inout_buffer_size_bytes, memory_resource);
}
};
C++ (autosar)¶
AUTOSAR C++14 subset profile.
// Post-mixer actuator commands, discriminated by airframe class.
//
// LEAST SUPPORTED TRANSPORT: CAN FD.
//
// WHY A UNION: the three airframe classes in the fleet need disjoint
// actuator sets, and a message that carried all of them would waste
// bandwidth on every flight and would leave a receiver guessing which
// half of the payload is meaningful. A @union serializes a tag plus
// exactly one option, so the wire cost is that of the selected variant
// rather than the sum of all three.
//
// A union's fields are options, not members: exactly one is present in
// any given value. The tag is implicit in the definition and is emitted
// ahead of the selected option.
//
// WHAT THE GENERATED CODE LOOKS LIKE: this is the one construct whose
// rendering genuinely differs between backends, so it is worth comparing
// them side by side in the showroom.
//
// - C, C++, Rust, and Go emit a plain aggregate holding all three
// options at once, plus a tag field naming the active one. It needs
// no allocation and its layout does not depend on which option is
// set, but the aggregate is as large as its largest option and
// reading the wrong one is a runtime mistake, not a compile-time
// one: consumers must branch on the tag first.
// - Python emits the same shape with the inactive options typed as
// None, so an unset option at least reads as absent rather than as a
// zeroed value.
// - TypeScript emits a true discriminated union -- three object types
// joined by `|`, each carrying its own `_tag` literal -- so the
// compiler refuses to let you read an option you have not narrowed
// to.
//
// None of this changes the wire format, which is a tag followed by the
// selected option in every case.
struct ControlSurfaces {
// Selected for quadrotor, hexrotor, and coaxial airframes.
::lanyard::flight::MultirotorMix multirotor{};
// Selected for conventional and flying-wing airframes.
::lanyard::flight::FixedWingSurfaces fixed_wing{};
// Selected for the hover phase of a VTOL transition. Structurally
// identical to the multirotor option but semantically distinct: a
// receiver uses the tag to decide whether the forward-flight surfaces
// should be held at their transition schedule or released to the
// autopilot.
::lanyard::flight::MultirotorMix vtol_hover{};
std::uint8_t _tag_{0U};
static constexpr const char* FULL_NAME = "lanyard.flight.ControlSurfaces";
static constexpr bool IS_DEPRECATED = false;
static constexpr const char* FULL_NAME_AND_VERSION = "lanyard.flight.ControlSurfaces.1.0";
static constexpr std::size_t EXTENT_BYTES = 64U;
static constexpr std::size_t SERIALIZATION_BUFFER_SIZE_BYTES = 26U;
static constexpr bool ZOH_ALIAS_ELIGIBLE = false;
static constexpr const char* ZOH_ALIAS_REASON = "invalid-bit-length";
static constexpr std::size_t UNION_OPTION_COUNT = 3U;
LLVMDSDL_NODISCARD inline std::int8_t serialize(std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes) const {
return ControlSurfaces__serialize_(this, buffer, inout_buffer_size_bytes);
}
LLVMDSDL_NODISCARD inline std::int8_t deserialize(const std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes) {
return ControlSurfaces__deserialize_(this, buffer, inout_buffer_size_bytes);
}
LLVMDSDL_NODISCARD static inline std::int8_t try_deserialize_view(const std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes, const std::uint8_t** out_view_bytes) {
return ControlSurfaces__try_deserialize_view_(buffer, inout_buffer_size_bytes, out_view_bytes);
}
LLVMDSDL_NODISCARD static inline std::int8_t try_serialize_view(const std::uint8_t* view_bytes, std::size_t view_size_bytes, std::uint8_t* buffer, std::size_t* inout_buffer_size_bytes) {
return ControlSurfaces__try_serialize_view_(view_bytes, view_size_bytes, buffer, inout_buffer_size_bytes);
}
};
Rust (std)¶
/// Post-mixer actuator commands, discriminated by airframe class.
///
/// LEAST SUPPORTED TRANSPORT: CAN FD.
///
/// WHY A UNION: the three airframe classes in the fleet need disjoint
/// actuator sets, and a message that carried all of them would waste
/// bandwidth on every flight and would leave a receiver guessing which
/// half of the payload is meaningful. A @union serializes a tag plus
/// exactly one option, so the wire cost is that of the selected variant
/// rather than the sum of all three.
///
/// A union's fields are options, not members: exactly one is present in
/// any given value. The tag is implicit in the definition and is emitted
/// ahead of the selected option.
///
/// WHAT THE GENERATED CODE LOOKS LIKE: this is the one construct whose
/// rendering genuinely differs between backends, so it is worth comparing
/// them side by side in the showroom.
///
/// - C, C++, Rust, and Go emit a plain aggregate holding all three
/// options at once, plus a tag field naming the active one. It needs
/// no allocation and its layout does not depend on which option is
/// set, but the aggregate is as large as its largest option and
/// reading the wrong one is a runtime mistake, not a compile-time
/// one: consumers must branch on the tag first.
/// - Python emits the same shape with the inactive options typed as
/// None, so an unset option at least reads as absent rather than as a
/// zeroed value.
/// - TypeScript emits a true discriminated union -- three object types
/// joined by `|`, each carrying its own `_tag` literal -- so the
/// compiler refuses to let you read an option you have not narrowed
/// to.
///
/// None of this changes the wire format, which is a tag followed by the
/// selected option in every case.
#[derive(Clone, Debug, PartialEq)]
pub struct lanyard_flight_ControlSurfaces_1_0 {
/// Selected for quadrotor, hexrotor, and coaxial airframes.
pub multirotor: lanyard_flight_MultirotorMix_1_0,
/// Selected for conventional and flying-wing airframes.
pub fixed_wing: lanyard_flight_FixedWingSurfaces_1_0,
/// Selected for the hover phase of a VTOL transition. Structurally
/// identical to the multirotor option but semantically distinct: a
/// receiver uses the tag to decide whether the forward-flight surfaces
/// should be held at their transition schedule or released to the
/// autopilot.
pub vtol_hover: lanyard_flight_MultirotorMix_1_0,
pub _tag_: u8,
}
Rust (no-std)¶
no_std + alloc profile, as a flight-controller firmware build would use.
/// Post-mixer actuator commands, discriminated by airframe class.
///
/// LEAST SUPPORTED TRANSPORT: CAN FD.
///
/// WHY A UNION: the three airframe classes in the fleet need disjoint
/// actuator sets, and a message that carried all of them would waste
/// bandwidth on every flight and would leave a receiver guessing which
/// half of the payload is meaningful. A @union serializes a tag plus
/// exactly one option, so the wire cost is that of the selected variant
/// rather than the sum of all three.
///
/// A union's fields are options, not members: exactly one is present in
/// any given value. The tag is implicit in the definition and is emitted
/// ahead of the selected option.
///
/// WHAT THE GENERATED CODE LOOKS LIKE: this is the one construct whose
/// rendering genuinely differs between backends, so it is worth comparing
/// them side by side in the showroom.
///
/// - C, C++, Rust, and Go emit a plain aggregate holding all three
/// options at once, plus a tag field naming the active one. It needs
/// no allocation and its layout does not depend on which option is
/// set, but the aggregate is as large as its largest option and
/// reading the wrong one is a runtime mistake, not a compile-time
/// one: consumers must branch on the tag first.
/// - Python emits the same shape with the inactive options typed as
/// None, so an unset option at least reads as absent rather than as a
/// zeroed value.
/// - TypeScript emits a true discriminated union -- three object types
/// joined by `|`, each carrying its own `_tag` literal -- so the
/// compiler refuses to let you read an option you have not narrowed
/// to.
///
/// None of this changes the wire format, which is a tag followed by the
/// selected option in every case.
#[derive(Clone, Debug, PartialEq)]
pub struct lanyard_flight_ControlSurfaces_1_0 {
/// Selected for quadrotor, hexrotor, and coaxial airframes.
pub multirotor: lanyard_flight_MultirotorMix_1_0,
/// Selected for conventional and flying-wing airframes.
pub fixed_wing: lanyard_flight_FixedWingSurfaces_1_0,
/// Selected for the hover phase of a VTOL transition. Structurally
/// identical to the multirotor option but semantically distinct: a
/// receiver uses the tag to decide whether the forward-flight surfaces
/// should be held at their transition schedule or released to the
/// autopilot.
pub vtol_hover: lanyard_flight_MultirotorMix_1_0,
pub _tag_: u8,
}
Go¶
// Post-mixer actuator commands, discriminated by airframe class.
//
// LEAST SUPPORTED TRANSPORT: CAN FD.
//
// WHY A UNION: the three airframe classes in the fleet need disjoint
// actuator sets, and a message that carried all of them would waste
// bandwidth on every flight and would leave a receiver guessing which
// half of the payload is meaningful. A @union serializes a tag plus
// exactly one option, so the wire cost is that of the selected variant
// rather than the sum of all three.
//
// A union's fields are options, not members: exactly one is present in
// any given value. The tag is implicit in the definition and is emitted
// ahead of the selected option.
//
// WHAT THE GENERATED CODE LOOKS LIKE: this is the one construct whose
// rendering genuinely differs between backends, so it is worth comparing
// them side by side in the showroom.
//
// - C, C++, Rust, and Go emit a plain aggregate holding all three
// options at once, plus a tag field naming the active one. It needs
// no allocation and its layout does not depend on which option is
// set, but the aggregate is as large as its largest option and
// reading the wrong one is a runtime mistake, not a compile-time
// one: consumers must branch on the tag first.
// - Python emits the same shape with the inactive options typed as
// None, so an unset option at least reads as absent rather than as a
// zeroed value.
// - TypeScript emits a true discriminated union -- three object types
// joined by `|`, each carrying its own `_tag` literal -- so the
// compiler refuses to let you read an option you have not narrowed
// to.
//
// None of this changes the wire format, which is a tag followed by the
// selected option in every case.
type ControlSurfaces_1_0 struct {
// Selected for quadrotor, hexrotor, and coaxial airframes.
Multirotor MultirotorMix_1_0
// Selected for conventional and flying-wing airframes.
FixedWing FixedWingSurfaces_1_0
// Selected for the hover phase of a VTOL transition. Structurally
// identical to the multirotor option but semantically distinct: a
// receiver uses the tag to decide whether the forward-flight surfaces
// should be held at their transition schedule or released to the
// autopilot.
VtolHover MultirotorMix_1_0
Tag uint8
}
TypeScript¶
// Post-mixer actuator commands, discriminated by airframe class.
//
// LEAST SUPPORTED TRANSPORT: CAN FD.
//
// WHY A UNION: the three airframe classes in the fleet need disjoint
// actuator sets, and a message that carried all of them would waste
// bandwidth on every flight and would leave a receiver guessing which
// half of the payload is meaningful. A @union serializes a tag plus
// exactly one option, so the wire cost is that of the selected variant
// rather than the sum of all three.
//
// A union's fields are options, not members: exactly one is present in
// any given value. The tag is implicit in the definition and is emitted
// ahead of the selected option.
//
// WHAT THE GENERATED CODE LOOKS LIKE: this is the one construct whose
// rendering genuinely differs between backends, so it is worth comparing
// them side by side in the showroom.
//
// - C, C++, Rust, and Go emit a plain aggregate holding all three
// options at once, plus a tag field naming the active one. It needs
// no allocation and its layout does not depend on which option is
// set, but the aggregate is as large as its largest option and
// reading the wrong one is a runtime mistake, not a compile-time
// one: consumers must branch on the tag first.
// - Python emits the same shape with the inactive options typed as
// None, so an unset option at least reads as absent rather than as a
// zeroed value.
// - TypeScript emits a true discriminated union -- three object types
// joined by `|`, each carrying its own `_tag` literal -- so the
// compiler refuses to let you read an option you have not narrowed
// to.
//
// None of this changes the wire format, which is a tag followed by the
// selected option in every case.
export type ControlSurfaces_1_0 =
// Selected for quadrotor, hexrotor, and coaxial airframes.
| { _tag: 0; multirotor: MultirotorMix_1_0; }
// Selected for conventional and flying-wing airframes.
| { _tag: 1; fixed_wing: FixedWingSurfaces_1_0; }
// Selected for the hover phase of a VTOL transition. Structurally
// identical to the multirotor option but semantically distinct: a
// receiver uses the tag to decide whether the forward-flight surfaces
// should be held at their transition schedule or released to the
// autopilot.
| { _tag: 2; vtol_hover: MultirotorMix_1_0; };
Python¶
# Post-mixer actuator commands, discriminated by airframe class.
#
# LEAST SUPPORTED TRANSPORT: CAN FD.
#
# WHY A UNION: the three airframe classes in the fleet need disjoint
# actuator sets, and a message that carried all of them would waste
# bandwidth on every flight and would leave a receiver guessing which
# half of the payload is meaningful. A @union serializes a tag plus
# exactly one option, so the wire cost is that of the selected variant
# rather than the sum of all three.
#
# A union's fields are options, not members: exactly one is present in
# any given value. The tag is implicit in the definition and is emitted
# ahead of the selected option.
#
# WHAT THE GENERATED CODE LOOKS LIKE: this is the one construct whose
# rendering genuinely differs between backends, so it is worth comparing
# them side by side in the showroom.
#
# - C, C++, Rust, and Go emit a plain aggregate holding all three
# options at once, plus a tag field naming the active one. It needs
# no allocation and its layout does not depend on which option is
# set, but the aggregate is as large as its largest option and
# reading the wrong one is a runtime mistake, not a compile-time
# one: consumers must branch on the tag first.
# - Python emits the same shape with the inactive options typed as
# None, so an unset option at least reads as absent rather than as a
# zeroed value.
# - TypeScript emits a true discriminated union -- three object types
# joined by `|`, each carrying its own `_tag` literal -- so the
# compiler refuses to let you read an option you have not narrowed
# to.
#
# None of this changes the wire format, which is a tag followed by the
# selected option in every case.
@dataclass(slots=True)
class ControlSurfaces_1_0:
_tag: int = 0
# Selected for quadrotor, hexrotor, and coaxial airframes.
multirotor: MultirotorMix_1_0 | None = None
# Selected for conventional and flying-wing airframes.
fixed_wing: FixedWingSurfaces_1_0 | None = None
# Selected for the hover phase of a VTOL transition. Structurally
# identical to the multirotor option but semantically distinct: a
# receiver uses the tag to decide whether the forward-flight surfaces
# should be held at their transition schedule or released to the
# autopilot.
vtol_hover: MultirotorMix_1_0 | None = None
Every build recipe compiles this definition along with the rest of the namespace.