Generated reference › Planar Arm Forward Kinematics — Robotics/Planar Kinematics
kind: generated#block#robotics-planar-kinematics

Planar Arm Forward Kinematics — Robotics/Planar Kinematics

Robotics/Planar_Kinematics/Planar_Arm_Forward_Kinematics · 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.

Planar Arm Forward Kinematics

Robotics / Planar Kinematics

The tool pose of an N-link planar serial arm from its N joint angles. Joint angles are relative – each measured from the previous link, which is what a joint sensor reports – so the absolute direction of link k is the running sum φk = q0 + … + qk, and the pose follows by walking the links tip to tip:

  • x = Σk lk·cos(φk)
  • y = Σk lk·sin(φk)
  • φ = φN−1 – the tool's own orientation, which is simply the sum of every joint angle

Ports

  • q – the joint angles, an [N,1] column in radians, base joint first. N is set by the Link Lengths config, and an input of any other height is an error rather than something broadcast.
  • pose[3,1], the triple (x, y, φ) the rest of this family uses. φ is raw: it is a sum of joint angles and may leave (−π, π].

Parameters

  • Link Lengths – an [N,1] column, base link first, in whatever length unit the diagram uses. Its height is the only source of N, so the arm is defined here and nowhere else; a second config that could disagree with it deliberately does not exist. Lengths may be zero (a coincident joint) but not negative.
  • 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 link lengths are baked into the emitted body as literals rather than exposed as tunable parameters: they are structural – changing one changes N and therefore the port sizes, so it is not something that could be retuned on a generated core anyway.

The arm is fully unrolled at export time. N is fixed by the config, so no emitted body contains a loop or a data-dependent index; the code grows linearly with N.

The three HDL targets are simulation-only real arithmetic, not synthesizable Q16.16: the body needs N sines and N cosines every sample and there is no fixed-point trigonometry to call. Quantization happens only at the port boundary.

Simulink bridge

None, and the reason is measured rather than assumed: Simulink's arm kinematics ship in the Robotics System Toolbox, which is not installed on this machine (robotics, nav, uav and shared_robotics are all absent from matlabroot/toolbox). A model carrying this block exports with the block reported rather than silently dropped.

Notes

  • Algebraic and stateless: the pose depends only on the current joint angles, so the block cannot break an algebraic loop.
  • Joint angles are RELATIVE, not absolute. This is the convention a real arm reports and the one Planar Arm Jacobian differentiates. If a model carries absolute link directions instead, the cumulative sum here would double-count – feed differences, or drop the sum.
  • Pairs with Planar Arm Jacobian, which is the derivative of this exact map and reads the same Link Lengths config. Give the two the same config value: they describe one arm, and nothing checks that for you.
  • φ is unwrapped by design, matching the ledger the whole Robotics family follows. Put an Angle Wrap after it when a wrapped heading is wanted, so the wrap is visible in the diagram.
  • Nonlinear, so deliberately no state space – a fabricated linear form would let model reduction merge matrices that do not describe this block.

Code facts#

FactValue
registered typeRobotics/Planar_Kinematics/Planar_Arm_Forward_Kinematics
familyRobotics/Planar_Kinematics
solver environment classICoreBlock_0_Robotics_1_Planar_Kinematics_2_Planar_Arm_Forward_Kinematics
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/Robotics/Planar_Kinematics/Planar_Arm_Forward_Kinematics/ICoreBlock_0_Robotics_1_Planar_Kinematics_2_Planar_Arm_Forward_Kinematics.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/Robotics/Planar_Kinematics/Planar_Arm_Forward_Kinematics/ICoreBlock_0_Robotics_1_Planar_Kinematics_2_Planar_Arm_Forward_Kinematics.h
default size on canvas140 × 88 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
1inICoreDoubleq
2outICoreDoublepose

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
Link Lengths[1; 0.8; 0.5]

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: planar arm kinematics ship in the Robotics System Toolbox, which is not installed. Rebuild the chain on the Simulink side from Trigonometric Function and Sum blocks, keeping the RELATIVE joint-angle convention and the (x, y, phi) pose layout this block uses

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

Description vs code#

The checker has a blind spot here — it could not resolve something (a grouped port bullet, a computed config name), which is reported and never counted as a pass. A reader has to settle it:

  • B0 every stimulus in the sample errored — cross-checks skipped

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).

Planar Arm Forward Kinematics — N relative joint angles to the tool pose (x, y, phi) phi_k = q_0 + q_1 + ... + q_k (cumulative: joint angles are RELATIVE) x = SUM_k l_k * cos(phi_k) y = SUM_k l_k * sin(phi_k) pose = [x; y; phi_{N-1}]

Written together with Planar_Arm_Jacobian, whose columns are suffix sums over the SAME l_k*cos(phi_k) and l_k*sin(phi_k) terms this block accumulates in full. See the header for why the pair travels together and what it buys that neither block has alone.

⚠ THE ACCUMULATION ORDER IS THE CONTRACT, and it is ascending k in all eleven implementations. Floating-point addition is not associative, so a backend summing the links tip-to-base would disagree with this reference in the last ulp on most samples -- a row that moves for a reason having nothing to do with the export.

⚠ EVERYTHING IS UNROLLED AT EXPORT TIME. N is fixed by the config, so the emitted body has no loop and no data-dependent indexing in any of the ten targets -- Decision_Tree's cascade argument, and it is what keeps the three HDL targets straightforward. The emitted body grows linearly in N, which the description states.

⚠ THE GENERATORS BAKE THE LINK LENGTHS IN, so loadBlockConfig() MUST be called from initializePortSignalSize() (§3): code export never calls it, and a generator reading an unfilled config map logs an error and stops the run.

Sample results#

No stimulus produced a sampled output in this rig — Invalid input size at Planar Arm Forward Kinematics block: ICore Blocks/Home/Planar Arm Forward Kinematics. That is a fact about the single-block rig, not a verdict on the block: an offline batch fit, a block whose output only appears at onSolverFinish, or one that needs a driven environment cannot be exercised alone.

Category unsampled · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60

Sample data: docs/generated/samples/Robotics__Planar_Kinematics__Planar_Arm_Forward_Kinematics.json