..
  *******************************************************************************
  Copyright (c) 2021 in-tech GmbH
                2022 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)

  This program and the accompanying materials are made available under the
  terms of the Eclipse Public License 2.0 which is available at
  http://www.eclipse.org/legal/epl-2.0.

  SPDX-License-Identifier: EPL-2.0
  *******************************************************************************

.. _components_vehiclecomponents:

VehicleComponents
-----------------

.. _components_aeb:

AEB
~~~

The Autonomous Emergency Braking system checks if a collision is likely to occur in the near future and, if necessary, brakes to avoid the collision.
In each timestep, the system evaluates all objects detected by a Sensor and calculates the time to collision (TTC) for this object based on the perceived movement of the object.
If, for any object, the TTC is lower than the threshold of the component, then the component gets activated. The system deactivates if the TTC is larger than 1,5 times the threshold of the component.

.. table::
   :class: tight-table

   ====================================== ====== ==== ===================================================================================
   Attribute                              Type   Unit Description
   ====================================== ====== ==== ===================================================================================
   CollisionDetectionLongitudinalBoundary Double m    Additional length added the vehicle boundary when checking for collision detection
   CollisionDetectionLateralBoundary      Double m    Additional width added the vehicle boundary when checking for collision detection
   TTC                                    Double s    Time to collision which is used to trigger AEB
   Acceleration                           Double m/s² Braking acceleration when activated
   ====================================== ====== ==== ===================================================================================

.. code-block:: xml

   <ProfileGroup Type="AEB">
       <Profile Type="AEB" Name="AEB1">
           <Double Key="CollisionDetectionLongitudinalBoundary" Value="4.0"/>
           <Double Key="CollisionDetectionLateralBoundary" Value="1.5"/>
           <Double Key="TTC" Value="2.0"/>
           <Double Key="Acceleration" Value="-2"/>
       </Profile>
       ...
   </ProfileGroup>

.. _components_trajectoryfollower:

DynamicsTrajectoryFollower
~~~~~~~~~~~~~~~~~~~~~~~~~~

This module forces agents to drive according to a specific trajectory. The trajectory is defined in the scenario. This module is disabled by default and is activated if a trajectory from openSCENARIO is triggered.
It is always important that the trajectories matches the current scenery file, otherwise the Agent could be placed outside of valid lanes. If the agent gets placed on a invalid position, it will be deleted.

All attributes are required.

.. table::
   :class: tight-table

   ===================== ==== =======================================================================================================================
   Attribute             Type Description
   ===================== ==== =======================================================================================================================
   AutomaticDeactivation Bool If true, the trajectory follower relinquishes control of the vehicle after the final instruction in the TrajectoryFile.
   EnforceTrajectory     Bool If true, the trajectory follower overrides external input related to the vehicle's travel.
   ===================== ==== =======================================================================================================================

.. code-block:: xml

   <ProfileGroup Type="DynamicsTrajectoryFollower">
       <Profile Name="BasicTrajectoryFollower">
           <Bool Key="AutomaticDeactivation" Value="true"/>
           <Bool Key="EnforceTrajectory" Value="true"/>
       </Profile>
   </ProfileGroup>

.. _components_fmuwrapper:

FMU Wrapper
~~~~~~~~~~~~

The FMU Wrapper provides a connection to arbitrary FMUs (Functional Mock-up Unit).
An FMU has to be compatible with the FMI 1.0 or the FMI 2.0 specification (Functional Mock-up Interface) and has to be ABI (Application Binary Interface) compatible with the opSimulation binary.

Additional reading about FMI is provided by the FMI standard website at https://fmi-standard.org/.
For interfacing the FMUs in openPASS, the Modelon FMI Library is used, which is recommended on the FMI standard website. See https://jmodelica.org/.

**FMU package format**

FMI defines a packaging format for FMUs.
The used container format is ZIP.
It basically contains - among other parts -  the compiled FMU code (as ``*.dll`` or ``*.so``, depending on the platform) and the ``modelDescription.xml``.
Latter provides meta-data about the FMU, i. e.
- Author information
- Model name, identifier and description
- Generation timestamp
- Name and datatype of model variables (inputs and outputs)


**Architectural overview**

The wrapper is instantiated as a component of an agent.
It reads the input variables for the FMU from the simulation and provides it the FMU and reads the output of the FMU and forwards it via signals to other agent components.

.. image:: _static/images/FmuWrapperOverview.svg
      :alt: |op| FMU wrapper architectural overview

**Framework channels**

The wrapper can use input and output signals via *Channels* as every other agent component does.
Framework channels (signals) can provide data and can also be written to by the wrapper.
In addition, the wrapper is able to access the \c AgentInterface and \c WorldInterface methods.

**FMI variables**

Communication with the FMU happens via FMI variables (inputs and outputs).
The wrapper will read in available variables from ``modelDescription.xml`` in the FMU package.
These variables need to be mapped to variables and signals of OpenPASS in the VehicleComponentProfile.

FMI 1.0 supports these standard datatypes:
- bool
- integer
- real
- string

**Configuration**

Configuration of a particular FMU takes place in ``ProfilesCatalog.xml``.
An example of a static system configuration can be found here "sim/contrib/examples/Configurations/StaticOSMPSensorDataToTrafficUpdateStepper".

The following parameters are always required for the FmuWrapper. Depending on the FmuHandler additional parameters may be needed.

.. table::
   :class: tight-table

   ==================== ======= ======= ================================================================================================================================
   Key                  Type    Default Description
   ==================== ======= ======= ================================================================================================================================
   FmuPath              string  \-       Path to FMU file, either absolute or relative to the simulator's configuration directory.
   Logging              bool    true    If set to true, FMU initialization and execution task are logged to a text file.
   CsvOutput            bool    true    If set to true, FMI outputs are logged to a CSV file.
   UnzipOncePerInstance bool    true    If set to true, unpack the FMU once for each running instance, instead of once per FMU file (forced to ``true`` on Linux systems)
   FmuType              string  \-       Type of the FMU ("OSMP" supported)
   ==================== ======= ======= ================================================================================================================================

.. literalinclude:: /../../../repo/sim/contrib/examples/Configurations/DynamicOSMPSensorDataToTUStepper/ProfilesCatalog.xml
   :language: xml
   :dedent: 2
   :start-at: <ProfileGroup Type="FMU1">
   :end-at: </ProfileGroup>

Upon instantiation of the FMU wrapper, it will extract the FMU ZIP file to a temporary directory.
Then the ``modelDescription.xml`` is parsed and the FMU is checked for compatibility.

If the parameter ``CsvOutput`` is set to `true`, a subfolder "FmuWrapper/Agent<ID>" will be created in the simulator's "results" directory.
"<ID>" is replaced with the agent id.
FMI output data will be logged to a file inside this directory.
The filename consists of the FMU's name and extension "csv".
This output can then be used for visualization in a spreadsheet application or it may be processed in any other way.

Same goes for parameter ``Logging`` (having "log" as output file extension).

If ``UnzipOncePerInstance`` is set to `true`, the FMU will be unzipped multiple times into different temporary directories.

**OSMP FMU**

OSMP allows to pass input to the FMU as OSI messages as well as receive output as OSI message.
For more information on OSMP see https://github.com/OpenSimulationInterface/osi-sensor-model-packaging.

The OsmpFmuHandler has the following additional (optional) parameters:

.. table::
   :class: tight-table

   ========================================================= ==================== ===============================================================================================================================================
   Key                                                       Type                 Description
   ========================================================= ==================== ===============================================================================================================================================
   Init\_\ *var_name*                                        string               *var_name* references an FMU variable (as defined in FMU's modelDescription.xml) to which a specific OSI message is sent during initialization  Allowed values: `GroundTruth`
   Input\_\ *var_name*                                       string               *var_name* references an FMU variable (as defined in FMU's modelDescription.xml) to which a specific OSI message is sent  Allowed values: `SensorView`, `SensorViewConfig`, `SensorData`, `TrafficCommand`
   Output\_\ *var_name*                                      string               *var_name* references an FMU variable (as defined in FMU's modelDescription.xml) from which a specific OSI message is received  Allowed values: `SensorViewConfigRequest`, `SensorData`, `TrafficUpdate`, ``MotionCommand``
   Parameter\_\ *var_name*                                   any                  The value of the parameter is assigned to the FMU variable *var_name*
   Parameter\_\ *transformation*\ [*mapping* ]\_\ *name*     string/string/any\*  Same as Parameter\_\ *name* but with an preceding *transformation* according to a *mapping*. |br| Currently, only mappings between the same types are supported. |br| \*;When using `TransformList` as *transformation*, the type of the data is expected to be a string and the string must be a comma separated list of values. |br|  |br| Allowed values: |br| *transformation*: `Transform`, `TransformList` |br| *mapping*: `ScenarioName>Id` |br|  |br| Example: `Parameter_TransformList[ScenarioName>Id]\_\ *name*`
   WriteSensorViewOutput                                     bool                 If true the SensorView is written into a JSON file
   WriteTrafficCommandOutput                                 bool                 If true the TrafficCommand is written into a JSON file
   WriteGroundTruthOutput                                    bool                 If true the GroundTruth is written into a JSON file
   WriteSensorDataOutput                                     bool                 If true the SensorData is written into a JSON file
   WriteTrafficUpdateOutput                                  bool                 If true the TrafficUpdate is written into a JSON file
   EnforceDoubleBuffering                                    bool                 If true the wrapper will throw an error if FMU doesn't use double buffering. Defaults to false.
   ========================================================= ==================== ===============================================================================================================================================

The type of OSI messages the OsmpFmuHandler sends and receives is defined by its parameters. Only messages for which an FMU variable is given in the configuration are sent/received.
An additional parameter defines whether the message should be logged as JSON file for every agent and every timestep (see table above).

Currently these messages are supported:

* SensorView: SensorView generated from the GroundTruth with this agent is host vehicle.
* SensorViewConfig, SensorViewConfigRequest: Configuration of a sensor according to OSMP.
* TrafficCommand: Trajectory from openSCENARIO, that will be converted into a TrafficCommand.
* SensorData: Output of a sensor. Can be input and/or output of an FMU. Received SensorData is forwarded to other components as SensorDataSignal.
* TrafficUpdate: Will be converted to a DynamicsSignal.
* MotionCommand: Will be converted to a DynamicsSignal. Has priority over TrafficUpdate.

**Generic Handler**

The Generic Fmu Handler allows to link Simulink models or any other FMU to |op|.
It lets the user link any input variables of the FMU to values of the Agent in the simulation and any output values of the FMU to signals, that are forwarded to other components.
These mappings are defined with the following additional parameters, where the key describes the meaning in the simulation and the value is the variable in the modelDescription.xml:

.. table::
   :class: tight-table

   ======================= ======= ===========================================================================================================
   Key                     Type    Description
   ======================= ======= ===========================================================================================================
   Parameter\_\ *varName*  any     Mapping of a fixed value (bool, integer, double, string) to an FMU input.
                                   ``varName`` references the FMU input defined in the modelDescription.xml.
   Input\_\ *varName*      string  Mapping of a specific value of the simulation to an FMU input.
                                   ``varName`` references the FMU input defined in the modelDescription.xml.
                                   The value of this parameter has to be one of the types specified in the table below.
   Output\_\ *varName*     string  Mapping of a FMU output to a specific field in a specific signal.
                                   ``varName`` references the FMU output defined in the modelDescription.xml.
                                   The value of this parameter has to be one of the types specified in the signal table below.
   ======================= ======= ===========================================================================================================

The allowed inputs (simulation values) are as follows:

.. table::
   :class: tight-table

   ========================================= ================== ==================================================================================================
   Type                                      FMU Variable Type  Calculation
   ========================================= ================== ==================================================================================================
   VelocityEgo                               Real               Absolute velocity (length of the velocity vector) at reference point
   AccelerationEgo                           Real               Longitudinal acceleration at reference point
   CentripetalAccelerationEgo                Real               Centripetal acceleration at reference point
   SteeringWheelEgo                          Real               Angle of the steering wheel (in radian)
   AccelerationPedalPositionEgo              Real               Position of the acceleration pedal in the interval [0, 1]
   BrakePedalPositionEgo                     Real               Position of the brake pedal in the interval [0, 1]
   DistanceRefToFrontEdgeEgo                 Real               Distance between the reference point and the front of the agent (static)
   PositionXEgo                              Real               X position of the reference point
   PositionYEgo                              Real               Y position of the reference point
   YawEgo                                    Real               Yaw of the reference point
   LaneEgo                                   Integer            Lane id of the MainLocatePoint on the route (0, if off route)
   PositionSEgo                              Real               S position of the reference point on the route (0, if off route)
   PositionTEgo                              Real               T position of the reference point on the route (0, if off route)
   ExistenceFront                            Boolean            true, if there is a object in front on the own lane (any range), false otherwise
   PositionXFront                            Real               X position of front object reference point (0, if no front object)
   PositionYFront                            Real               Y position of front object reference point (0, if no front object)
   YawFront                                  Real               Yaw of front object reference point (0, if no front object)
   PositionSFront                            Real               S position of front object reference point on ego route (0, if no front object)
   PositionTFront                            Real               T position of front object reference point on ego route (0, if no front object)
   RelativeDistanceFront                     Real               Net distance to front object along route (0, if no front object)
   WidthFront                                Real               Width of front object (0, if no front object)
   LengthFront                               Real               Length of front object (0, if no front object)
   DistanceRefToFrontEdgeFront               Real               Distance between the reference point and the front of the front object (0, if no front object)
   VelocityFront                             Real               Absolute velocity of front object at reference point (0, if no front object)
   LaneFront                                 Integer            Lane id of the reference point of the front object on the ego route (0, if no front object)
   ExistenceFrontFront                       Boolean            true, if there are at least two objects in front on the own lane (any range), false otherwise
   PositionXFrontFront                       Real               X position of second front object reference point (0, if no second front object)
   PositionYFrontFront                       Real               Y position of second front object reference point (0, if no second front object)
   RelativeDistanceFrontFront                Real               Net distance to second front object reference point (0, if no second front object)
   VelocityFrontFront                        Real               Absolute velocity of second front object reference point (0, if no second front object)
   LaneFrontFront                            Integer            Lane id of the reference point of second front object reference point (0, if no second front object)
   LaneCountLeft                             Integer            Number of lanes to the left of MainLocatePoint of type Driving, Exit, Entry, OnRamp or OffRamp
   LaneCountRight                            Integer            Number of lanes to the right of MainLocatePoint of type Driving, Exit, Entry, OnRamp or OffRamp
   SpeedLimit\_\ *X*                         Real               Speed limit in effect in distance *X* meters from MainLocatePoint (999, if no speed limit)
   RoadCurvature\_\ *X*                      Real               Road curvature in distance *X* meters from MainLocatePoint
   ========================================= ================== ==================================================================================================


If the FmuWrapper is linked to at least one sensor with InputId "Camera", the following additional inputs are available.
The objects seen by this sensor(s) are sorted by distance from the agent and accessed by indices starting from 0.
For each object the values listed in the following table are available where *X* is the index of the object (between 0 and 9).
If there are less objects than *X*, a default value is set (-1 for the Id, 0 for the other values).
   
.. table::
   :class: tight-table

   ============================================ ================== ========================================================================================================
   Type                                         FMU Variable Type  Calculation
   ============================================ ================== ========================================================================================================
   SensorFusionObjectId\_\ *X*                  Integer            Id of the object
   SensorFusionNumberOfDetectingSensors\_\ *X*  Integer            Number of sensors detecting the object
   SensorFusionRelativeS\_\ *X*                 Real               Distance between reference points along route (NaN, if object not on route)
   SensorFusionRelativeNetS\_\ *X*              Real               Net distance along route (NaN, if object not on route)
   SensorFusionRelativeT\_\ *X*                 Real               Lateral obstruction for MainLocatePoint (NaN, if object not on route) (see :ref:`world_getobstruction`)
   SensorFusionRelativeNetLeft\_\ *X*           Real               Lateral obstruction for leftmost point (NaN, if object not on route)
   SensorFusionRelativeNetRight\_\ *X*          Real               Lateral obstruction for rightmost point (NaN, if object not on route)
   SensorFusionRelativeNetX\_\ *X*              Real               Net distance between bounding boxes in x
   SensorFusionRelativeNetY\_\ *X*              Real               Net distance between bounding boxes in y
   SensorFusionLane\_\ *X*                      Integer            Lane of MainLocatePoint
   SensorFusionVelocity\_\ *X*                  Real               Absolute velocity at reference point
   SensorFusionVelocityX\_\ *X*                 Real               Velocity in x at reference point
   SensorFusionVelocityY\_\ *X*                 Real               Velocity in y at reference point
   SensorFusionYaw\_\ *X*                       Real               Yaw
   ============================================ ================== ========================================================================================================

The FMU wrapper can output one or more of these signals:
AccelerationSignal, LongitudinalSignal, SteeringSignal and DynamicsSignal

The name of the signal field has to be specified after the signal name.
This means the output type is one of the following:

.. table::
   :class: tight-table

   ====================================== ==================
   Type                                   FMU Variable Type
   ====================================== ==================
   ComponentState                         Enum
   AccelerationSignal_Acceleration        Real
   LongitudinalSignal_AccPedalPos         Real
   LongitudinalSignal_BrakePedalPos       Real
   LongitudinalSignal_Gear                Int
   SteeringSignal_SteeringWheelAngle      Real
   DynamicsSignal_Acceleration            Real
   DynamicsSignal_Velocity                Real
   DynamicsSignal_PositionX               Real
   DynamicsSignal_PositionY               Real
   DynamicsSignal_Yaw                     Real
   DynamicsSignal_YawRate                 Real
   DynamicsSignal_YawAcceleration         Real
   DynamicsSignal_SteeringWheelAngle      Real
   DynamicsSignal_CentripetalAcceleration Real
   DynamicsSignal_TravelDistance          Real
   ====================================== ==================

If one of these fields of a signal (except ComponentState) is mapped to an FMU variable, all fields of this signal have to be mapped.
If the ComponentState is mapped to a FMU variable, it is used for all signals, otherwise it defaults to Acting.


.. _components_geometric2d:

SensorGeometric2D
~~~~~~~~~~~~~~~~~

This sensor is selected, when a sensor is parameterized as ProfileGroup "Geometric2D".

.. table::
   :class: tight-table

   =============================== ====== ==== ==================================================================================================
   Parameter                       Type   Unit Description
   =============================== ====== ==== ==================================================================================================
   DetectionRange                  Double m    Detection range
   EnableVisualObstruction         Bool        Activates 2D sensor obstruction calculation
   FailureProbability              Double      Probability object is not detected although it is visible
   Latency                         Double s    Sensor latency
   OpeningAngleH                   Double rad  Horizontal opening angle
   RequiredPercentageOfVisibleArea Double      Required percentage of an object within the sensor cone to trigger a detection
   =============================== ====== ==== ==================================================================================================

.. literalinclude:: /../../../repo/sim/contrib/examples/Configurations/ADAS_AEB_PreventingCollisionWithObstacle/ProfilesCatalog.xml
   :language: xml
   :dedent: 2
   :start-at: <ProfileGroup Type="Geometric2D">
   :end-at: </ProfileGroup>

.. note:: 
   
   Sensors also need a mounting position, defined w.r.t. the coordinate system of the vehicle (center of rear axis).
   See also :ref:`profilescatalog_vehicleprofiles`.

.. |br| raw:: html

      <br>
