Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2026-2026 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MSCFModel_NaSch.h
15 : /// @author Jerry Lin
16 : /// @date Thu, 13 Aug 2026
17 : ///
18 : // The Nagel-Schreckenberg (1992) cellular automaton car-following model
19 : /****************************************************************************/
20 : #pragma once
21 : #include <config.h>
22 :
23 : #include "MSCFModel.h"
24 : #include <utils/xml/SUMOXMLDefinitions.h>
25 :
26 :
27 : // ===========================================================================
28 : // class definitions
29 : // ===========================================================================
30 : /** @class MSCFModel_NaSch
31 : * @brief The Nagel-Schreckenberg (1992) cellular automaton car-following model
32 : *
33 : * A discretized car-following model in the spirit of the original NaSch
34 : * cellular automaton. Unlike SUMO's continuous models it does not derive a
35 : * safe speed from the leader's speed; instead the gap to the leader alone
36 : * bounds the next speed. Speeds are always rounded down to a multiple of one
37 : * "cell" per simulation step, where the cell length is implied by the
38 : * vehicle's **accel** attribute (a cell is covered by accelerating for
39 : * exactly one step, see the constructor). Randomized deceleration ("dawdling")
40 : * is applied with probability **sigma**, reusing SUMO's generic imperfection
41 : * parameter for the model's classic per-step slowdown rule.
42 : *
43 : * @see MSCFModel
44 : * @see https://github.com/eclipse-sumo/sumo/issues/12182
45 : */
46 : class MSCFModel_NaSch : public MSCFModel {
47 : public:
48 : /** @brief Constructor
49 : * @param[in] vtype the type for which this model is built and also the parameter object to configure this model
50 : * @param[in] dawdle the probability of randomized deceleration by one cell per step ("sigma")
51 : */
52 : MSCFModel_NaSch(const MSVehicleType* vtype, double dawdle);
53 :
54 :
55 : /// @brief Destructor
56 : ~MSCFModel_NaSch();
57 :
58 :
59 : /// @name Implementations of the MSCFModel interface
60 : /// @{
61 :
62 : /** @brief Computes the vehicle's safe speed (no dawdling)
63 : *
64 : * NaSch rule 2 ("slowing down"): the leader's own speed is irrelevant,
65 : * only the (net) gap to the leader bounds the next speed.
66 : * @param[in] veh The vehicle (EGO)
67 : * @param[in] speed The vehicle's speed
68 : * @param[in] gap2pred The (net) distance to the LEADER
69 : * @param[in] predSpeed The speed of LEADER (ignored, see above)
70 : * @return EGO's safe speed
71 : */
72 : double followSpeed(const MSVehicle* const veh, double speed, double gap2pred,
73 : double predSpeed, double predMaxDecel, const MSVehicle* const pred = 0, const CalcReason usage = CalcReason::CURRENT) const;
74 :
75 : /** @brief Computes the vehicle's safe speed (no dawdling)
76 : * This method is used during the insertion stage. Whereas the method
77 : * followSpeed returns the desired speed which may be lower than the safe
78 : * speed, this method only considers safety constraints
79 : *
80 : * Returns the velocity of the vehicle in dependence to the vehicle's and its leader's values and the distance between them.
81 : * @param[in] veh The vehicle (EGO)
82 : * @param[in] speed The vehicle's speed
83 : * @param[in] gap2pred The (net) distance to the LEADER
84 : * @param[in] predSpeed The speed of LEADER
85 : * @return EGO's safe speed
86 : */
87 : double insertionFollowSpeed(const MSVehicle* const veh, double speed, double gap2pred, double predSpeed, double predMaxDecel, const MSVehicle* const pred = 0) const;
88 :
89 : /** @brief Computes the vehicle's safe speed for approaching a non-moving obstacle (no dawdling)
90 : * @param[in] veh The vehicle (EGO)
91 : * @param[in] speed The vehicle's speed
92 : * @param[in] gap2pred The (net) distance to the obstacle
93 : * @param[in] decel unused, NaSch does not bound the deceleration used for stopping (see minNextSpeedEmergency)
94 : * @return EGO's safe speed for approaching a non-moving obstacle
95 : */
96 : double stopSpeed(const MSVehicle* const veh, const double speed, double gap2pred, double decel, const CalcReason usage = CalcReason::CURRENT) const;
97 :
98 :
99 : /// @brief NaSch rule 3 ("randomization"): dawdle by exactly one cell with probability sigma
100 : double patchSpeedBeforeLC(const MSVehicle* veh, double vMin, double vMax) const;
101 :
102 :
103 : /** @brief NaSch does not impose an extra bound on emergency braking: a vehicle
104 : * may always come to a full (Euler) resp. arbitrarily quick (ballistic) stop
105 : * within a single step if the gap requires it.
106 : */
107 : double minNextSpeedEmergency(double speed, const MSVehicle* const veh = 0) const;
108 :
109 :
110 : /** @brief Returns the model's name
111 : * @return The model's name
112 : */
113 0 : int getModelID() const {
114 0 : return SUMO_TAG_CF_NASCH;
115 : }
116 :
117 :
118 : /** @brief Get the driver's imperfection
119 : * @return The dawdle probability of drivers of this class
120 : */
121 0 : double getImperfection() const {
122 0 : return myDawdle;
123 : }
124 : /// @}
125 :
126 :
127 : /** @brief Sets a new value for driver imperfection
128 : * @param[in] imperfection The new dawdle probability
129 : */
130 0 : void setImperfection(double imperfection) {
131 0 : myDawdle = imperfection;
132 0 : }
133 :
134 :
135 : /** @brief Duplicates the car-following model
136 : * @param[in] vtype The vehicle type this model belongs to (1:1)
137 : * @return A duplicate of this car-following model
138 : */
139 : MSCFModel* duplicate(const MSVehicleType* vtype) const;
140 :
141 : protected:
142 : /** @brief Rounds a speed down to the nearest multiple of the cell speed
143 : * (the speed gained by accelerating for exactly one simulation step).
144 : * NaSch speeds always correspond to a whole number of cells per step.
145 : * @param[in] speed the continuous speed to discretize
146 : * @return the largest multiple of the cell speed that does not exceed speed (0 if speed <= 0)
147 : */
148 : double roundToCell(double speed) const;
149 :
150 : /// @brief the safe speed considering only the gap to the leader/obstacle (NaSch rule 1+2)
151 : double vsafe(const MSVehicle* const veh, double speed, double gap) const;
152 :
153 : protected:
154 : /// @brief The probability of randomized deceleration by one cell per step ("sigma")
155 : double myDawdle;
156 :
157 : /// @brief The speed gained per step by accelerating at myAccel, i.e. one cell's worth of speed
158 : double myCellSpeed;
159 : };
|