Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSTrainHelper.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2024 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/****************************************************************************/
18// A class that helps computing positions of a train's carriages.
19/****************************************************************************/
20#include <config.h>
21
22#include <microsim/MSLane.h>
24#include <microsim/MSVehicle.h>
25#include "MSTrainHelper.h"
26
27
28const double MSTrainHelper::CARRIAGE_DOOR_WIDTH = 1.5;
30
31// ===========================================================================
32// method definitions
33// ===========================================================================
34void
35MSTrainHelper::computeTrainDimensions(double exaggeration, int vehicleQuality) {
36 const MSVehicleType& vtype = myTrain->getVehicleType();
37 const double totalLength = vtype.getLength();
38 myUpscaleLength = getUpscaleLength(exaggeration, totalLength, vtype.getWidth(), vehicleQuality);
41 if (myLocomotiveLength == 0) {
43 }
45 myLength = totalLength * myUpscaleLength;
46 myHalfWidth = 0.5 * vtype.getWidth() * exaggeration;
47 myNumCarriages = MAX2(1, 1 + (int)((myLength - myLocomotiveLength) / (myDefaultLength + myCarriageGap) + 0.5)); // Round to closest integer.
48 if (myUpscaleLength > 1 && vehicleQuality != 4) {
49 // at high zoom, it doesn't help to draw many carriages)
52 }
53 assert(myNumCarriages > 0);
54 if (myNumCarriages == 1) {
55 myCarriageGap = 0;
56 }
64 }
66}
67
68
69void
70MSTrainHelper::computeCarriages(bool reversed, bool secondaryShape) {
71 myCarriages.clear();
72
73 const MSLane* lane = myTrain->getLane(); // Lane on which the carriage's front is situated.
74 int furtherIndex = 0;
75 const MSLane* backLane = lane; // Lane on which the carriage's back is situated.
76 int backFurtherIndex = furtherIndex;
77 // Offsets of front and back parts of a carriage.
78 double carriageOffset = myTrain->getPositionOnLane();
80 // This still produces some artifacts when not fully on the current lane.
81 carriageOffset = MIN2(carriageOffset + myTrain->getLength(), lane->getLength());
82 }
83 double carriageBackOffset = carriageOffset - myFirstCarriageLength;
84
85 double curCLength = myFirstCarriageLength;
86 myFirstCarriageNo = 0; // default case - we're going forwards
88 if (myIsReversed) {
90 if (myNumCarriages > 1) {
91 carriageBackOffset = carriageOffset - myCarriageLength;
92 }
93 }
95 myFirstCarriageNo = -1; // don't draw locomotive
96 }
97
99 || (myTrain->getVClass() & (SVC_RAIL_ELECTRIC | SVC_RAIL_FAST | SVC_RAIL)) == 0 ? 0 : 1;
100
101 const double lateralOffset = (myTrain->isParking() && myTrain->getNextStopParameter()->posLat == INVALID_DOUBLE
102 ? (myTrain->getLane()->getWidth() * (MSGlobals::gLefthand ? -1 : 1))
104
105 for (int i = 0; i < myNumCarriages; ++i) {
106 Carriage* carriage = new Carriage();
107 if (i == myFirstCarriageNo) {
108 curCLength = myFirstCarriageLength;
109 if (myFirstCarriageNo > 0) {
110 // Previous loop iteration has adjusted backpos for a normal carriage so have to correct
111 carriageBackOffset += myCarriageLengthWithGap;
112 carriageBackOffset -= myFirstCarriageLength + myCarriageGap;
113 }
114 } else {
115 curCLength = myCarriageLength;
116 }
117 while (carriageOffset < 0) {
118 const MSLane* prev = myTrain->getPreviousLane(lane, furtherIndex);
119 if (prev != lane) {
120 carriageOffset += prev->getLength();
121 } else {
122 // No lane available.
123 carriageOffset = 0;
124 }
125 lane = prev;
126 }
127 while (carriageBackOffset < 0) {
128 const MSLane* prev = myTrain->getPreviousLane(backLane, backFurtherIndex);
129 if (prev != backLane) {
130 carriageBackOffset += prev->getLength();
131 } else {
132 // No lane available.
133 carriageBackOffset = 0;
134 }
135 backLane = prev;
136 }
137 carriage->front = lane->getShape(secondaryShape).positionAtOffset(carriageOffset * lane->getLengthGeometryFactor(secondaryShape), lateralOffset);
138 carriage->back = backLane->getShape(secondaryShape).positionAtOffset(carriageBackOffset * backLane->getLengthGeometryFactor(secondaryShape), lateralOffset);
139 myCarriages.push_back(carriage);
140
141 carriageOffset -= (curCLength + myCarriageGap);
142 carriageBackOffset -= myCarriageLengthWithGap;
143 }
144}
145
146
147void
149 for (Carriage* carriage : myCarriages) {
150 Position dir = carriage->front - carriage->back;
151 const double carriageLength = dir.length2D();
152 if (carriageLength > 0.0) {
153 dir.norm2D();
154 for (int j = 1; j <= myCarriageDoors; j++) {
155 const double doorOffset = j * carriageLength / (myCarriageDoors + 1);
156 carriage->doorPositions.push_back(carriage->front - dir * doorOffset);
157 }
158 }
159 }
160}
161
162
163void
164MSTrainHelper::computeUnboardingPositions(double passengerRadius, std::vector<Position>& unboardingPositions) {
165 passengerRadius += PEDESTRIAN_RADIUS_EXTRA_TOLERANCE;
166 for (Carriage* carriage : myCarriages) {
167 Position dir = carriage->front - carriage->back;
168 const double carriageLength = dir.length2D();
169 if (carriageLength > 0.0) {
170 dir.norm2D();
171 const Position perp = Position(-dir.y(), dir.x());
172 double nbrLongitudinalCells, longitudinalOffset;
173 longitudinalOffset = std::modf((carriageLength - 2.0 * passengerRadius) / (2.0 * passengerRadius), &nbrLongitudinalCells);
174 double nbrLateralCells, lateralOffset;
175 lateralOffset = std::modf((myHalfWidth * 2.0 - 2.0 * passengerRadius) / (2.0 * passengerRadius), &nbrLateralCells);
176 const Position gridOrigin = carriage->back + dir * (passengerRadius + 0.5 * longitudinalOffset) - perp * (myHalfWidth - passengerRadius - 0.5 * lateralOffset);
177 for (unsigned int i = 0; i <= (unsigned int)nbrLongitudinalCells; i++) {
178 for (unsigned int j = 0; j <= (unsigned int)nbrLateralCells; j++) {
179 carriage->unboardingPositions.push_back(gridOrigin + dir * i * 2.0 * passengerRadius + perp * j * 2.0 * passengerRadius);
180 }
181 }
182 }
183 std::copy(carriage->unboardingPositions.begin(), carriage->unboardingPositions.end(), std::back_inserter(unboardingPositions));
184 }
185 // Shuffle the positions upstream so that we don't have to sample later on, just pop the last element.
186 RandHelper::shuffle(unboardingPositions);
187}
188
189
190double
191MSTrainHelper::getUpscaleLength(double upscale, double length, double width, int vehicleQuality) {
192 if (upscale > 1 && length > 5 && width < 5 && vehicleQuality != 4) {
193 return MAX2(1.0, upscale * 5 / length);
194 } else {
195 return upscale;
196 }
197}
@ SVC_RAIL
vehicle is a not electrified rail
@ SVC_RAIL_FAST
vehicle that is allowed to drive on high-speed rail tracks
@ SVC_RAIL_ELECTRIC
rail vehicle that requires electrified tracks
const double INVALID_DOUBLE
invalid double
Definition StdDefs.h:64
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
bool isReversed() const
Returns whether the logical state of the vehicle is reversed - for drawing.
const SUMOVehicleParameter::Stop * getNextStopParameter() const
return parameters for the next stop (SUMOVehicle Interface)
double getLength() const
Returns the vehicle's length.
bool isParking() const
Returns whether the vehicle is parking.
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
static bool gLefthand
Whether lefthand-drive is being simulated.
Definition MSGlobals.h:174
Representation of a lane in the micro simulation.
Definition MSLane.h:84
virtual double getLengthGeometryFactor(bool) const
Definition MSLane.h:290
double getLength() const
Returns the lane's length.
Definition MSLane.h:606
virtual const PositionVector & getShape(bool) const
Definition MSLane.h:294
double getWidth() const
Returns the lane's width.
Definition MSLane.h:635
void computeTrainDimensions(double exaggeration, int vehicleQuality)
double myFirstCarriageLength
const MSVehicle * myTrain
static const double PEDESTRIAN_RADIUS_EXTRA_TOLERANCE
small extra tolerance used to avoid constraint violations
std::vector< Carriage * > myCarriages
void computeDoorPositions()
compute door positions on demand and fills the carriage structures
double myLocomotiveLength
double myCarriageLengthWithGap
void computeUnboardingPositions(double passengerRadius, std::vector< Position > &unboardingPositions)
compute unboarding positions on demand and fills the carriage structures
static const double CARRIAGE_DOOR_WIDTH
average door width used to compute doors positions
double myDefaultLength
int myFirstPassengerCarriage
double myCarriageLength
double getUpscaleLength() const
double myUpscaleLength
void computeCarriages(bool reversed, bool secondaryShape)
const MSLane * getPreviousLane(const MSLane *current, int &furtherIndex) const
MSAbstractLaneChangeModel & getLaneChangeModel()
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition MSVehicle.h:581
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition MSVehicle.h:413
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition MSVehicle.h:374
The car-following model and parameter.
double getWidth() const
Get the width which vehicles of this class shall have when being drawn.
double getLength() const
Get vehicle's length [m].
const SUMOVTypeParameter & getParameter() const
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
void norm2D()
Normalizes the given vector.
Definition Position.h:182
double x() const
Returns the x-position.
Definition Position.h:55
double length2D() const
Computes the length of the given vector neglecting the z coordinate.
Definition Position.h:177
double y() const
Returns the y-position.
Definition Position.h:60
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
static void shuffle(std::vector< T > &v, SumoRNG *rng=nullptr)
Definition RandHelper.h:240
double carriageLength
the length of train carriages and locomotive
int carriageDoors
the number of doors per carriage
double posLat
the lateral offset when stopping