Eclipse SUMO - Simulation of Urban MObility
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 
28 const double MSTrainHelper::CARRIAGE_DOOR_WIDTH = 1.5;
30 
31 // ===========================================================================
32 // method definitions
33 // ===========================================================================
34 void
35 MSTrainHelper::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 
69 void
70 MSTrainHelper::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 
147 void
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 
163 void
164 MSTrainHelper::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 
190 double
191 MSTrainHelper::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.
const MSVehicleType & getVehicleType() const
Returns the vehicle's type definition.
SUMOVehicleClass getVClass() const
Returns the vehicle's access class.
static bool gLefthand
Whether lefthand-drive is being simulated.
Definition: MSGlobals.h:171
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:598
double getWidth() const
Returns the lane's width.
Definition: MSLane.h:627
virtual const PositionVector & getShape(bool) const
Definition: MSLane.h:294
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
double myHalfWidth
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 myCarriageGap
double myCarriageLength
double getUpscaleLength() const
Definition: MSTrainHelper.h:63
double myUpscaleLength
void computeCarriages(bool reversed, bool secondaryShape)
const MSLane * getPreviousLane(const MSLane *current, int &furtherIndex) const
Definition: MSVehicle.cpp:8051
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5774
double getLateralPositionOnLane() const
Get the vehicle's lateral position on the lane.
Definition: MSVehicle.h:416
double getPositionOnLane() const
Get the vehicle's position along the lane.
Definition: MSVehicle.h:377
const MSLane * getLane() const
Returns the lane the vehicle is on.
Definition: MSVehicle.h:584
The car-following model and parameter.
Definition: MSVehicleType.h:63
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