Generated reference › Nonlinear Second Order Actuator — Robotics/Actuators And Drivetrain
kind: generated#block#robotics-actuators-and-drivetrain

Nonlinear Second Order Actuator — Robotics/Actuators And Drivetrain

Robotics/Actuators_And_Drivetrain/Nonlinear_Second_Order_Actuator · 1 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Description#

The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.

Nonlinear Second-Order Actuator

Robotics / Actuators and Drivetrain

The fin or servo actuator of the Linear Second-Order Actuator with the three limits a real one has. With ωn the natural frequency, ζ the damping ratio and vmax the rate limit:

  • us = sat(u, xmin, xmax) – the demand is held inside the deflection limits.
  • r = sat(us − x, ±2ζvmax/ωn) – the rate limit, applied to the tracking error.
  • x'' = ωn²·r − 2ζωn·x', with x held in [xmin, xmax] and x' in ±vmax. When x reaches a limit its rate is set to zero.

The error saturation is what makes vmax the steady slewing rate: with r pinned at its limit, x' settles at exactly vmax.

Ports

  • Input – u, the demanded position, a scalar [1,1], in the unit the limits are given in (radians by default).
  • Output – x, the actual position, a scalar [1,1], always inside [xmin, xmax].

Parameters

  • Natural Frequency (rad/s) – ωn, a scalar > 0. Defaults to 1.
  • Damping Ratio – ζ, a scalar > 0. Defaults to 0.3.
  • Maximum Deflection – xmax. Defaults to 20° in radians, 0.349.
  • Minimum Deflection – xmin, below xmax. Defaults to −0.349.
  • Rate Limit – vmax, a scalar > 0, in position units per second. Defaults to 500°/s in radians, 8.73.
  • Initial Position – x at t = 0. Defaults to 0.
  • Initial Velocity – x' at t = 0. Defaults to 0.
  • Integration Substeps – M, the number of fourth-order Runge-Kutta steps each sample is integrated with, a whole number of 1 or more. Defaults to 100, which reproduces Simulink's fixed-step ode4 at one hundredth of the sample time exactly. This one has no Simulink counterpart.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

Code export

All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. Every core runs the same map as the simulation: the demand held for a sample, M Runge-Kutta substeps with the limits applied after each, and the output taken before the update. The derived constants (ωn², 2ζωn, the error limit and the substep) are folded at export time; there is no tunable parameter object. A core does 4·M derivative evaluations per sample.

The three HDL targets are simulation-only real arithmetic, quantized at the port: a loop of saturated Runge-Kutta stages is not a fixed-point datapath. The cores simulate correctly and are not offered as synthesizable.

Simulink bridge

Import and export, mapped to Aerospace Blockset's aerolibactuator/Nonlinear Second-Order Actuator: Natural Frequency (rad/s) → wn_fin, Damping Ratio → z_fin, Maximum Deflection → fin_max, Minimum Deflection → fin_min, Rate Limit → fin_maxrate, Initial Position → fin_act_0 and Initial Velocity → fin_act_vel. Integration Substeps does not cross: the Simulink block is continuous and its solver decides. "Sampling Time (s)" does not cross either: the Simulink block defines no SampleTime parameter, measured on R2026a.

Notes

  • Discrete-only and stateful. The limits are part of the state's evolution – reaching a position limit resets the rate – and a state reset is not something a continuous derivative can say. So the block samples its input at its own rate, holds it, and integrates across the sample with M Runge-Kutta substeps. Against a continuous Simulink model run at a fixed step of Ts/M this is the same computation; against a variable-step one it differs by the solver's own error near a limit.
  • The output does not depend on the input at the same instant, so a feedback loop through the block is not an algebraic loop.
  • For an actuator that never reaches its limits, the Linear Second-Order Actuator is the same dynamics as a real state space.

Code facts#

FactValue
registered typeRobotics/Actuators_And_Drivetrain/Nonlinear_Second_Order_Actuator
familyRobotics/Actuators_And_Drivetrain
solver environment classICoreBlock_0_Robotics_1_Actuators_And_Drivetrain_2_Nonlinear_Second_Order_Actuator
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Actuators_And_Drivetrain/Nonlinear_Second_Order_Actuator/ICoreBlock_0_Robotics_1_Actuators_And_Drivetrain_2_Nonlinear_Second_Order_Actuator.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Robotics/Actuators_And_Drivetrain/Nonlinear_Second_Order_Actuator/ICoreBlock_0_Robotics_1_Actuators_And_Drivetrain_2_Nonlinear_Second_Order_Actuator.h
default size on canvas120 × 80 px
ports at insert1 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDouble—
2outICoreDouble—

Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.

Configuration variables#

Config variableDefaultSimulink parameter
Natural Frequency (rad/s)1wn_fin
Damping Ratio0.3z_fin
Maximum Deflection0.3490658503988659fin_max
Minimum Deflection-0.3490658503988659fin_min
Rate Limit8.7266462599716466fin_maxrate
Initial Position0fin_act_0
Initial Velocity0fin_act_vel
Integration Substeps100not crossed

Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.

supportSupport::Both
Simulink pathaerolibactuator/Nonlinear Second-Order Actuator
port-count rulePortsParam::None
SampleTime parameterno — the counterpart defines none; the rate stays on the ICore side
deliberately not crossedIntegration Substeps
ICore configSimulink parameterValue translation
Natural Frequency (rad/s)wn_finpasses through
Damping Ratioz_finpasses through
Maximum Deflectionfin_maxpasses through
Minimum Deflectionfin_minpasses through
Rate Limitfin_maxratepasses through
Initial Positionfin_act_0passes through
Initial Velocityfin_act_velpasses through

Caveat (shown to the user): aerolibactuator/Nonlinear Second-Order Actuator is continuous and has NO SampleTime parameter (verified against the R2026a block dialog), so "Sampling Time (s)" does not cross. "Integration Substeps" is how this block integrates across a sample and has no Simulink counterpart: a continuous model's solver decides that

Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.

The verdict above is tools/docs/check_block_descriptions.py (P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.

File banner (developer view)#

The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).

Nonlinear Second-Order Actuator — the fin actuator with its demand, rate and position limits Per sample, the demand u is held and the state (x, v) is advanced by M RK4 substeps of h = Ts/M on

us = min(max(u, xmin), xmax) Demand limits r = min(max(us - x, -R), R), R = ((vmax*2)*zeta)/wn dv = wn^2 * r - (2*zeta*wn) * v, dx = v dx := 0 when x sits on a limit and v points out; dv := 0 when v sits on +-vmax and dv points out

and after EACH substep: x > xmax -> x = xmax, v = 0; x < xmin -> x = xmin, v = 0; v = min(max(v, -vmax), vmax). The output is the pre-update position, min(max(x, xmin), xmax).

⚠ MEASURED AGAINST R2026a BEFORE ANY OF IT WAS WRITTEN. The masked subsystem is Saturate (Demand limits) -> Sum -> Saturate (rate limit*2*zeta/wn) -> Gain wn^2 -> Sum with Gain 2*zeta*wn on x' -> Second-Order Integrator LIMITED (x in [xmin, xmax], x' in +-vmax, zero-crossing on, reinit off). Three clamp rules were prototyped against Simulink's fixed-step ode4 at Ts/100 on a rig that sat on a limit for 39 % of 500 samples:

derivative gating alone 4.41e-2 gating + clamping x and x' 4.42e-2 gating + clamping + ZEROING x' at an x limit 0 <- this block

so the Second-Order Integrator resets its rate when the position saturates, even with "reinitialize dx/dt" off -- the thing no doc page says. With M = 100 this block is that reference, arithmetic operation for arithmetic operation.

A DISCRETE-ONLY block, for the reason the header gives: a state reset is not a derivative. All ten backends run the same map; the three HDL ones in SIMULATION-ONLY real arithmetic.

Sample results#

Nonlinear Second Order Actuator — Step: 0 -> 1 at t = 1 sNonlinear Second Order Actuator — Step: 0 -> 1 at t = 1 s00.51012345t (s)in ICoreDouble-Out-0out ICoreDouble-Out-0

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)-0.008721 … 0.02343
rampRamp: slope 1 from t = 00 … 0.3491
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias-0.1891 … 0.2788
tableRepeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample-0.03292 … 0.07704

Plotted: step — Step: 0 -> 1 at t = 1 s

Category dynamic · sample time 0.1 · 60 steps · commit fc85ac64df179e0aadfcbe797a2731524d14cbb9 · produced by docsSample --out <folder> --blocks Linear_Second_Order_Actuator Nonlinear_Second_Order_Actuator Wind_Shear_Model Discrete_Wind_Gust_Model Julian_Date_Conversion --steps 60 · data docs/generated/samples/Robotics__Actuators_And_Drivetrain__Nonlinear_Second_Order_Actuator.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).