..
  *******************************************************************************
  Copyright (c) 2021-2024 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
  *******************************************************************************

.. _algorithm_longitudinal:

Algorithm_Longitudinal
######################


This module is responsible for the control of the vehicle's longitudinal
behavior. It receives the command variables from a driver behavior model and generates 
the accelerator and brake pedal position and the current gear of the driver to match
these command variables. The pedal positions and the gear can then be forwarded
to a vehicle dynamics module like :ref:`dynamics_regular_driving`.
The actuation of the clutch pedal is currently not simulated by the modul

.. _algorithm_longitudinal_detailed_description:

Detailed description of the module's features
=============================================

.. _algorithm_longitudinal_detailed_description_inverted_dynamics_model_:

Inverted longitudinal dynamics model
------------------------------------

The inverted longitudinal dynamics model produces :math:`act_{olc,stat}`
by utilizing an inverted powertrain and brake system model. The powertrain model 
and all of its parameters and state variables are illustrated in the following image. 
The brake model is not worth illustrating, as it directly applies on the required acceleration 
:math:`a_{set}` of the vehicle.

.. _image_PowertrainModel1_:

.. figure:: _static/images/PowertrainModel.svg
   :alt: Illustration of the powertrain model and its parameters and state variables

   Illustration of the powertrain model and its parameters and state variables


The core element of all calculations in this model is speed and acceleration.
The speed :math:`n_{wheel}` at the wheels is constraint by the current velocity
:math:`v_{act}` of the vehicle and the static wheel radius :math:`r_{stat}`:

.. math::
   n_{wheel} = \frac{v_{act}}{r_{stat}} \cdot \frac{60}{2 \cdot \pi}
   

where :math:`n_{wheel}` is specified in :math:`rpm` (revolutions per minute) and :math:`v_{act}` is
defined in :math:`m/s`, which requires the conversion term at the end of the equation.
As the equation also illustrates, only a simple rolling relation defines the
model and there is no simulation of tire-road-friction and tire slip involved.

The speed :math:`n_{eng}` of the engine is constraint by the speed
:math:`n_{wheel}` of the wheels, the ratio :math:`i_{a}` of the axle, and the
current ratio :math:`i_{g}` of the gearbox, depending of the current gear:

.. math::
   n_{eng} = n_{wheel} \cdot i_{a} \cdot i_{g}
   

The required acceleration :math:`a_{set}` determines the torque :math:`M_{wheel}`
at the wheels, as the overall mass :math:`m` of the vehicle has to be accelerated by
this torque:

.. math::
   M_{wheel} = m \cdot a_{set} \cdot r_{stat}


As the equation illustrates, no driving resistances other than the inertia of
the vehicle are simulated by this model. The required torque :math:`M_{wheel}`
at the wheels must be generated by the engine, considering the ratios of the
powertrain:

.. math::
   M_{eng} = \frac{M_{wheel}}{i_{a} \cdot i_{g}}


As the current speed :math:`n_{eng}` of the engine, the required acceleration
:math:`a_{set}` of the vehicle, and the required torque :math:`M_{eng}` of the
engine are known or defined by the above equations, this knowledge can be used
to determine the estimated positions of the accelerator and the brake pedal or
to calculate the optimal gear for the required acceleration :math:`a_{set}`,
if a positive acceleration is needed. For the accelerator pedal and optimal gear
calculation, there is still some missing knowledge about the engine itself.
The relationship between the current engine speed :math:`n_{eng}` and the
possible engine torque :math:`M_{eng}` is determined by a simple engine map,
which is illustrated in the following image:

.. _image_EngineMap_:

.. figure:: _static/images/EngineMap.svg
   :alt: Simplified engine map used for the inverted powertrain model

   Simplified engine map used for the inverted powertrain model


The engine map is defined by two characteristic curves:


* :math:`M_{eng,max}` defines the maximum torque, which can be produced by the
  engine at a specific engine speed :math:`n_{eng}`. This is directly connected
  with the maximum possible actuation of the accelerator pedal.
* :math:`M_{eng,drag}` defines the drag torque, which is produced by the engine
  at a specific engine speed :math:`n_{eng}`, if the accelerator pedal is not
  actuated at all.

The two characteristic curves are only defined between the minimum and maximum
possible speed of the engine. As the two characteristic curves are directly
related to a full actuation (:math:`act_{olc,stat} = 1`) and no actuation
(:math:`act_{olc,stat} = 0`) of the accelerator pedal, the estimated pedal
position for the accelerator pedal :math:`act_{olc,stat}`, which produces the
currently required engine torque :math:`M_{eng}`, can be calculated by linear
interpolation between these two characteristic curves at the current engine
speed :math:`n_{eng}`.

Analogous for the brake pedal position:


* The maximum actuation of the brake pedal (:math:`act_{olc,stat} = -1`) is
  directly connected with the maximum possible deceleration of the vehicle, which
  is simply set to 1G (:math:`= 9.81 m/s^2`).
* No actuation of the brake pedal (:math:`act_{olc,stat} = 0`) also produces no
  deceleration.

Between these two possible decelerations, the estimated brake pedal position to
produce the required acceleration :math:`a_{set}` is calculated by linear
interpolation.

The logic for the calculation of the static controller output :math:`act_{olc,stat}`,
utilizing the considerations above, is defined as follows:

If the required acceleration :math:`a_{set}` is smaller than zero, it can be
produced by the engine drag torque or the brake system. If the engine drag
torque :math:`M_{eng,drag}` at the current engine speed :math:`n_{eng}` is not
strong enough to meet the engine torque :math:`M_{eng}`, which would be
necessary to produce :math:`a_{set}`, an **additional** actuation of the brake
pedal is applied (the driver does not open the clutch, so the engine drag torque
is also applied to the wheels). This mechanism is not considering a change in
gears, but uses the current gear of the gearbox (the driver does not consider to
shift down for a stronger effect of the engine drag torque).

If the required acceleration :math:`a_{set}` is greater than or equal to zero,
it can only be produced by the powertrain. First of all, the optimal gear to
produce the engine torque :math:`M_{eng}` required for :math:`a_{set}` is
calculated, which is described in :ref:`the subsequent subsection<algorithm_longitudinal_openloop_optimal_gear_>`.
With this chosen gear, the current engine speed :math:`n_{eng}` is calculated.
:math:`n_{eng}` is used to determine the maximum engine torque :math:`M_{eng,max}`
and the engine drag torque :math:`M_{eng,drag}` from the characteristic curves.
As these two values are connected to a full actuation and no actuation of the
accelerator pedal, the estimated accelerator pedal position, which is necessary
to produce the required acceleration :math:`a_{set}`, can be calculated by
linear interpolation.

The state variable :math:`v_{act}` is received from the module :ref:`sensor_driver`,
the required acceleration :math:`a_{set}` is received from a driver behavior
model, and the vehicle parameters :math:`m`, :math:`r_{stat}`, :math:`i_{a}`, :math:`i_{g}` per gear,
and the information about the engine map are received from the module :ref:`parameters_vehicle`.

The calculations above are done in the function CalculatePedalPositions, which is called in 
the function CalculatePedalPositionAndGear of Algorithm_Longitudinal.

.. _algorithm_longitudinal_openloop_optimal_gear_:

Algorithm for optimal gear determination
----------------------------------------

The algorithm for the determination of the optimal gear for the required
acceleration :math:`a_{set}` is implemented in the function CalculateGearAndEngineSpeed. 
It is called within the function CalculatePedalPositionAndGear of Algorithm_Longitudinal, 
which applies the :ref:`inverted longitudinal dynamics model<algorithm_longitudinal_detailed_description_inverted_dynamics_model_>`. 
The algorithm receives the current velocity :math:`v_{act}` of the vehicle and the required acceleration :math:`a_{set}`.

Within a for-loop over all gears, the engine speed :math:`n_{eng}` is calculated
for each gear, which would result from the current velocity :math:`v_{act}`,
as well as the maximum engine torque :math:`M_{eng,max}` and the engine drag
torque :math:`M_{eng,drag}` resulting from these engine speeds. Violating the
minimum engine speed :math:`n_{eng,min}` and the maximum engine speed :math:`n_{eng,max}`
is not considered in this step (resulting engine speeds are written as they result
from the powertrain calculation and the engine torques are set to the lower or
upper limits of the characteristic curves respectively, if the engine speed
range is violated).

The results above are further processed in a second for-loop over all gears.
The following aspects are checked to determine, if a gear fits the current
required state:


* Is the resulting engine speed :math:`n_{eng}` within the range of :math:`n_{eng,min}`
  and :math:`n_{eng,max}`?
* Is the resulting engine torque :math:`M_{eng}` to produce the required
  acceleration :math:`a_{set}` within the range of :math:`M_{eng,drag}` and :math:`M_{eng,max}`?

The lowest gear that fits these criteria sets a Boolean foundGear true and the
results (gear number and resulting engine speed :math:`n_{eng}`) are written in
the result vector. This is done for all further gears, until a gear does not fit
the requirements anymore. This initiates the return of the last sufficient gear
and its resulting engine speed :math:`n_{eng}`. A short example should
illustrate this logic:


#. The 2nd gear activates the Boolean foundGear, because :math:`n_{eng}` does
   not exceed :math:`n_{eng,max}` anymore
#. The 4th gear activates the return of the results, because the required engine
   torque :math:`M_{eng}` would exceed the maximum possible engine torque :math:`M_{eng,max}`
   at the corresponding engine speed :math:`n_{eng}`
#. The algorithm chooses the 3rd gear as optimum and returns it and its
   corresponding engine speed :math:`n_{eng}`

This logic therefore guarantees, that always the highest possible gear is chosen
by the driver.
