Examples#

Use the single-rate example when one periodic runnable is sufficient for a function, for example simple signal conditioning or threshold checks with one execution rhythm.

Use the multi-rate example when preprocessing and decision logic should run at different cycle times, for example 10 ms input conditioning and 20 ms output publication.

SpeedHazardDetection (single cyclic runnable)

VehicleSpeedFusion (multi-rate cyclic runnables at 10 ms and 20 ms)

wheel Speed Plausibility Check including error and supervision example

API#

As no final API specification is available yet, these examples should be considered preliminary drafts. They demonstrate the metamodel concepts and shall reuse canonical VSS semantics where possible. Any non-standard catalogue path must be identified as an approved extension.

speed_hazard_detection.cpp
  1/********************************************************************************
  2* Copyright (c) 2026 ZF Friedrichshafen AG
  3*
  4* See the NOTICE file(s) distributed with this work for additional
  5* information regarding copyright ownership.
  6*
  7* This program and the accompanying materials are made available under the
  8* terms of the Apache License Version 2.0 which is available at
  9* https://www.apache.org/licenses/LICENSE-2.0
 10*
 11* SPDX-License-Identifier: Apache-2.0
 12*
 13* Contributors:
 14*   Thomas Pfleiderer - documentation
 15* *******************************************************************************
 16*/
 17 
 18#include "speed_hazard_detection.hpp"
 19#include <algorithm>
 20
 21namespace autoapiframework {
 22namespace speedHazardDetection {
 23
 24// ============================================================================
 25// SpeedHazardDetectionContext Implementation
 26// ============================================================================
 27
 28SpeedHazardDetectionContext::SpeedHazardDetectionContext()
 29    : isInitialized(false),
 30      previousSpeed(0.0f),
 31      previousSpeedTimestamp(0),
 32      hazardRequestActive(false),
 33      hazardRequestStartTimestamp(0),
 34      cycleCounter(0) {
 35}
 36
 37void SpeedHazardDetectionContext::reset() {
 38    isInitialized = false;
 39    previousSpeed = 0.0f;
 40    previousSpeedTimestamp = 0;
 41    hazardRequestActive = false;
 42    hazardRequestStartTimestamp = 0;
 43    cycleCounter = 0;
 44}
 45
 46bool SpeedHazardDetectionContext::getInitializationStatus() const {
 47    return isInitialized;
 48}
 49
 50uint32_t SpeedHazardDetectionContext::getCycleCount() const {
 51    return cycleCounter;
 52}
 53
 54// ============================================================================
 55// SpeedHazardDetection Function Implementation
 56// ============================================================================
 57
 58FunctionResult SpeedHazardDetection::init(
 59    SpeedHazardDetectionContext& context,
 60    const SpeedHazardDetectionParameters& parameters) {
 61    
 62    // Validate parameters
 63    if (parameters.speedHazardForwardThresholdPercent < 0.0f) {
 64        return FunctionResult::FAILURE;
 65    }
 66    
 67    if (parameters.hazardRequestDurationMs == 0) {
 68        return FunctionResult::FAILURE;
 69    }
 70    
 71    // Reset context state
 72    context.reset();
 73    
 74    // Initialize with safe defaults
 75    context.previousSpeed = 0.0f;
 76    context.previousSpeedTimestamp = 0;
 77    context.hazardRequestActive = false;
 78    context.hazardRequestStartTimestamp = 0;
 79    context.cycleCounter = 0;
 80    
 81    // Mark as initialized
 82    context.isInitialized = true;
 83    
 84    return FunctionResult::SUCCESS;
 85}
 86
 87FunctionResult SpeedHazardDetection::step(
 88    SpeedHazardDetectionContext& context,
 89    const SpeedHazardDetectionParameters& parameters,
 90    const SpeedHazardDetectionInputs& inputs,
 91    SpeedHazardDetectionOutputs& outputs) {
 92    
 93    // Check initialization
 94    if (!context.isInitialized) {
 95        outputs.functionStatus = FunctionResult::NOT_AVAILABLE;
 96        outputs.hazardRequest.value = false;
 97        outputs.hazardRequest.quality = DataQuality::INVALID;
 98        return FunctionResult::NOT_AVAILABLE;
 99    }
100    
101    // Increment cycle counter
102    context.cycleCounter++;
103    
104    // ========================================================================
105    // INPUT VALIDATION
106    // ========================================================================
107    
108    // Check vehicle speed data quality
109    if (inputs.vehicleSpeed.quality == DataQuality::INVALID ||
110        inputs.vehicleSpeed.quality == DataQuality::UNINITIALIZED) {
111        outputs.functionStatus = FunctionResult::FAILURE;
112        outputs.hazardRequest.quality = DataQuality::INVALID;
113        return FunctionResult::FAILURE;
114    }
115    
116    // Check acceleration data quality
117    if (inputs.accelerationLongitudinal.quality == DataQuality::INVALID ||
118        inputs.accelerationLongitudinal.quality == DataQuality::UNINITIALIZED) {
119        outputs.functionStatus = FunctionResult::FAILURE;
120        outputs.hazardRequest.quality = DataQuality::INVALID;
121        return FunctionResult::FAILURE;
122    }
123    
124    // Validate speed range
125    if (inputs.vehicleSpeed.value < 0.0f || inputs.vehicleSpeed.value > 300.0f) {
126        outputs.functionStatus = FunctionResult::FAILURE;
127        outputs.hazardRequest.quality = DataQuality::INVALID;
128        return FunctionResult::FAILURE;
129    }
130    
131    // Validate acceleration range
132    if (inputs.accelerationLongitudinal.value < -20.0f ||
133        inputs.accelerationLongitudinal.value > 20.0f) {
134        outputs.functionStatus = FunctionResult::FAILURE;
135        outputs.hazardRequest.quality = DataQuality::INVALID;
136        return FunctionResult::FAILURE;
137    }
138    
139    // ========================================================================
140    // SPEED INCREASE DETECTION LOGIC
141    // ========================================================================
142    
143    float currentSpeed = inputs.vehicleSpeed.value;
144    float speedIncrease = 0.0f;
145    
146    if (context.previousSpeedTimestamp > 0) {
147        // Calculate time delta in seconds
148        uint32_t timeDeltaMs = inputs.vehicleSpeed.updateTimestampMs - 
149                               context.previousSpeedTimestamp;
150        float timeDeltaS = timeDeltaMs / 1000.0f;
151        
152        // Ensure we have a valid time delta (at least 1ms)
153        if (timeDeltaS > 0.0f) {
154            speedIncrease = currentSpeed - context.previousSpeed;
155        }
156    }
157    
158    // Calculate relative speed increase in percent
159    float relativeSpeedIncreasePercent = 0.0f;
160    if (context.previousSpeed > 0.1f) {  // Avoid division by zero
161        relativeSpeedIncreasePercent = 
162            (speedIncrease / context.previousSpeed) * 100.0f;
163    }
164    
165    // ========================================================================
166    // HAZARD REQUEST DECISION LOGIC
167    // ========================================================================
168    
169    bool shouldActivateHazard = false;
170    
171    // Check if acceleration threshold triggers hazard for forward motion
172    if (currentSpeed > 5.0f &&  // Only when vehicle is actively moving
173        inputs.accelerationLongitudinal.value > 0.0f &&  // Forward acceleration
174        relativeSpeedIncreasePercent >= parameters.speedHazardForwardThresholdPercent) {
175        shouldActivateHazard = true;
176    }
177    
178    // ========================================================================
179    // HAZARD REQUEST LATCHING
180    // ========================================================================
181    
182    if (shouldActivateHazard) {
183        // Activate or re-trigger the hazard request
184        context.hazardRequestActive = true;
185        context.hazardRequestStartTimestamp = inputs.vehicleSpeed.updateTimestampMs;
186    }
187    
188    // Check if hazard request should remain active based on duration
189    if (context.hazardRequestActive) {
190        uint32_t hazardDurationElapsedMs = 
191            inputs.vehicleSpeed.updateTimestampMs - context.hazardRequestStartTimestamp;
192        
193        if (hazardDurationElapsedMs >= parameters.hazardRequestDurationMs) {
194            // Hazard request duration has expired
195            context.hazardRequestActive = false;
196        }
197    }
198    
199    // ========================================================================
200    // OUTPUT ASSIGNMENT
201    // ========================================================================
202    
203    outputs.hazardRequest.value = context.hazardRequestActive;
204    outputs.hazardRequest.quality = DataQuality::VALID;
205    outputs.hazardRequest.updateTimestampMs = inputs.vehicleSpeed.updateTimestampMs;
206    outputs.functionStatus = FunctionResult::SUCCESS;
207    
208    // ========================================================================
209    // STATE UPDATE FOR NEXT CYCLE
210    // ========================================================================
211    
212    context.previousSpeed = currentSpeed;
213    context.previousSpeedTimestamp = inputs.vehicleSpeed.updateTimestampMs;
214    
215    return FunctionResult::SUCCESS;
216}
217
218FunctionResult SpeedHazardDetection::terminate(
219    SpeedHazardDetectionContext& context,
220    SpeedHazardDetectionOutputs& outputs) {
221    
222    // Ensure all outputs are in safe state
223    outputs.hazardRequest.value = false;
224    outputs.hazardRequest.quality = DataQuality::VALID;
225    outputs.hazardRequest.updateTimestampMs = 0;
226    outputs.functionStatus = FunctionResult::SUCCESS;
227    
228    // Reset internal state
229    context.reset();
230    
231    return FunctionResult::SUCCESS;
232}
233
234} // namespace speedHazardDetection
235} // namespace autoapiframework
speed_hazard_detection.hpp
  1/********************************************************************************
  2* Copyright (c) 2026 ZF Friedrichshafen AG
  3*
  4* See the NOTICE file(s) distributed with this work for additional
  5* information regarding copyright ownership.
  6*
  7* This program and the accompanying materials are made available under the
  8* terms of the Apache License Version 2.0 which is available at
  9* https://www.apache.org/licenses/LICENSE-2.0
 10*
 11* SPDX-License-Identifier: Apache-2.0
 12*
 13* Contributors:
 14*   Thomas Pfleiderer - documentation
 15* *******************************************************************************
 16*/
 17 
 18#ifndef SPEED_HAZARD_DETECTION_HPP
 19#define SPEED_HAZARD_DETECTION_HPP
 20
 21#include <cstdint>
 22#include <cstring>
 23
 24namespace autoapiframework {
 25namespace speedHazardDetection {
 26
 27// ============================================================================
 28// ENUMS - Based on Eclipse-autoapiframework-Metamodel v0.4.0
 29// ============================================================================
 30
 31enum class ASIL {
 32    QM = 0,
 33    A = 1,
 34    B = 2,
 35    C = 3,
 36    D = 4
 37};
 38
 39enum class DataQuality {
 40    UNINITIALIZED = 0,
 41    INVALID = 1,
 42    VALID = 2
 43};
 44
 45enum class RunType {
 46    INIT = 0,
 47    CYCLIC = 1,
 48    EVENT = 2,
 49    TERMINATE = 3
 50};
 51
 52enum class ProtectionType {
 53    NONE = 0,
 54    COMPLEMENT = 1,
 55    OTHER = 2
 56};
 57
 58enum class FunctionResult {
 59    SUCCESS = 0,
 60    FAILURE = 1,
 61    NOT_AVAILABLE = 2
 62};
 63
 64// ============================================================================
 65// DATA INTERFACE STRUCTURES
 66// ============================================================================
 67
 68/**
 69 * @struct VehicleSpeed
 70 * @brief Current vehicle speed value.
 71 * 
 72 * VSS Path: Vehicle.Speed
 73 * Unit: km/h
 74 * Range: [0.0, 300.0]
 75 * ASIL: B
 76 * Update Period: 10ms
 77 */
 78struct VehicleSpeed {
 79    float value;                    ///< Speed value in km/h
 80    DataQuality quality;            ///< Data quality indicator
 81    uint32_t updateTimestampMs;     ///< Last update timestamp in milliseconds
 82    
 83    VehicleSpeed() 
 84        : value(0.0f), quality(DataQuality::UNINITIALIZED), updateTimestampMs(0) {}
 85    
 86    VehicleSpeed(float val)
 87        : value(val), quality(DataQuality::VALID), updateTimestampMs(0) {}
 88};
 89
 90/**
 91 * @struct VehicleAccelerationLongitudinal
 92 * @brief Longitudinal acceleration used to detect strong acceleration events.
 93 * 
 94 * VSS Path: Vehicle.Acceleration.Longitudinal
 95 * Unit: m/s²
 96 * Range: [-20.0, 20.0]
 97 * ASIL: B
 98 * Update Period: 10ms
 99 */
100struct VehicleAccelerationLongitudinal {
101    float value;                    ///< Acceleration value in m/s²
102    DataQuality quality;            ///< Data quality indicator
103    uint32_t updateTimestampMs;     ///< Last update timestamp in milliseconds
104    
105    VehicleAccelerationLongitudinal()
106        : value(0.0f), quality(DataQuality::UNINITIALIZED), updateTimestampMs(0) {}
107    
108    VehicleAccelerationLongitudinal(float val)
109        : value(val), quality(DataQuality::VALID), updateTimestampMs(0) {}
110};
111
112/**
113 * @struct VehicleBodyLightsHazardRequest
114 * @brief Hazard warning lights request signal.
115 * 
116 * VSS Path: Vehicle.Body.Lights.Hazard.Request
117 * Unit: boolean
118 * ASIL: B
119 * Update Period: 20ms
120 */
121struct VehicleBodyLightsHazardRequest {
122    bool value;                     ///< Request status: true = activate hazard lights
123    DataQuality quality;            ///< Data quality indicator
124    uint32_t updateTimestampMs;     ///< Last update timestamp in milliseconds
125    
126    VehicleBodyLightsHazardRequest()
127        : value(false), quality(DataQuality::UNINITIALIZED), updateTimestampMs(0) {}
128    
129    VehicleBodyLightsHazardRequest(bool val)
130        : value(val), quality(DataQuality::VALID), updateTimestampMs(0) {}
131};
132
133/**
134 * @struct VehicleSpeedQualifier
135 * @brief Quality qualifier for Vehicle.Speed value.
136 * 
137 * VSS Path: Vehicle.Speed.Qualifier
138 * Unit: code (enum-based)
139 * ASIL: QM
140 * Update Period: 10ms
141 */
142struct VehicleSpeedQualifier {
143    uint8_t value;                  ///< Quality code (0-5)
144    DataQuality quality;            ///< Data quality indicator
145    uint32_t updateTimestampMs;     ///< Last update timestamp in milliseconds
146    
147    VehicleSpeedQualifier()
148        : value(0), quality(DataQuality::UNINITIALIZED), updateTimestampMs(0) {}
149    
150    VehicleSpeedQualifier(uint8_t val)
151        : value(val), quality(DataQuality::VALID), updateTimestampMs(0) {}
152};
153
154// ============================================================================
155// PARAMETER STRUCTURES
156// ============================================================================
157
158/**
159 * @struct SpeedHazardDetectionParameters
160 * @brief Configuration parameters for SpeedHazardDetection function.
161 */
162struct SpeedHazardDetectionParameters {
163    /// Relative speed increase threshold in percent for forward acceleration
164    float speedHazardForwardThresholdPercent;
165    
166    /// Hold time for hazard request after trigger in milliseconds
167    uint32_t hazardRequestDurationMs;
168    
169    SpeedHazardDetectionParameters()
170        : speedHazardForwardThresholdPercent(10.0f),
171          hazardRequestDurationMs(3000) {}
172};
173
174// ============================================================================
175// FUNCTION INPUT/OUTPUT CONTEXT
176// ============================================================================
177
178/**
179 * @struct SpeedHazardDetectionInputs
180 * @brief All input signals for the SpeedHazardDetection function.
181 */
182struct SpeedHazardDetectionInputs {
183    VehicleSpeed vehicleSpeed;
184    VehicleAccelerationLongitudinal accelerationLongitudinal;
185    VehicleSpeedQualifier speedQualifier;
186    
187    void reset() {
188        vehicleSpeed = VehicleSpeed();
189        accelerationLongitudinal = VehicleAccelerationLongitudinal();
190        speedQualifier = VehicleSpeedQualifier();
191    }
192};
193
194/**
195 * @struct SpeedHazardDetectionOutputs
196 * @brief All output signals for the SpeedHazardDetection function.
197 */
198struct SpeedHazardDetectionOutputs {
199    VehicleBodyLightsHazardRequest hazardRequest;
200    FunctionResult functionStatus;
201    
202    SpeedHazardDetectionOutputs()
203        : hazardRequest(), functionStatus(FunctionResult::SUCCESS) {}
204    
205    void reset() {
206        hazardRequest = VehicleBodyLightsHazardRequest();
207        functionStatus = FunctionResult::SUCCESS;
208    }
209};
210
211// ============================================================================
212// FUNCTION CONTEXT / STATE
213// ============================================================================
214
215/**
216 * @class SpeedHazardDetectionContext
217 * @brief Internal state and context for SpeedHazardDetection function.
218 * 
219 * This structure maintains all internal state variables required for
220 * the cyclic execution of the speed hazard detection algorithm.
221 */
222class SpeedHazardDetectionContext {
223public:
224    // Initialization state
225    bool isInitialized;
226    
227    // Previous cycle state
228    float previousSpeed;
229    uint32_t previousSpeedTimestamp;
230    
231    // Hazard request latching state
232    bool hazardRequestActive;
233    uint32_t hazardRequestStartTimestamp;
234    
235    // Cycle counter
236    uint32_t cycleCounter;
237    
238    /**
239     * @brief Constructor - initializes context with default values.
240     */
241    SpeedHazardDetectionContext();
242    
243    /**
244     * @brief Reset context to initial state.
245     */
246    void reset();
247    
248    /**
249     * @brief Get initialization status.
250     * @return true if function is initialized, false otherwise
251     */
252    bool getInitializationStatus() const;
253    
254    /**
255     * @brief Get current cycle count.
256     * @return Current cycle counter value
257     */
258    uint32_t getCycleCount() const;
259};
260
261// ============================================================================
262// FUNCTION INTERFACE
263// ============================================================================
264
265/**
266 * @class SpeedHazardDetection
267 * @brief Static C++ API for Speed Hazard Detection Function.
268 * 
269 * Specification: SpeedHazardDetection v1.0.0
270 * Meta Model: Eclipse-autoapiframework-Metamodel v0.4.0
271 * 
272 * Description:
273 *   Detects rapid acceleration and requests hazard warning lights if the
274 *   configured threshold is exceeded.
275 *
276 * Note:
277 *   qualityCode is runtime companion information and is therefore not
278 *   represented as a static metadata field in the function specification.
279 */
280class SpeedHazardDetection {
281public:
282    /**
283     * @brief Initialize the Speed Hazard Detection function.
284     * 
285     * @param context Reference to the function context
286     * @param parameters Reference to the function parameters
287     * @return FunctionResult indicating success or error status
288     * 
289     * Run Type: init
290     * ASIL: B
291     * 
292     * Initializes internal states and latched outputs. Must be called once
293     * before the first cyclic execution.
294     */
295    static FunctionResult init(
296        SpeedHazardDetectionContext& context,
297        const SpeedHazardDetectionParameters& parameters
298    );
299    
300    /**
301     * @brief Execute one cycle of Speed Hazard Detection.
302     * 
303     * @param context Reference to the function context
304     * @param parameters Reference to the function parameters
305     * @param inputs Reference to the input signals
306     * @param outputs Reference to the output signals (will be updated)
307     * @return FunctionResult indicating success or error status
308     * 
309     * Run Type: cyclic
310     * ASIL: B
311     * Cycle Time: 20ms
312     * 
313     * Evaluates inputs and calculates hazard request output.
314     * The algorithm:
315     *   1. Validates input signal quality
316     *   2. Calculates relative speed increase since last cycle
317     *   3. Compares against configured threshold
318     *   4. Activates hazard request if threshold exceeded
319     *   5. Maintains hazard request latch for configured duration
320     */
321    static FunctionResult step(
322        SpeedHazardDetectionContext& context,
323        const SpeedHazardDetectionParameters& parameters,
324        const SpeedHazardDetectionInputs& inputs,
325        SpeedHazardDetectionOutputs& outputs
326    );
327    
328    /**
329     * @brief Terminate the Speed Hazard Detection function.
330     * 
331     * @param context Reference to the function context
332     * @param outputs Reference to the output signals (will be updated)
333     * @return FunctionResult indicating success or error status
334     * 
335     * Run Type: terminate
336     * ASIL: QM
337     * 
338     * Shutdown cleanup for deterministic deactivation. Ensures all
339     * outputs are reset to safe defaults.
340     */
341    static FunctionResult terminate(
342        SpeedHazardDetectionContext& context,
343        SpeedHazardDetectionOutputs& outputs
344    );
345};
346
347} // namespace speedHazardDetection
348} // namespace autoapiframework
349
350#endif // SPEED_HAZARD_DETECTION_HPP