mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-11-07 20:16:08 +01:00
fix(physics): articulated couplers stall freight trains (eu07/maszyna#553) (#255)
* fix(physics): articulated couplers stall freight trains (eu07/maszyna#553) Articulated wagons (T3000e, N-230, N-234) set up with CType=Articulated barely moved in a freight train and jerked. - The articulated joint took the spring force up to DmaxC = 0.05 m only, 225 kN, well short of its FmaxC of 850 kN and of what a loaded section in a freight train takes. It overstretched and the sections collided at every physics step. Dmax is now sized so the spring carries FmaxC (0.19 m stretched, 0.09 m pressed in), never below the old 0.05 m. - ComputeCollision() scaled the velocities of both vehicles by sqrt(1 - beta), so each collision braked the pair as a whole: two coupled vehicles in a sustained "collision" lost a third of their speed per step. The restitution now applies to the velocities relative to the centre of mass only, and the pair keeps its momentum. Tests: the articulated joint carries FmaxC within its travel; a jerked articulated set and a jerked screw-coupled pair keep their momentum. On the code before the fix both pairs stop dead within 3 s. * style(physics): English-only comment in ComputeCollision() The comment above the collision velocities started in Polish and went on in English. * style(physics): SonarQube findings in the #553 fix std::lerp for the collision velocities (cpp:S6179) and test locals renamed so they no longer shadow the end and coupling enumerators (cpp:S1117).
This commit is contained in:
@@ -456,3 +456,72 @@ TEST_CASE("couplers: the coupler force of vehicles facing each other lands on th
|
||||
CHECK(second->Couplers[end::front].CForce == 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
// eu07/maszyna#553: articulated wagons (T3000e, N-234 and the like) set up with articulated couplers barely moved in a
|
||||
// freight train. the joint took the spring force up to 5 cm only, 225 kN, so it overstretched under the train and the
|
||||
// sections collided at every step; and each collision scaled the velocities of both vehicles down, rather than only
|
||||
// the velocity of one relative to the other, braking the whole train
|
||||
|
||||
namespace {
|
||||
|
||||
// the wagon from data/wagon.json, loaded, with articulated couplers at both ends
|
||||
vehicle articulated_wagon(double Velocity, std::string const &Name) {
|
||||
return vehicle{definition::load("wagon").set("Param", "M", 60000).set("BuffCoupl", "CType", "Articulated"), Velocity, Name};
|
||||
}
|
||||
|
||||
// couples the facing ends of the two vehicles for good, as the scenery does for an articulated set
|
||||
void join(vehicle &First, int FirstEnd, vehicle &Second, int SecondEnd) {
|
||||
REQUIRE(First->Attach(FirstEnd, SecondEnd, &Second.mover(), coupling::coupler, true, false));
|
||||
REQUIRE(Second->Attach(SecondEnd, FirstEnd, &First.mover(), coupling::coupler, true, false));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_CASE("couplers: an articulated joint takes its full tensile force within its travel") {
|
||||
auto wagon{articulated_wagon(0.0, "wagon")};
|
||||
auto const &joint{wagon->Couplers[end::front]};
|
||||
REQUIRE(joint.type() == TCouplerType::Articulated);
|
||||
|
||||
CHECK(joint.SpringKC * joint.DmaxC >= doctest::Approx(joint.FmaxC));
|
||||
CHECK(joint.SpringKB * joint.DmaxB >= doctest::Approx(joint.FmaxC));
|
||||
// and no less than it had before
|
||||
CHECK(joint.DmaxC >= 0.05);
|
||||
CHECK(joint.DmaxB >= 0.05);
|
||||
}
|
||||
|
||||
TEST_CASE("couplers: an articulated set keeps its momentum when one section jerks the other") {
|
||||
// the front section moving, the rear one barely (so that its brakes are released), joined: the jerk overstretches the joint, the sections collide
|
||||
// and run on together at half the speed, as the momentum they have between them dictates
|
||||
auto front_section{articulated_wagon(20.0, "front")};
|
||||
auto rear_section{articulated_wagon(0.1, "rear")};
|
||||
join(rear_section, end::front, front_section, end::rear);
|
||||
test::pair pair{rear_section, end::front, front_section, end::rear, 0.0};
|
||||
REQUIRE(pair.coupled());
|
||||
// brakes released, as a locomotive keeps them
|
||||
front_section.hold_brake_pipe(5.0);
|
||||
rear_section.hold_brake_pipe(5.0);
|
||||
|
||||
pair.run(3.0, test::track{0.15, 0.0});
|
||||
|
||||
CHECK(front_section.speed() == doctest::Approx(rear_section.speed()).epsilon(0.1));
|
||||
// rolling resistance takes a little in the 3 s, the collisions used to take most of it
|
||||
CHECK(0.5 * (front_section.speed() + rear_section.speed()) > 9.0);
|
||||
CHECK(0.5 * (front_section.speed() + rear_section.speed()) < 10.05 + 1e-6);
|
||||
CHECK(pair.coupled());
|
||||
}
|
||||
|
||||
TEST_CASE("couplers: a collision of coupled vehicles keeps the momentum of the pair") {
|
||||
// the same jerk through screw couplers, which collide when stretched beyond their travel as well
|
||||
auto front_wagon{vehicle{definition::load("wagon"), 30.0, "front"}};
|
||||
auto rear_wagon{vehicle{definition::load("wagon"), 0.1, "rear"}};
|
||||
join(rear_wagon, end::front, front_wagon, end::rear);
|
||||
test::pair pair{rear_wagon, end::front, front_wagon, end::rear, 0.0};
|
||||
REQUIRE(pair.coupled());
|
||||
front_wagon.hold_brake_pipe(5.0);
|
||||
rear_wagon.hold_brake_pipe(5.0);
|
||||
|
||||
pair.run(3.0, test::track{0.15, 0.0});
|
||||
|
||||
CHECK(0.5 * (front_wagon.speed() + rear_wagon.speed()) > 13.5);
|
||||
CHECK(0.5 * (front_wagon.speed() + rear_wagon.speed()) < 15.05 + 1e-6);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user