1+ #pragma once
2+
3+ #include " RoadDynamics.hpp"
4+
5+ namespace dsm {
6+ template <typename delay_t >
7+ requires (std::unsigned_integral<delay_t >)
8+ class FirstOrderDynamics : public RoadDynamics <delay_t > {
9+ double m_speedFluctuationSTD;
10+
11+ public:
12+ // / @brief Construct a new First Order Dynamics object
13+ // / @param graph, The graph representing the network
14+ FirstOrderDynamics (Graph& graph, std::optional<unsigned int > seed = std::nullopt )
15+ : RoadDynamics<delay_t >(graph, seed), m_speedFluctuationSTD{0 .} {};
16+ // / @brief Set the speed of an agent
17+ // / @param agentId The id of the agent
18+ // / @throw std::invalid_argument, If the agent is not found
19+ void setAgentSpeed (Size agentId) override ;
20+ // / @brief Set the standard deviation of the speed fluctuation
21+ // / @param speedFluctuationSTD The standard deviation of the speed fluctuation
22+ // / @throw std::invalid_argument, If the standard deviation is negative
23+ void setSpeedFluctuationSTD (double speedFluctuationSTD);
24+ // / @brief Get the mean speed of a street in \f$m/s\f$
25+ // / @return double The mean speed of the street or street->maxSpeed() if the street is empty
26+ // / @details The mean speed of a street is given by the formula:
27+ // / \f$ v_{\text{mean}} = v_{\text{max}} \left(1 - \frac{\alpha}{2} \left( n - 1\right) \right) \f$
28+ // / where \f$ v_{\text{max}} \f$ is the maximum speed of the street, \f$ \alpha \f$ is the minimum speed rateo divided by the capacity
29+ // / and \f$ n \f$ is the number of agents in the street
30+ double streetMeanSpeed (Id streetId) const override ;
31+ // / @brief Get the mean speed of the streets in \f$m/s\f$
32+ // / @return Measurement The mean speed of the agents and the standard deviation
33+ Measurement<double > streetMeanSpeed () const override ;
34+ // / @brief Get the mean speed of the streets with density above or below a threshold in \f$m/s\f$
35+ // / @param threshold The density threshold to consider
36+ // / @param above If true, the function returns the mean speed of the streets with a density above the threshold, otherwise below
37+ // / @return Measurement The mean speed of the agents and the standard deviation
38+ Measurement<double > streetMeanSpeed (double threshold, bool above) const override ;
39+ };
40+
41+ template <typename delay_t >
42+ requires (std::unsigned_integral<delay_t >)
43+ void FirstOrderDynamics<delay_t >::setAgentSpeed(Size agentId) {
44+ const auto & agent{this ->m_agents [agentId]};
45+ const auto & street{this ->m_graph .streetSet ()[agent->streetId ().value ()]};
46+ double speed{street->maxSpeed () *
47+ (1 . - this ->m_minSpeedRateo * street->density (true ))};
48+ if (m_speedFluctuationSTD > 0 .) {
49+ std::normal_distribution<double > speedDist{speed, speed * m_speedFluctuationSTD};
50+ speed = speedDist (this ->m_generator );
51+ }
52+ speed < 0 . ? agent->setSpeed (street->maxSpeed () * (1 . - this ->m_minSpeedRateo ))
53+ : agent->setSpeed (speed);
54+ }
55+
56+ template <typename delay_t >
57+ requires (std::unsigned_integral<delay_t >)
58+ void FirstOrderDynamics<delay_t >::setSpeedFluctuationSTD(double speedFluctuationSTD) {
59+ if (speedFluctuationSTD < 0 .) {
60+ throw std::invalid_argument (
61+ buildLog (" The speed fluctuation standard deviation must be positive." ));
62+ }
63+ m_speedFluctuationSTD = speedFluctuationSTD;
64+ }
65+
66+ template <typename delay_t >
67+ requires (std::unsigned_integral<delay_t >)
68+ double FirstOrderDynamics<delay_t >::streetMeanSpeed(Id streetId) const {
69+ const auto & street{this ->m_graph .streetSet ().at (streetId)};
70+ if (street->nAgents () == 0 ) {
71+ return street->maxSpeed ();
72+ }
73+ double meanSpeed{0 .};
74+ Size n{0 };
75+ if (street->nExitingAgents () == 0 ) {
76+ n = static_cast <Size>(street->waitingAgents ().size ());
77+ double alpha{this ->m_minSpeedRateo / street->capacity ()};
78+ meanSpeed = street->maxSpeed () * n * (1 . - 0.5 * alpha * (n - 1 .));
79+ } else {
80+ for (const auto & agentId : street->waitingAgents ()) {
81+ meanSpeed += this ->m_agents .at (agentId)->speed ();
82+ ++n;
83+ }
84+ for (auto const & queue : street->exitQueues ()) {
85+ for (const auto & agentId : queue) {
86+ meanSpeed += this ->m_agents .at (agentId)->speed ();
87+ ++n;
88+ }
89+ }
90+ }
91+ const auto & node = this ->m_graph .nodeSet ().at (street->nodePair ().second );
92+ if (node->isIntersection ()) {
93+ auto & intersection = dynamic_cast <Intersection&>(*node);
94+ for (const auto & [angle, agentId] : intersection.agents ()) {
95+ const auto & agent{this ->m_agents .at (agentId)};
96+ if (agent->streetId ().has_value () && agent->streetId ().value () == streetId) {
97+ meanSpeed += agent->speed ();
98+ ++n;
99+ }
100+ }
101+ } else if (node->isRoundabout ()) {
102+ auto & roundabout = dynamic_cast <Roundabout&>(*node);
103+ for (const auto & agentId : roundabout.agents ()) {
104+ const auto & agent{this ->m_agents .at (agentId)};
105+ if (agent->streetId ().has_value () && agent->streetId ().value () == streetId) {
106+ meanSpeed += agent->speed ();
107+ ++n;
108+ }
109+ }
110+ }
111+ return meanSpeed / n;
112+ }
113+
114+ template <typename delay_t >
115+ requires (std::unsigned_integral<delay_t >)
116+ Measurement<double > FirstOrderDynamics<delay_t >::streetMeanSpeed() const {
117+ if (this ->m_agents .size () == 0 ) {
118+ return Measurement (0 ., 0 .);
119+ }
120+ std::vector<double > speeds;
121+ speeds.reserve (this ->m_graph .streetSet ().size ());
122+ for (const auto & [streetId, street] : this ->m_graph .streetSet ()) {
123+ speeds.push_back (this ->streetMeanSpeed (streetId));
124+ }
125+ return Measurement<double >(speeds);
126+ }
127+ template <typename delay_t >
128+ requires (std::unsigned_integral<delay_t >)
129+ Measurement<double > FirstOrderDynamics<delay_t >::streetMeanSpeed(double threshold,
130+ bool above) const {
131+ if (this ->m_agents .size () == 0 ) {
132+ return Measurement (0 ., 0 .);
133+ }
134+ std::vector<double > speeds;
135+ speeds.reserve (this ->m_graph .streetSet ().size ());
136+ for (const auto & [streetId, street] : this ->m_graph .streetSet ()) {
137+ if (above) {
138+ if (street->density (true ) > threshold) {
139+ speeds.push_back (this ->streetMeanSpeed (streetId));
140+ }
141+ } else {
142+ if (street->density (true ) < threshold) {
143+ speeds.push_back (this ->streetMeanSpeed (streetId));
144+ }
145+ }
146+ }
147+ return Measurement<double >(speeds);
148+ }
149+ } // namespace dsm
0 commit comments