Generated reference › Polar To Cartesian — Robotics/Coordinate Transforms
kind: generated#block#robotics-coordinate-transforms

Polar To Cartesian — Robotics/Coordinate Transforms

Robotics/Coordinate_Transforms/Polar_To_Cartesian · 2 input / 2 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.

Polar To Cartesian

Robotics / Coordinate Transforms

Converts a planar polar pair to Cartesian form, entry by entry: x = r·cos θ and y = r·sin θ, with θ in radians.

The inverse of Cartesian To Polar. The two round-trip exactly for any θ already inside (−π, π] and any r ≥ 0.

Ports

  • r – the radius, any size [m,n]. It may be negative – see Notes.
  • theta – the angle in radians. It must be the same size as r; the two are paired entry by entry and neither is broadcast. It need not lie in any particular interval.
  • xr·cos θ, the same size as the inputs.
  • yr·sin θ, the same size as the inputs.

Parameters

  • 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. There is no tunable parameter, because the block has no parameter at all.

The three HDL targets are simulation-only: they carry the arithmetic in real and quantize only at the port boundary, because a sine and a cosine have no Q16.16 form to call.

Every backend needs only a multiply and the two trigonometric functions, which each of the ten has by name – including PLC Structured Text, where SIN and COS are standard. Nothing here is guarded, because nothing here has a restricted domain.

Simulink bridge

Both directions, onto simulink_extras/Transformations/Polar to Cartesian. That block has no dialog parameters whatsoever (verified with get_param(blk, 'DialogParameters'), which comes back empty), so there is nothing to map: the bridge is the library path alone. It also has no SampleTime parameter, so Sampling Time (s) does not cross – the block runs at the surrounding Simulink rate.

Notes

  • Algebraic and stateless: both outputs depend only on the current inputs.
  • Nonlinear in θ, and deliberately carries no state space.
  • A negative radius is passed through the formula, not corrected. r = −2 at θ = π/3 gives (−1, −1.732) – the point diametrically opposite. The block does not fold it to r > 0 with θ + π, and does not clamp it. This is measured against the Simulink block, and it is the useful behaviour: a signed range from a sensor stays meaningful.
  • θ is not wrapped. Angles far outside (−π, π] are fine – sine and cosine are periodic. So this block accepts the raw, unwrapped angle that poses and headings carry in this library, with no Angle Wrap needed in front of it.
  • Round-tripping is exact but not an identity in general. Feeding x and y back through Cartesian To Polar returns |r| and θ wrapped into (−π, π] – the same point, in canonical form. That is the polar representation being many-to-one, not a loss of precision: the measured error is exactly zero.

Code facts#

FactValue
registered typeRobotics/Coordinate_Transforms/Polar_To_Cartesian
familyRobotics/Coordinate_Transforms
solver environment classICoreBlock_0_Robotics_1_Coordinate_Transforms_2_Polar_To_Cartesian
sourcesrc/ICoreSDK/ICoreBlockLibrary/Blocks/Robotics/Coordinate_Transforms/Polar_To_Cartesian/ICoreBlock_0_Robotics_1_Coordinate_Transforms_2_Polar_To_Cartesian.cpp
headersrc/ICoreSDK/ICoreBlockLibrary/Blocks/Robotics/Coordinate_Transforms/Polar_To_Cartesian/ICoreBlock_0_Robotics_1_Coordinate_Transforms_2_Polar_To_Cartesian.h
default size on canvas126 × 84 px
ports at insert2 in, 2 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoubler
2inICoreDoubletheta
3outICoreDoublex
4outICoreDoubley

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#

No config variable beyond the Sampling Time (s) every block carries.

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 pathsimulink_extras/Transformations/Polar to Cartesian
port-count rulePortsParam::None
SampleTime parameterno — the counterpart defines none; the rate stays on the ICore side

Caveat (shown to the user): the Simulink block has no dialog parameters at all, so nothing but the block itself crosses; it also defines no SampleTime, so "Sampling Time (s)" does not cross and the block runs at the surrounding Simulink rate

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

Polar To Cartesian — the planar transform, elementwise x = r * cos(theta) y = r * sin(theta)

The inverse of Cartesian_To_Polar, measured WITH it in one MATLAB session against one shared probe table and then round-tripped through it -- 0.000e+00 error against the canonical polar form, and every point independently matched r*cos / r*sin. Measuring the two together is what the board row asked for, and it is the only way to catch a pair that is self-consistent and both wrong.

⚠ TWO MEASURED FACTS THAT MAKE THIS BLOCK TOTAL, and they are why it carries no guards where its inverse carries two:

  • a NEGATIVE radius is NOT canonicalized -- r = -2 at theta = pi/3 gives (-1, -1.732),

the formula as written. No folding into r > 0, no clamp to zero.

  • theta is NOT wrapped -- 5.5 and -4.2 rad were probed and simply go to sin/cos, which

are periodic. So this block takes the RAW unwrapped angle the convention ledger says poses carry, with no Angle_Wrap needed in front of it.

sin and cos are total in IEEE.MATH_REAL, in Verilog/SystemVerilog's real system functions and in IEC 61131-3 alike, so unlike Cartesian_To_Polar there is no domain to guard in any of the ten backends and PLC ST needs no reconstruction -- it has SIN and COS by name.

Sample results#

Polar To Cartesian — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per samplePolar To Cartesian — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample-202012345t (s)in ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0out ICoreDouble-Out-1
tin ICoreDouble-Out-0in ICoreDouble-Out-0out ICoreDouble-Out-0out ICoreDouble-Out-1
0-2-20.83231.819
0.40.50.50.43880.2397
0.8-2-20.83231.819
1.20.50.50.43880.2397
1.6-2-20.83231.819
20.50.50.43880.2397
2.4-2-20.83231.819
2.80.50.50.43880.2397
3.2-2-20.83231.819
3.60.50.50.43880.2397
4-2-20.83231.819
4.40.50.50.43880.2397
4.8-2-20.83231.819
5.20.50.50.43880.2397

Every 4th of 60 samples, from the table stimulus.

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)0 … 0.5403
rampRamp: slope 1 from t = 0-3.287 … 5.136
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias-0.561 … 0.5611
stepStep: 0 -> 1 at t = 1 s0 … 0.5403

Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample

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