@@ -941,43 +941,60 @@ void Simulator::updateTrainPositions()
941941 trainState.speedOrDirectionChanged = false ;
942942 }
943943
944- auto updateHelper = [this ](Simulator::Train::VehicleItem& item, float speed, bool reverse) -> bool
944+ auto updateHelper = [this ](Simulator::Train::VehicleItem& item, float speed,
945+ bool reverse, float &outRemaining) -> bool
945946 {
946947 if (reverse)
947948 speed = -speed;
948949
949950 if (item.reversed == reverse)
950- return updateVehiclePosition (item.vehicle ->state .front , speed) &&
951- updateVehiclePosition (item.vehicle ->state .rear , speed);
951+ return updateVehiclePosition (item.vehicle ->state .front , speed, outRemaining ) &&
952+ updateVehiclePosition (item.vehicle ->state .rear , speed, outRemaining );
952953 else
953- return updateVehiclePosition (item.vehicle ->state .rear , speed) &&
954- updateVehiclePosition (item.vehicle ->state .front , speed);
954+ return updateVehiclePosition (item.vehicle ->state .rear , speed, outRemaining ) &&
955+ updateVehiclePosition (item.vehicle ->state .front , speed, outRemaining );
955956 };
956957
957958 const float speed = m_stateData.powerOn ? trainState.speed : 0 .0f ;
958959
959- if (!trainState.reverse )
960+ float outRemaining = 0 .0f ;
961+
962+ do
960963 {
961- for (auto & vehicleItem : train->vehicles )
964+ float tickPosDelta = speed;
965+ if (outRemaining > 0 .0f && speed != 0 .0f )
966+ {
967+ // This is second round, travel just remaining distance to stop
968+ if (speed > 0 .0f )
969+ tickPosDelta = outRemaining;
970+ else
971+ tickPosDelta = outRemaining;
972+ }
973+
974+ if (!trainState.reverse )
962975 {
963- if (! updateHelper ( vehicleItem, speed, trainState. reverse ) )
976+ for ( auto & vehicleItem : train-> vehicles )
964977 {
965- setTrainSpeed (train, 0 .0f );
966- break ;
978+ if (!updateHelper (vehicleItem, tickPosDelta, trainState.reverse , outRemaining))
979+ {
980+ setTrainSpeed (train, 0 .0f );
981+ break ;
982+ }
967983 }
968984 }
969- }
970- else // reverse
971- {
972- for (auto & vehicleItem : train->vehicles | std::views::reverse)
985+ else // reverse
973986 {
974- if (! updateHelper ( vehicleItem, speed, trainState. reverse ) )
987+ for ( auto & vehicleItem : train-> vehicles | std::views:: reverse)
975988 {
976- setTrainSpeed (train, 0 .0f );
977- break ;
989+ if (!updateHelper (vehicleItem, tickPosDelta, trainState.reverse , outRemaining))
990+ {
991+ setTrainSpeed (train, 0 .0f );
992+ break ;
993+ }
978994 }
979995 }
980996 }
997+ while (outRemaining > 0 .0f && speed != 0 .0f );
981998 }
982999}
9831000
@@ -1004,8 +1021,10 @@ inline bool isTurnoutUnknownState(const Simulator::TrackSegment& segment,
10041021 return false ;
10051022}
10061023
1007- bool Simulator::updateVehiclePosition (VehicleState::Face& face, const float speed)
1024+ bool Simulator::updateVehiclePosition (VehicleState::Face& face, const float speed, float &outRemaining )
10081025{
1026+ outRemaining = 0 .0f ;
1027+
10091028 float distance = face.distance + (face.segmentDirectionInverted ? -speed : speed);
10101029
10111030 // Move to next segment when reaching the end:
@@ -1015,18 +1034,26 @@ bool Simulator::updateVehiclePosition(VehicleState::Face& face, const float spee
10151034 const auto & segment = staticData.trackSegments [face.segmentIndex ];
10161035 const auto segmentLength = getSegmentLength (segment, m_stateData);
10171036
1018- if (distance >= segmentLength)
1037+ // If train is right on the end of segment (distance == segmentLenght) do not update
1038+ // unlsess we are effectively moving. Because if speed is 0, segmentDirectionInverted is
1039+ // not calculated correctly and because in case of 2 segment touching by their side 1,
1040+ // it will infinitely jump vehicle face from one to another.
1041+ if (distance > segmentLength || (distance == segmentLength && speed != 0 ))
10191042 {
10201043 const auto nextSegmentIndex = getNextSegmentIndex (segment, true , m_stateData);
10211044 if (nextSegmentIndex == invalidIndex)
10221045 {
1046+ outRemaining = segmentLength - face.distance - 0.0001 ;
10231047 return false ; // no next segment
10241048 }
10251049
10261050 auto & nextSegment = staticData.trackSegments [nextSegmentIndex];
10271051
10281052 if (isTurnoutUnknownState (nextSegment, m_stateData))
1053+ {
1054+ outRemaining = segmentLength - face.distance - 0.0001 ;
10291055 return false ;
1056+ }
10301057
10311058 if (segment.sensor .index != invalidIndex)
10321059 {
@@ -1058,13 +1085,17 @@ bool Simulator::updateVehiclePosition(VehicleState::Face& face, const float spee
10581085 const auto nextSegmentIndex = getNextSegmentIndex (segment, false , m_stateData);
10591086 if (nextSegmentIndex == invalidIndex)
10601087 {
1088+ outRemaining = face.distance ;
10611089 return false ; // no next segment
10621090 }
10631091
10641092 auto & nextSegment = staticData.trackSegments [nextSegmentIndex];
10651093
10661094 if (isTurnoutUnknownState (nextSegment, m_stateData))
1095+ {
1096+ outRemaining = face.distance ;
10671097 return false ;
1098+ }
10681099
10691100 if (segment.sensor .index != invalidIndex)
10701101 {
0 commit comments