Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,19 @@ public Vector positionAt(TrackPose pose) {
return offsetAt(pose).add(new Vector(pose.x, pose.y, pose.z));
}

/**
* Places a car so this coupler meets {@code target} seen from above. The car keeps the
* height of its own rail: where the grade changes between two cars, their couplers
* sit at different heights, and meeting exactly would lift or sink the car off its track.
*/
public TrackPose coupledPose(TrackPose nominal, Vector target) {
double dx = target.getX() - nominal.x;
double dz = target.getZ() - nominal.z;
float yaw = dx * dx + dz * dz > 1e-8
? (float) Math.toDegrees(Math.atan2(-dx, dz)) : nominal.yaw;
TrackPose facing = new TrackPose(nominal.x, nominal.y, nominal.z, yaw, nominal.pitch);
Vector offset = offsetAt(facing);
return new TrackPose(target.getX() - offset.getX(), target.getY() - offset.getY(),
return new TrackPose(target.getX() - offset.getX(), nominal.y,
target.getZ() - offset.getZ(), yaw, nominal.pitch);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,27 @@ void passengerFrontMeetsLocomotiveBackWithRealPivotsAndBaseRotation(
TrackPose nominal = new TrackPose(96, 64, 194, yaw - 25, pitch);
TrackPose coupled = front.coupledPose(nominal, back.positionAt(parent));
Vector renderedFront = renderedAnchor(coupled, PASSENGER_FRONT, new Vector3f(), -entityYaw, size);
assertEquals(0, expectedBack.distance(renderedFront), 1e-5);
// Couplers meet seen from above; the car stays at its own rail height.
assertEquals(0, Math.hypot(expectedBack.getX() - renderedFront.getX(),
expectedBack.getZ() - renderedFront.getZ()), 1e-5);
assertEquals(nominal.y, coupled.y, 1e-9);
assertEquals(pitch, coupled.pitch);
assertEquals(new Vector3f(0, 15f / 16, 78f / 16), PASSENGER_FRONT);
}

@Test
void carOnLevelTrackBehindLocomotiveOnGradeStaysOnItsRail() {
// Lab case: locomotive 11 degrees nose down, passenger car still on the level.
Connector back = connector(LOCO_BACK, LOCO_PIVOT, 88, new Vector3f(1));
Connector front = connector(PASSENGER_FRONT, new Vector3f(), 88, new Vector3f(1));
TrackPose loco = new TrackPose(5449.57, 430.384, 3462.5, 88.4f, 11.1f);
TrackPose nominal = new TrackPose(5457.82, 432.0, 3462.49, 88.4f, 0f);
TrackPose coupled = front.coupledPose(nominal, back.positionAt(loco));
assertEquals(432.0, coupled.y, 1e-9);
assertEquals(nominal.x, coupled.x, 0.5);
assertEquals(nominal.z, coupled.z, 0.5);
}

private static Vector renderedAnchor(TrackPose pose, Vector3f point, Vector3f pivot,
float entityYaw, Vector3f scale) {
Vector3d result = new Matrix4d().translation(pose.x, pose.y, pose.z)
Expand Down