Skip to content

Robots and wings

flapsim.robot.loader

Load a robot from a manifest, a bare URDF/MJCF file, or an MjSpec.

RobotModel dataclass

A compiled MuJoCo model with its manifest and wing objects.

geometry_warnings()

Frame and joint-sign warnings for every wing at the current pose.

load(source, *, manifest=None, base=None, position=None, timestep=None, scene=True, check=True)

Build a :class:RobotModel.

source is a built-in robot name, a manifest file, a bare URDF/MJCF file, a :class:RobotManifest, or an :class:mujoco.MjSpec (then pass its manifest separately or get a wing-less default). base overrides the manifest's base type ("fixed" or "free"), position the spawn position and timestep the integrator step. With check the wing frames and joint signs are sanity-checked at the neutral pose and problems are reported as warnings.

resolve_manifest(source)

Accept a manifest, a manifest path, a model path or a built-in name.

builtin_robots() cached

Map every built-in robot name and alias to its manifest file.

flapsim.robot.manifest

Robot manifest: what a URDF or MJCF file cannot say about a flapping robot.

A manifest is a small YAML or JSON document that lives next to the model file. It names the torso and the wings, gives each wing its aerodynamic frame, its stroke and feathering joints and its planform, and lists the model patches (joint dynamics, equality constraints, mass overrides) that MuJoCo needs but URDF cannot express. :meth:RobotManifest.from_file parses and validates it and :func:flapsim.robot.load turns it into a compiled MuJoCo model with :class:~flapsim.wings.Wing objects attached.

Conventions

  • Vectors are expressed in the frame of the body they belong to.
  • frame.span points from the wing root to the tip along the feathering axis; frame.chord points from the leading edge (the hinge line) to the trailing edge. FlapSim derives the surface normal from them, so the side of the hinge on which the wing lies is never ambiguous.
  • sign on a joint reference converts the MuJoCo joint coordinate into the aerodynamic convention: psi = sign * qpos.
  • when on a patch restricts it to "fixed" or "free" base models; the default "always" applies it to both.

RobotManifest dataclass

for_model_file(path) classmethod

A wing-less manifest for a bare URDF or MJCF file.

resolve(path)

Resolve a path from extras relative to the manifest location.

ModelSpec dataclass

BaseSpec dataclass

ModelPatches dataclass

JointPatch dataclass

Joint properties URDF cannot express (all SI, None leaves MuJoCo's).

BodyPatch dataclass

Mass-property overrides for one body (or "*" for all others).

EqualityPatch dataclass

An equality constraint between two joints or two bodies.

WingSpec dataclass

WingFrame dataclass

Aerodynamic frame of a wing in its body frame, or the name of a site.

span points from root to tip along the feathering axis and chord from the leading edge (hinge line) to the trailing edge. For a site, the site's +X is the chord direction and +Y the span direction.

WingMass dataclass

Mass properties of a wing body, given in wing coordinates.

Wing coordinates are (normal, span, chord) with span positive from root to tip and chord positive from the leading to the trailing edge, so mirrored wings share the same numbers.

  • type: thin_plate: a uniform plate covering length x mean_chord.
  • type: spar_plate: a leading-edge spar (rod along the span) holding spar_fraction of the mass plus a uniform membrane plate holding the rest. This is the usual mass distribution of a membrane wing and the one that gives physically correct passive feathering.
  • type: explicit: com and diaginertia about the wing axes through the centre of mass.

Planform dataclass

Wing planform: how to obtain the blade-element integrals.

profile selects the source: an analytic shape (rectangular or elliptic, needs length and mean_chord), a chord polyline of (r, c) pairs in metres from root to tip, or explicit integrals. pitch_axis_fraction is the chordwise position of the feathering axis measured from the leading edge as a fraction of the chord (hinge inside the plate); leading_edge_offset is the distance in metres from the feathering axis to the leading edge when the plate starts beyond the hinge (a root spar). Use one or the other.

JointRef dataclass

TorsoSpec dataclass

ManifestError

Bases: ValueError

Raised when a robot manifest is malformed or contradicts itself.

flapsim.robot.builders

Parametric robots built in Python, for users without CAD and for tests.

flat_plate_flapper(*, span=0.07, chord=0.02, thickness=0.0005, shoulder=0.012, body_mass=0.03, wing_mass=0.0001, arm_mass=0.0002, stroke_range=1.5, feathering_range=0.785398, feathering_stiffness=2e-07, feathering_damping=1e-09, feathering_armature=1e-10, spar_fraction=0.8, timestep=5e-05, position=(0.0, 0.0, 0.5), name='flat_plate_flapper')

A two-wing flapper with rectangular flat-plate wings.

The torso sits at the origin and the wings span the body x axis. At the neutral pose each plate is vertical: its normal points along -y (the stroke direction) and its chord hangs down (-z) from the leading-edge hinge. This is the quasi-steady model's convention, in which a feathering angle of zero means the plate meets the stroke flow at 90 degrees. The stroke joints rotate about +z (left) and -z (right), so equal joint angles give mirrored motion; the passive feathering joints rotate about +x for both wings. Returns the MjSpec and a matching manifest; pass both to :func:flapsim.robot.load. The wing mass is distributed as a leading-edge spar (spar_fraction) plus a membrane plate through the manifest's mass model.

flat_plate_simulation(*, frequency_hz=30.0, amplitude_rad=1.2, base='fixed', aero='aero/quasi_steady', **builder_kwargs)

A :class:~flapsim.core.Simulation of :func:flat_plate_flapper.

The stroke joints are driven sinusoidally (equal angles give mirrored motion) and the quasi-steady aero plugin is attached unless aero is None.

flapsim.robot.inspect

Describe a compiled MuJoCo model so a user can write a manifest quickly.

model_summary(model, manifest=None, wings=None)

A JSON-serialisable description of bodies, joints, sites and wings.

describe_model(model, manifest=None, wings=None)

A human-readable table of the model, as printed by flapsim inspect.

flapsim.wings.wing

Runtime wing: a manifest :class:WingSpec resolved against a MuJoCo model.

The aerodynamic frame of a wing has +X along the surface normal, +Y along the feathering axis and +Z = X x Y; the chord extends from the hinge along -Z. From the manifest's span (root to tip) and chord (leading to trailing edge) vectors: Y = side * span, Z = -chord and X = Y x Z. Mirrored wings therefore share one frame orientation at the neutral pose (for a right wing +Y is the negative root-to-tip direction) and the side factor in the aerodynamic formulas puts the centre of pressure back on the wing. This is the convention of the quasi-steady model in :mod:flapsim.fluid.aero.

WingState dataclass

Kinematic state of one wing read from MjData.

Wing

body_mass_properties()

(mass, com_body, fullinertia_body) from the manifest mass model.

Wing coordinates (normal, span, chord) map onto the aero axes as (X, side * Y, -Z); the inertia is rotated into the body frame and returned as [Ixx, Iyy, Izz, Ixy, Ixz, Iyz].

geometry_warnings(model, data)

Plain-language warnings when the frame or joint signs look reversed.

Checks, at the current (neutral) pose: the wing's centre of mass lies on the chord side of the hinge (-Z), a positive stroke rate moves the wing against +X (so the relative flow is along +X), and a positive feathering rate rotates the wing about +Y.

apply_wrench(data, force_world, torque_world)

Write a world-frame wrench about the body centre of mass.

flapsim.wings.planform

Wing planform integrals for blade-element aerodynamics.

The quasi-steady model needs chord-weighted radial moments of the planform. With the non-dimensional span coordinate r_hat = r / R and chord c_hat = c(r) / c_mean they are

  • r_kk = integral c_hat * r_hat**k for k = 0..3 (normal force),
  • z_cpk = integral c_hat**2 * r_hat**k for k = 0..2 (pitching moment),
  • z_rd = integral (|y_te| y_te**3 - |y_le| y_le**3) / c_mean**4 (rotational damping), where y is the chordwise distance from the feathering axis to the trailing and leading edges.

For a rectangular wing hinged at its leading edge all of them are 1 / (k + 1) and z_rd = 1. Several constructors are offered: analytic profiles, a chord polyline, a planform polygon and a mesh outline.

from_chord_distribution(r_hat, c_hat, *, pitch_axis_fraction=0.0, samples=20001)

Integrals of a sampled chord distribution c(r_hat) on [0, 1].

c_hat may carry any unit; it is normalised to a unit mean chord. The points define a piecewise-linear chord, which is resampled on samples points before trapezoid integration so that coarse polylines integrate accurately.

from_profile(profile, *, pitch_axis_fraction=0.0, samples=20001)

Integrals of an analytic planform: rectangular or elliptic.

from_polyline(points, *, pitch_axis_fraction=0.0)

Integrals of a chord polyline [(r, c), ...] in metres, root to tip.

Returns (length, mean_chord, integrals).

from_polygon(polygon, hinge_origin, span_direction, chord_direction, *, quadrature_order=24, axis_tolerance=0.01)

Integrals of a planar planform polygon given in metres.

polygon is an (N, 2) outline in any planar coordinates, hinge_origin the wing root on the feathering axis, span_direction the axis towards the tip and chord_direction the axis from the leading edge towards the trailing edge. The quasi-steady moment formula assumes the feathering axis runs along the leading edge; pitch_axis_exact in the result reports whether the outline satisfies that within axis_tolerance.

read_stl_triangles(path)

Return the triangles of a binary or ASCII STL file as (N, 3, 3).

read_stl_vertices(path)

Return the unique vertices of a binary or ASCII STL file as (N, 3).

from_mesh(path, *, span_axis, chord_axis, hinge_origin=(0.0, 0.0, 0.0), bins=64, scale=1.0, samples_per_edge=64)

Approximate planform integrals from a wing mesh (STL).

Vertices are projected onto the span_axis/chord_axis plane and binned along the span; each bin's chord is the extent of its vertices in the chord direction. chord_axis points from the leading edge towards the trailing edge and hinge_origin lies on the feathering axis. scale converts the mesh unit to metres (1e-3 for millimetre meshes). The result is an approximation whose quality depends on the mesh resolution and on bins.

resolve_planform(planform)

Turn a manifest :class:~flapsim.robot.manifest.Planform into numbers.

wing_params(length, mean_chord, integrals, *, rho=1.225, d0=0.0, ds=0.0, x_le=0.0, x0=0.0)

Assemble the flat parameter object used by the quasi-steady model.