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 
138  carriage->front = lane->getShape(secondaryShape).positionAtOffset(carriageOffset * lane->getLengthGeometryFactor(secondaryShape), lateralOffset);
139  carriage->back = backLane->getShape(secondaryShape).positionAtOffset(carriageBackOffset * lane->getLengthGeometryFactor(secondaryShape), lateralOffset);
140  myCarriages.push_back(carriage);
141 
142  carriageOffset -= (curCLength + myCarriageGap);
143  carriageBackOffset -= myCarriageLengthWithGap;
144  }
145 }
146 
147 
148 void
150  for (Carriage* carriage : myCarriages) {
151  Position dir = carriage->front - carriage->back;
152  const double carriageLength = dir.length2D();
153  if (carriageLength > 0.0) {
154  dir.norm2D();
155  for (int j = 1; j <= myCarriageDoors; j++) {
156  const double doorOffset = j * carriageLength / (myCarriageDoors + 1);
157  carriage->doorPositions.push_back(carriage->front - dir * doorOffset);
158  }
159  }
160  }
161 }
162 
163 
164 void
165 MSTrainHelper::computeUnboardingPositions(double passengerRadius, std::vector<Position>& unboardingPositions) {
166  passengerRadius += PEDESTRIAN_RADIUS_EXTRA_TOLERANCE;
167  for (Carriage* carriage : myCarriages) {
168  Position dir = carriage->front - carriage->back;
169  const double carriageLength = dir.length2D();
170  if (carriageLength > 0.0) {
171  dir.norm2D();
172  const Position perp = Position(-dir.y(), dir.x());
173  double nbrLongitudinalCells, longitudinalOffset;
174  longitudinalOffset = std::modf((carriageLength - 2.0 * passengerRadius) / (2.0 * passengerRadius), &nbrLongitudinalCells);
175  double nbrLateralCells, lateralOffset;
176  lateralOffset = std::modf((myHalfWidth * 2.0 - 2.0 * passengerRadius) / (2.0 * passengerRadius), &nbrLateralCells);
177  const Position gridOrigin = carriage->back + dir * (passengerRadius + 0.5 * longitudinalOffset) - perp * (myHalfWidth - passengerRadius - 0.5 * lateralOffset);
178  for (unsigned int i = 0; i <= (unsigned int)nbrLongitudinalCells; i++) {
179  for (unsigned int j = 0; j <= (unsigned int)nbrLateralCells; j++) {
180  carriage->unboardingPositions.push_back(gridOrigin + dir * i * 2.0 * passengerRadius + perp * j * 2.0 * passengerRadius);
181  }
182  }
183  }
184  std::copy(carriage->unboardingPositions.begin(), carriage->unboardingPositions.end(), std::back_inserter(unboardingPositions));
185  }
186  // Shuffle the positions upstream so that we don't have to sample later on, just pop the last element.
187  RandHelper::shuffle(unboardingPositions);
188 }
189 
190 
191 double
192 MSTrainHelper::getUpscaleLength(double upscale, double length, double width, int vehicleQuality) {
193  if (upscale > 1 && length > 5 && width < 5 && vehicleQuality != 4) {
194  return MAX2(1.0, upscale * 5 / length);
195  } else {
196  return upscale;
197  }
198 }
@ 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:169
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:8011
MSAbstractLaneChangeModel & getLaneChangeModel()
Definition: MSVehicle.cpp:5749
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:177
double x() const
Returns the x-position.
Definition: Position.h:55
double length2D() const
Computes the length of the given vector.
Definition: Position.h:172
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