Generated reference › Two Mass Drivetrain — Robotics/Actuators And Drivetrain
kind: generated#block#robotics-actuators-and-drivetrain

Two Mass Drivetrain — Robotics/Actuators And Drivetrain

Robotics/Actuators_And_Drivetrain/Two_Mass_Drivetrain · 2 input / 3 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.

Two Mass Drivetrain

Robotics / Actuators And Drivetrain

A motor inertia and a load inertia coupled by a shaft that is not rigid – the flexible-joint plant, and the reason a position loop that is perfectly stable on the bench oscillates once the load is bolted on.

Four states, x = [θm, ωm, θl, ωl]:

  • Jmωm' = τm − k(θm−θl) − c(ωm−ωl) − bmωm
  • Jlωl' = k(θm−θl) + c(ωm−ωl) − blωl − τload

The resonance sits at ωn = √(k(1/Jm + 1/Jl)) with damping ratio ζ = (c/2)· √((1/Jm + 1/Jl)/k) – a frequency neither inertia carries on its own, which is exactly why two separate integrators cannot stand in for this block.

Ports

  • tau_m – the motor torque applied to the motor inertia (N·m), a scalar [1,1]. This is one drivetrain, so use one block per axis.
  • tau_load – the external load torque (N·m), a scalar. It opposes motion: a positive value decelerates the load, matching the sign convention DC Motor uses for its own load port.
  • w_m – motor speed (rad/s). This is what the motor encoder reads, and what a naive loop closes on.
  • w_l – load speed (rad/s). This is what the machine actually does.
  • tau_shaft – the torque the coupling transmits, k(θm−θl) + c(ωm−ωl) (N·m). Exposed as a port because it is the quantity that breaks couplings, and because it is the one output that reads all four states.

Parameters

  • Motor Inertia (kg.m^2)Jm, positive. Rotor plus everything rigidly attached to it.
  • Load Inertia (kg.m^2)Jl, positive.
  • Shaft Stiffness (N.m/rad)k, zero or more. At exactly zero the two inertias are uncoupled and each simply integrates its own torque – a legal degenerate case, and a useful sanity check.
  • Shaft Damping (N.m.s/rad)c, zero or more. This is the internal damping of the coupling, acting on the speed difference; it is what limits the resonant peak.
  • Motor Damping (N.m.s)bm, zero or more, acting on motor speed against ground (bearings, windage).
  • Load Damping (N.m.s)bl, zero or more, the same against the load.
  • Initial Shaft Twist (rad) – the initial θm−θl, i.e. a pre-wound shaft. Nonzero here is what makes the plant ring from the first sample.
  • Initial Motor Speed (rad/s) / Initial Load Speed (rad/s) – the two speed states at t = 0.
  • 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. The block exports the discretized state space, by whichever method the model selects (ZOH, FOH, Tustin, Matched, either Euler) – the coefficients are baked in at export time and are not tunable on the generated core, so re-export after changing a drivetrain.

Every row is emitted as a multiply-accumulate over the four states and two inputs, including the entries that are zero, so all ten backends sum the terms in the same order. Floating-point addition is not associative, and that uniformity is what keeps the software targets bit-identical to the C++ reference.

The three HDL targets are synthesizable Q16.16 at ordinary drivetrain parameters – no division and nothing transcendental survives into the body. That is a property of the discretized coefficients rather than of the block: a very small inertia drives 1/J, and with it Bd, up by orders of magnitude, and a shaft stiff enough to put the resonance near the sample rate does the same to Ad. Check the numbers if either applies.

Simulink bridge

No equivalent (Support::None). Drivetrain blocks ship in Simscape Driveline, which is not installed on this machine (measured – isfolder([matlabroot '/toolbox/simscape']) is false), and a physical-network block would not map onto a signal-flow port list in any case. A model that must cross can carry the same plant as a State-Space block: A, B, C, D exactly as printed at the top of this block's source, with states (θm, ωm, θl, ωl).

Notes

  • Linear and stateful, and it carries a proper continuous state space – so model reduction can absorb it into a neighbouring plant in series, parallel or feedback, and the discretization follows the model's own method rather than a hardcoded Euler step.
  • The plant is marginally stable, deliberately. Only the shaft difference enters the equations, so the rigid-body mode (both shafts turning together) has no restoring term and the two absolute positions random-walk under a zero-mean torque. That is the machine, not a defect – an unloaded drivetrain does drift. It is also why the initial condition is a twist rather than two absolute angles: only the difference is observable.
  • Damping is split three ways on purpose. c acts on the speed difference (inside the coupling) while bm and bl act against ground. They are not interchangeable: raising c damps the resonance, raising bm or bl mostly just wastes torque.
  • No backlash, no friction, no torque limit. Put Backlash or Stribeck Friction on the shaft and Saturation on the torque if the mechanism needs them – keeping them out is what leaves this block linear, and with it everything in the first note.
  • Pairs with DC Motor upstream: its w output is the motor side, its tau_load port takes the reaction. Together they are the plant a cascade loop is actually tuned against.

Code facts#

FactValue
registered typeRobotics/Actuators_And_Drivetrain/Two_Mass_Drivetrain
familyRobotics/Actuators_And_Drivetrain
solver environment classICoreBlock_0_Robotics_1_Actuators_And_Drivetrain_2_Two_Mass_Drivetrain
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/Robotics/Actuators_And_Drivetrain/Two_Mass_Drivetrain/ICoreBlock_0_Robotics_1_Actuators_And_Drivetrain_2_Two_Mass_Drivetrain.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/Robotics/Actuators_And_Drivetrain/Two_Mass_Drivetrain/ICoreBlock_0_Robotics_1_Actuators_And_Drivetrain_2_Two_Mass_Drivetrain.h
default size on canvas148 × 100 px
ports at insert2 in, 3 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubletau_m
2inICoreDoubletau_load
3outICoreDoublew_m
4outICoreDoublew_l
5outICoreDoubletau_shaft

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
Motor Inertia (kg.m^2)0.01
Load Inertia (kg.m^2)0.02
Shaft Stiffness (N.m/rad)100
Shaft Damping (N.m.s/rad)0.05
Motor Damping (N.m.s)0.005
Load Damping (N.m.s)0.005
Initial Shaft Twist (rad)0
Initial Motor Speed (rad/s)0
Initial Load Speed (rad/s)0

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::None
Simulink path
port-count rulePortsParam::None
SampleTime parameteryes

Caveat (shown to the user): no Simulink equivalent available: drivetrain blocks ship in Simscape Driveline, which is not installed on this machine (measured), and a physical-network block carries no signal-flow port list to map onto. A model that must cross can carry the same plant as a State-Space block with states (theta_m, w_m, theta_l, w_l), inputs (tau_m, tau_load) and outputs (w_m, w_l, tau_shaft) - the matrices are printed at the top of this block's source

Catalog contract: src/ICoreSDK/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).

Two Mass Drivetrain — the flexible joint, and why position loops oscillate theta_m' = w_m Jm w_m' = tau_m - k(theta_m - theta_l) - c(w_m - w_l) - bm w_m theta_l' = w_l Jl w_l' = k(theta_m - theta_l) + c(w_m - w_l) - bl w_l - tau_load

x = [theta_m; w_m; theta_l; w_l], u = [tau_m; tau_load], y = [w_m; w_l; tau_shaft], with tau_shaft = k(theta_m - theta_l) + c(w_m - w_l) -- what the coupling actually transmits.

⚠ SAME STATE-SPACE-FIRST LIFECYCLE AS DC_Motor, inherited rather than re-derived: seed the continuous set in the constructor from the block's own defaults, re-derive it in loadBlockConfig(), take both compute pairs FROM it, and let discretize() decide the export. That block's row was left free for this one to reuse, which is the only reason this file is short enough to read.

⚠ THE RESONANCE IS THE POINT. w_n = sqrt(k(1/Jm + 1/Jl)) with damping ratio zeta = (c/2)*sqrt((1/Jm + 1/Jl)/k). Both are properties of the CONFIG, and both matter to export: a stiff shaft on small inertias puts w_n above the sample rate, at which the discretized set stops describing the plant and no backend can rescue it. The description says so, and the block reports it rather than pretending.

⚠ THE PLANT IS MARGINALLY STABLE BY CONSTRUCTION and that is physics: only theta_m - theta_l enters the equations, so the rigid-body mode is a free integrator and the two positions random-walk under zero-mean torque. It is also why the seed is a TWIST rather than two angles.

Sample results#

Two Mass Drivetrain — Step: 0 -> 1 at t = 1 sTwo Mass Drivetrain — Step: 0 -> 1 at t = 1 s-2e14302e1434e143012345t (s)in ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0out ICoreDouble-Out-1out ICoreDouble-Out-2

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)-1.78e113 … 8.625e157
rampRamp: slope 1 from t = 0-7.569e168 … 3.296e159
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias-1.504e169 … 6.547e159
tableRepeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample-3.138e174 … 2.302e138

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

Category dynamic · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60 · data docs/generated/samples/Robotics__Actuators_And_Drivetrain__Two_Mass_Drivetrain.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).