Emergency Stop Ramp — Robotics/Safety Supervision
Robotics/Safety_Supervision/Emergency_Stop_Ramp · 3 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.
Emergency Stop Ramp
Robotics / Safety Supervision
Brings a command to zero at a controlled rate when a trip fires, and holds it there until it is explicitly cleared. With dt the block's sampling period:
- stopped ← estop ? 1 : (reset ? 0 : stopped) – so estop wins when both arrive on the same sample.
- while stopped, y moves from its own previous value one step of Deceleration·dt toward zero and stays at zero on arrival.
- while not stopped, y = u.
An input above 0.5 counts as asserted on both estop and reset; anything at or below it is not.
Ports
- u – the command being supervised, a scalar [1,1]: a velocity, a torque, a duty cycle.
- estop – a scalar [1,1]: above 0.5 trips the stop. Drive it from a button, a Watchdog Timer's inverted ok, a Stall Detector's stall, or several of those through an Or.
- reset – a scalar [1,1]: above 0.5 clears the latch, but only on a sample where estop is not asserted.
- y – a scalar [1,1]: the supervised command.
- stopped – a scalar [1,1]: 1 while the latch is engaged, including the whole ramp, 0 while passing through. It is a port rather than hidden state because y = 0 also happens when the command itself is zero, so this is the only signal that says why.
Parameters
- Deceleration – a scalar > 0, in output units per second: how fast the command is driven to zero once tripped. The per-sample step is Deceleration·dt, so a command of 2.0 at a deceleration of 8 units/s reaches zero in 0.25 s whatever the rate.
- Start Stopped – whether the block powers up latched:
- No – starts passing the command through.
- Yes – starts stopped, so the machine cannot move until a reset is seen. The conservative choice for anything that could be energised at power-on.
- 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 step Deceleration·dt is folded to a single constant at export time, so no generated core multiplies by a rate or carries the sampling period; there is no tunable parameter object.
The three HDL targets are genuine synthesizable Q16.16: comparisons plus one add or subtract of that constant, with no division and nothing transcendental.
Simulink bridge
None. Simulink has the pieces – a Switch, a Rate Limiter, a
latch built from Memory and Logical Operator blocks – but no single block
that ramps a command down and holds it, and the emergency-stop blocks that do
exist belong to toolboxes not installed on this machine. The entry reports the
block with that reason rather than dropping it silently, and no parity
testbench is owed – the documented consequence of
Support::None. Code export verification still covers all ten
languages.
Notes
- The latch is the point. Rate Limiter cannot stand in for this block: it slews toward whatever it is given, so it follows the command back up the instant the command returns. A stop a noisy trip line can release on its own is not a stop. Its siblings Watchdog Timer and Stall Detector deliberately do not latch, so that this behaviour lives in exactly one block.
- Estop wins on the same sample. With both inputs asserted the block stays stopped – the two are independent signals and can genuinely arrive together.
- The ramp resumes from the current output, never from u, so a second trip part-way down continues rather than stepping back up to the command.
- Release is immediate. On reset the block passes the command through on that same sample; it does not ramp back up. Follow it with a Rate Limiter if the resumption must be gentle – that is a separate decision with its own tuning.
- Stateful and inherently discrete
(
setDiscreteOnlyBlock(true)): the step is per sample, and there is no derivative to integrate. - Nonlinear, and deliberately carries no state space. A latch and a clamp are not describable by A/B/C/D, so model reduction correctly refuses the block.
- On the HDL targets the ramp arithmetic is Q16.16, so the output lands within one quantum (about 1.5e−5) of zero rather than exactly on it only if the step is not representable; the clamp is a comparison against the step, so arrival at zero is exact for any step the format can hold.
Code facts#
| Fact | Value |
|---|---|
| registered type | Robotics/Safety_Supervision/Emergency_Stop_Ramp |
| family | Robotics/Safety_Supervision |
| solver environment class | ICoreBlock_0_Robotics_1_Safety_Supervision_2_Emergency_Stop_Ramp |
| source | src/ICoreSDK/ICoreBlockLibrary/Blocks/Robotics/Safety_Supervision/Emergency_Stop_Ramp/ICoreBlock_0_Robotics_1_Safety_Supervision_2_Emergency_Stop_Ramp.cpp |
| header | src/ICoreSDK/ICoreBlockLibrary/Blocks/Robotics/Safety_Supervision/Emergency_Stop_Ramp/ICoreBlock_0_Robotics_1_Safety_Supervision_2_Emergency_Stop_Ramp.h |
| default size on canvas | 140 × 92 px |
| ports at insert | 3 in, 2 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | in | ICoreDouble | u |
| 2 | in | ICoreDouble | estop |
| 3 | in | ICoreDouble | reset |
| 4 | out | ICoreDouble | y |
| 5 | out | ICoreDouble | stopped |
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 variable | Default | Simulink parameter |
|---|---|---|
Deceleration | 1 | — |
Start Stopped | No%~%Yes~~No | — |
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.
Simulink bridge#
| support | Support::None |
| Simulink path | — |
| port-count rule | PortsParam::None |
SampleTime parameter | yes |
Caveat (shown to the user): no Simulink equivalent available: base Simulink has the pieces (a Switch, a Rate Limiter, and a latch built from Memory plus Logical Operator blocks) but no single block that ramps a command to zero and HOLDS it there, and the emergency-stop blocks that do exist belong to toolboxes not installed on this machine. Rebuild it from those pieces if a model must cross, keeping the two rules this block documents: estop wins over reset on the same sample, and the ramp continues from the block's own previous output rather than from the command
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).
Emergency Stop Ramp — the controlled stop, and the one block in Family S that LATCHES stopped := estop ? 1 : (reset ? 0 : stopped) -- estop wins the tie y := stopped ? toward_zero(y, decel*dt) : u -- ramp from the HELD output
Four decisions, each of which had to be made rather than inherited, and each stated in the description because none of them is implied by the port list:
- THE LATCH. A stop that a noisy trip line can release by itself is not a stop, which is
exactly why Rate_Limiter cannot be this block: it slews toward whatever it is given, so it follows the command back up the moment the command returns. Watchdog_Timer and Stall_Detector deliberately do not latch on the grounds that the latch lives here, once.
- ESTOP WINS ON THE SAME SAMPLE. The two are independent signals and really can arrive
together; the safe reading of "both" is not to release.
- THE RAMP RESUMES FROM THE CURRENT OUTPUT, never from u -- so a re-trip mid-ramp continues
instead of stepping back up to the command. That is why the held output is state.
- RELEASE IS IMMEDIATE. Coming back gently is a separate decision with its own tuning, and
the library already has the block for it: put a Rate_Limiter after this one.
⚠ dt is the block's OWN sampling period, read through getSamplingTime() at the point of use. Local sampling times are assigned AFTER port sizing, so a step cached in loadBlockConfig() would bake in a rate the model had not decided yet -- Rate_Limiter's lifecycle exactly.
All ten targets are exact and the three HDLs are genuine synthesizable Q16.16: compares plus one add or subtract of an export-time constant.
Sample results#
The same rig also ran:
| Stimulus | What it is | Output range |
|---|---|---|
impulse | Impulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair) | 0 … 0 |
ramp | Ramp: slope 1 from t = 0 | 0 … 0.5 |
sine | Sine Wave: amplitude 1, 2 rad/s, no phase, no bias | 0 … 0.3894 |
table | Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample | -2 … 0.5 |
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__Safety_Supervision__Emergency_Stop_Ramp.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).