mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-18 21:59:18 +02:00
Two vehicles with automatic couplers coupled the moment they touched, in CouplerForce(), before CollisionDetect() ran; its derail check only covers uncoupled vehicles, so they never collided nor derailed, at any speed. With crash damage on, the coupling now waits for a closing speed of at most 15 km/h, the limit of the derail check. A faster hit locks the automatic coupling until the vehicles part, so the collision runs its course instead of the couplers catching once it has slowed them down. Two collision bugs on the way: - CollisionVelocity() took the length of the difference of the heading quaternions times the speeds; a quaternion turns by half its angle, so for vehicles facing each other the speeds came out at right angles: a head-on hit at 10 + 10 km/h read as 14.1 km/h, under the limit. The closing speed is now taken from the touching ends, as CouplerForce() relates the vehicles: the sum of the speeds head-on, the difference rear-end, negative when the ends part, - CollisionDetect() gave ComputeCollision() the other vehicle's speed along that vehicle's own axis, which points the other way for vehicles facing each other: a wagon hit head-on counted as running into the hitter, and the hitter bounced back as from a wall (20 km/h into a standing wagon: it ran off at 6 km/h instead of 17). The speed is turned into this vehicle's frame and back. Head-on hits now count with both speeds, so with crash damage on they derail sooner than before, at the 15 km/h the check was meant for. Tests: test::pair runs two test vehicles on one track the way vehicle_table::update() runs a scene (neighbours, forces, movement), with coupling, buffing, collisions and derailing coming from the physics. tests/unit/test_couplers.cpp: catching up to 15 km/h and not above; a slow hit couples, a fast one doesn't, nor once slowed down, the lock resets once the vehicles part; a hit a little over 15 km/h bounces apart on the rails, harder ones derail; head-on 7 + 7 couples, 8 + 8 bounces, 15 + 15 derails; no catching a coupler of another type, couplers of different control systems couple without the control connection.
63 lines
2.3 KiB
C++
63 lines
2.3 KiB
C++
#include "stdafx.h"
|
|
#include "doctest.h"
|
|
#include "vehicle.h"
|
|
|
|
using test::definition;
|
|
using test::track;
|
|
using test::vehicle;
|
|
|
|
namespace {
|
|
|
|
struct braking_result {
|
|
bool skidded{false}; // the wheels locked while braking
|
|
bool stopped{false}; // came (almost) to a stop on the braking rail
|
|
};
|
|
|
|
// brakes the wagon from 40 km/h on the Braking rail until it's (nearly) stopped, then has it stand on the
|
|
// Standing one for 30 seconds
|
|
braking_result brake_to_stop_then_stand(vehicle &Coach, track const &Braking, track const &Standing) {
|
|
braking_result result;
|
|
Coach.hold_brake_pipe(5.0);
|
|
Coach.run(5.0, Braking);
|
|
Coach.hold_brake_pipe(3.5); // service braking
|
|
// a skidding wagon brakes on the sliding adhesion only, give it time
|
|
for (auto step = 0; step < 60000; ++step) { // 600 s in 0.01 s steps
|
|
result.skidded |= Coach->SlippingWheels;
|
|
if (auto const speed{std::abs(Coach.speed())}; speed > 0.0 && speed < 0.1) {
|
|
// almost stopped; a skidding wagon is still skidding at this point
|
|
result.stopped = true;
|
|
break;
|
|
}
|
|
Coach.step(Braking);
|
|
}
|
|
Coach.run(30.0, Standing);
|
|
return result;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
// the engine doesn't let a stopped, braked vehicle slip (the Vel > 0.1 trap in TMoverParameters::ComputeTotalForce),
|
|
// so a wagon which stopped in a skid should be no different from one which stopped without it. it used to stay
|
|
// skidding instead, with its brakes capped by the sliding adhesion, and slid or crept away (eu07/maszyna#479)
|
|
TEST_CASE("wheelslip: a wagon which stopped in a skid holds like one which stopped without it") {
|
|
track const dry{0.15, 0.0};
|
|
track const slippery{0.02, 0.0};
|
|
// held only by the brakes: the sliding adhesion on this rail is too low for the slope
|
|
track const slipperyslope{0.02, 0.08};
|
|
|
|
vehicle normal{definition::load("wagon"), 40.0};
|
|
auto const normalbraking{brake_to_stop_then_stand(normal, dry, slipperyslope)};
|
|
vehicle skidding{definition::load("wagon"), 40.0};
|
|
auto const skiddingbraking{brake_to_stop_then_stand(skidding, slippery, slipperyslope)};
|
|
|
|
// the test means something only when the braking went as planned
|
|
REQUIRE(normalbraking.stopped);
|
|
REQUIRE_FALSE(normalbraking.skidded);
|
|
REQUIRE(skiddingbraking.stopped);
|
|
REQUIRE(skiddingbraking.skidded);
|
|
|
|
CHECK(std::abs(normal.speed()) < 0.1);
|
|
CHECK(std::abs(skidding.speed()) < 0.1);
|
|
CHECK_FALSE(skidding->SlippingWheels);
|
|
}
|