Skip to content

Commit b135c89

Browse files
committed
enroute vertical navigation
Signed-off-by: Octol1ttle <[email protected]>
1 parent e9efbd5 commit b135c89

File tree

18 files changed

+196
-131
lines changed

18 files changed

+196
-131
lines changed

src/main/kotlin/ru/octol1ttle/flightassistant/api/autoflight/pitch/PitchLimiter.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ru.octol1ttle.flightassistant.api.autoflight.pitch
33
import ru.octol1ttle.flightassistant.api.autoflight.ControlInput
44

55
// TODO: Pitch Limit Hint (for smooth pitch limits and to allow diversion from actual pitch limit)
6+
@Deprecated("Dispatch ComputerQueries instead")
67
interface PitchLimiter {
78
fun getMinimumPitch(): ControlInput? {
89
return null

src/main/kotlin/ru/octol1ttle/flightassistant/api/autoflight/thrust/ThrustSource.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package ru.octol1ttle.flightassistant.api.autoflight.thrust
22

33
/**
4-
* Defines a source of thrust to be used by the [ru.octol1ttle.flightassistant.impl.computer.autoflight.ThrustComputer]
4+
* Defines a source of thrust to be used by the [ru.octol1ttle.flightassistant.impl.computer.autoflight.base.ThrustComputer]
55
*/
66
interface ThrustSource {
77
/**

src/main/kotlin/ru/octol1ttle/flightassistant/api/util/MathHelper.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ fun findShortestPath(from: Float, to: Float, valueRange: Float): Float {
6262
if (diff >= valueRange * 0.5) {
6363
diff -= valueRange
6464
}
65-
if (diff < -valueRange * 0.5) {
65+
if (diff < valueRange * -0.5) {
6666
diff += valueRange
6767
}
6868

@@ -73,16 +73,16 @@ fun pointsToDirection(targetX: Double, targetZ: Double, originX: Double, originZ
7373
return degrees(atan2(-(targetX - originX), targetZ - originZ))
7474
}
7575

76-
fun inverseMin(a: Float, b: Float): Float? {
77-
if (a == 0.0f && b == 0.0f) {
76+
fun inverseMin(a: Double, b: Double): Double? {
77+
if (a == 0.0 && b == 0.0) {
7878
return null
7979
}
80-
if (a == 0.0f) {
81-
return 1.0f / b
80+
if (a == 0.0) {
81+
return 1.0 / b
8282
}
83-
if (b == 0.0f) {
84-
return 1.0f / a
83+
if (b == 0.0) {
84+
return 1.0 / a
8585
}
8686

87-
return 1.0f / min(a, b)
87+
return 1.0 / min(a, b)
8888
}

src/main/kotlin/ru/octol1ttle/flightassistant/api/util/ScreenSpace.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,17 @@ object ScreenSpace {
7777
return pos.z > -1 && pos.z < 1
7878
}
7979

80-
fun getX(heading: Float, useNoRollMatrix: Boolean = true): Int? {
81-
val vec: Vector3f = fromWorldSpace(Vec3.directionFromRotation(0.0f, heading - 180.0f), useNoRollMatrix)
80+
fun getX(heading: Float): Int? {
81+
val vec: Vector3f = fromWorldSpace(Vec3.directionFromRotation(0.0f, heading - 180.0f), true)
8282
if (!isVisible(vec)) {
8383
return null
8484
}
8585

8686
return vec.x.toInt()
8787
}
8888

89-
fun getY(pitch: Float, useNoRollMatrix: Boolean = true): Int? {
90-
val vec: Vector3f = fromWorldSpace(Vec3.directionFromRotation(-pitch, mc.entityRenderDispatcher.camera.yRot), useNoRollMatrix)
89+
fun getY(pitch: Float): Int? {
90+
val vec: Vector3f = fromWorldSpace(Vec3.directionFromRotation(-pitch, mc.entityRenderDispatcher.camera.yRot), true)
9191
if (!isVisible(vec)) {
9292
return null
9393
}

src/main/kotlin/ru/octol1ttle/flightassistant/api/util/extensions/VectorExtensions.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,26 @@ package ru.octol1ttle.flightassistant.api.util.extensions
22

33
import net.minecraft.SharedConstants
44
import net.minecraft.world.phys.Vec3
5+
import org.joml.Vector2d
56

67
fun Vec3.perSecond(): Vec3 {
78
return this.scale(SharedConstants.TICKS_PER_SECOND.toDouble())
9+
}
10+
11+
fun distance2d(x1: Int, z1: Int, x2: Double, z2: Double): Double {
12+
return Vector2d.distance(x1.toDouble(), z1.toDouble(), x2, z2)
13+
}
14+
15+
fun vec2dFromInts(x: Int, z: Int): Vector2d {
16+
return Vector2d(x.toDouble(), z.toDouble())
17+
}
18+
19+
fun getProgressOnTrack(track: Vector2d, trackStart: Vector2d, position: Vector2d): Double {
20+
val trackLengthSquared: Double = track.lengthSquared()
21+
if (trackLengthSquared == 0.0) {
22+
return 1.0
23+
}
24+
25+
val fromStart: Vector2d = position.sub(trackStart)
26+
return ((fromStart.x * track.x + fromStart.y * track.y) / trackLengthSquared).coerceIn(0.0..1.0)
827
}

src/main/kotlin/ru/octol1ttle/flightassistant/config/options/DisplayOptions.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ class DisplayOptions {
5050

5151
@SerialEntry
5252
var showFlightPathVector: Boolean = true
53-
@SerialEntry
53+
54+
@SerialEntry @Deprecated("does anyone use this??")
5455
var flightPathVectorSize: Float = 1.0f
5556

5657
@SerialEntry

src/main/kotlin/ru/octol1ttle/flightassistant/config/options/SafetyOptions.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class SafetyOptions {
4242
@SerialEntry
4343
var sinkRateAlertMethod: AlertMethod = AlertMethod.SCREEN_AND_AUDIO
4444
@SerialEntry
45-
var sinkRateLimitPitch: Boolean = true
45+
var sinkRateLimitPitch: Boolean = true // TODO: this often triggers BEFORE the automatic recovery. they should trigger at the same time and be paired with each other.
4646
@SerialEntry
4747
var sinkRateAutoThrust: Boolean = true
4848
@SerialEntry

src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/autoflight/AutoFlightComputer.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,23 +143,23 @@ class AutoFlightComputer(computers: ComputerBus) : Computer(computers), FlightCo
143143
return null
144144
}
145145

146-
return activeVerticalMode?.getControlInput(computers)?.copy(active = autopilot)
146+
return activeVerticalMode?.getControlInput(computers)?.copy(active = autopilot, deltaTimeMultiplier = 1.5f)
147147
}
148148

149149
override fun getHeadingInput(): ControlInput? {
150150
if (!flightDirectors && !autopilot) {
151151
return null
152152
}
153153

154-
return activeLateralMode?.getControlInput(computers)?.copy(active = autopilot)
154+
return activeLateralMode?.getControlInput(computers)?.copy(active = autopilot, deltaTimeMultiplier = 1.5f)
155155
}
156156

157157
override fun getRollInput(): ControlInput? {
158158
if (!autopilot) {
159159
return null
160160
}
161161

162-
return ControlInput(0.0f, ControlInput.Priority.NORMAL)
162+
return ControlInput(0.0f, ControlInput.Priority.NORMAL, deltaTimeMultiplier = 2.0f)
163163
}
164164

165165
override fun reset() {

src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/autoflight/FlightPlanComputer.kt

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package ru.octol1ttle.flightassistant.impl.computer.autoflight
22

3-
import kotlin.math.abs
43
import net.minecraft.network.chat.Component
54
import net.minecraft.resources.ResourceLocation
6-
import org.joml.Vector2d
75
import ru.octol1ttle.flightassistant.FlightAssistant
86
import ru.octol1ttle.flightassistant.api.computer.Computer
97
import ru.octol1ttle.flightassistant.api.computer.ComputerBus
108
import ru.octol1ttle.flightassistant.api.computer.ComputerQuery
9+
import ru.octol1ttle.flightassistant.api.util.extensions.distance2d
1110
import ru.octol1ttle.flightassistant.impl.computer.autoflight.modes.DirectCoordinatesLateralMode
11+
import ru.octol1ttle.flightassistant.impl.computer.autoflight.modes.ManagedAltitudeVerticalMode
12+
import ru.octol1ttle.flightassistant.impl.computer.autoflight.modes.SelectedAltitudeVerticalMode
1213
import ru.octol1ttle.flightassistant.impl.computer.autoflight.modes.SpeedReferenceVerticalMode
1314
import ru.octol1ttle.flightassistant.impl.computer.autoflight.modes.TakeoffThrustMode
1415
import ru.octol1ttle.flightassistant.impl.computer.autoflight.modes.TrackNavigationLateralMode
@@ -25,17 +26,34 @@ class FlightPlanComputer(computers: ComputerBus) : Computer(computers) {
2526
updateEnrouteData()
2627
}
2728

29+
private fun getEnrouteOrigin(): EnrouteWaypoint? {
30+
if (currentPhase == FlightPhase.TAKEOFF && !departureData.isDefault()) {
31+
return departureData.toEnrouteWaypoint()
32+
}
33+
return enrouteData.singleOrNull { it.active == EnrouteWaypoint.Active.ORIGIN }
34+
}
35+
36+
private fun getEnrouteTarget(): EnrouteWaypoint? {
37+
return enrouteData.singleOrNull { it.active == EnrouteWaypoint.Active.TARGET }
38+
}
39+
40+
private fun isCloseTo(target: EnrouteWaypoint): Boolean {
41+
return distance2d(target.coordinatesX, target.coordinatesZ, computers.data.x, computers.data.z) < computers.data.velocityPerSecond.horizontalDistance() * 3.0
42+
}
43+
2844
private fun updateFlightPhase(): FlightPhase {
2945
if (!computers.data.flying) {
30-
if (!departureData.isDefault() && abs(departureData.coordinatesX - computers.data.position.x) < 20 && abs(departureData.coordinatesZ - computers.data.position.z) < 20) {
46+
if (!departureData.isDefault() && distance2d(departureData.coordinatesX, departureData.coordinatesZ, computers.data.x, computers.data.z) < 20) {
3147
return FlightPhase.TAKEOFF
3248
}
3349
return FlightPhase.ON_GROUND
3450
}
3551

3652
if (currentPhase == FlightPhase.TAKEOFF) {
37-
if (enrouteData.isNotEmpty() && computers.data.altitude - (computers.data.groundY ?: computers.data.voidY.toDouble()) >= 15) {
38-
return FlightPhase.CLIMB
53+
if (enrouteData.isNotEmpty()) {
54+
if (enrouteData[0].altitude - computers.data.altitude < 5) {
55+
return FlightPhase.CLIMB
56+
}
3957
}
4058
return FlightPhase.TAKEOFF
4159
}
@@ -52,11 +70,12 @@ class FlightPlanComputer(computers: ComputerBus) : Computer(computers) {
5270
return
5371
}
5472

55-
val target: EnrouteWaypoint? = enrouteData.singleOrNull { it.active == EnrouteWaypoint.Active.TARGET }
56-
if (target != null && Vector2d.distance(target.coordinatesX.toDouble(), target.coordinatesZ.toDouble(), computers.data.position.x, computers.data.position.z) < computers.data.velocityPerSecond.horizontalDistance() * 3.0) {
73+
val target: EnrouteWaypoint = getEnrouteTarget() ?: return
74+
75+
if (isCloseTo(target)) {
5776
val targetIndex: Int = enrouteData.indexOf(target)
5877
val next: EnrouteWaypoint? = if (targetIndex + 1 >= enrouteData.size) null else enrouteData[targetIndex + 1]
59-
enrouteData.singleOrNull { it.active == EnrouteWaypoint.Active.ORIGIN }?.active = null
78+
getEnrouteOrigin()?.active = null
6079
if (next != null) {
6180
target.active = EnrouteWaypoint.Active.ORIGIN
6281
next.active = EnrouteWaypoint.Active.TARGET
@@ -75,7 +94,21 @@ class FlightPlanComputer(computers: ComputerBus) : Computer(computers) {
7594

7695
fun getVerticalMode(): AutoFlightComputer.VerticalMode? {
7796
return when (currentPhase) {
78-
FlightPhase.TAKEOFF -> SpeedReferenceVerticalMode(departureData.minimumClimbSpeed)
97+
FlightPhase.TAKEOFF -> {
98+
val target: EnrouteWaypoint? = getEnrouteTarget()
99+
if (target != null && target.altitude - computers.data.altitude < 5) {
100+
return SelectedAltitudeVerticalMode(target.altitude)
101+
}
102+
return SpeedReferenceVerticalMode(departureData.minimumClimbSpeed)
103+
}
104+
105+
FlightPhase.CLIMB -> {
106+
if (enrouteData.isEmpty()) return null
107+
val origin: EnrouteWaypoint? = getEnrouteOrigin()
108+
val target: EnrouteWaypoint = getEnrouteTarget() ?: return null
109+
if (origin != null) ManagedAltitudeVerticalMode(origin.coordinatesX, origin.coordinatesZ, origin.altitude, target.coordinatesX, target.coordinatesZ, target.altitude)
110+
else SelectedAltitudeVerticalMode(target.altitude)
111+
}
79112
else -> null
80113
}
81114
}
@@ -90,8 +123,8 @@ class FlightPlanComputer(computers: ComputerBus) : Computer(computers) {
90123

91124
FlightPhase.CLIMB -> {
92125
if (enrouteData.isEmpty()) return null
93-
val origin: EnrouteWaypoint? = enrouteData.singleOrNull { it.active == EnrouteWaypoint.Active.ORIGIN }
94-
val target: EnrouteWaypoint = enrouteData.singleOrNull { it.active == EnrouteWaypoint.Active.TARGET } ?: return null
126+
val origin: EnrouteWaypoint? = getEnrouteOrigin()
127+
val target: EnrouteWaypoint = getEnrouteTarget() ?: return null
95128
if (origin != null) TrackNavigationLateralMode(origin.coordinatesX, origin.coordinatesZ, target.coordinatesX, target.coordinatesZ)
96129
else DirectCoordinatesLateralMode(target.coordinatesX, target.coordinatesZ)
97130
}
@@ -125,6 +158,10 @@ class FlightPlanComputer(computers: ComputerBus) : Computer(computers) {
125158
return this == DEFAULT
126159
}
127160

161+
fun toEnrouteWaypoint(): EnrouteWaypoint {
162+
return EnrouteWaypoint(coordinatesX, coordinatesZ, elevation, active = EnrouteWaypoint.Active.ORIGIN)
163+
}
164+
128165
companion object {
129166
val DEFAULT: DepartureData = DepartureData()
130167
}

src/main/kotlin/ru/octol1ttle/flightassistant/impl/computer/autoflight/modes/BuiltInLateralModes.kt

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ package ru.octol1ttle.flightassistant.impl.computer.autoflight.modes
22

33
import net.minecraft.network.chat.Component
44
import org.joml.Vector2d
5-
import org.joml.Vector2i
65
import ru.octol1ttle.flightassistant.api.autoflight.ControlInput
76
import ru.octol1ttle.flightassistant.api.computer.ComputerBus
7+
import ru.octol1ttle.flightassistant.api.util.extensions.vec2dFromInts
8+
import ru.octol1ttle.flightassistant.api.util.extensions.getProgressOnTrack
89
import ru.octol1ttle.flightassistant.api.util.pointsToDirection
910
import ru.octol1ttle.flightassistant.impl.computer.autoflight.AutoFlightComputer
1011

@@ -21,7 +22,7 @@ data class HeadingLateralMode(override val targetHeading: Int) : AutoFlightCompu
2122
data class DirectCoordinatesLateralMode(override val targetX: Int, override val targetZ: Int) : AutoFlightComputer.LateralMode, AutoFlightComputer.FollowsCoordinatesMode {
2223
override fun getControlInput(computers: ComputerBus): ControlInput {
2324
return ControlInput(
24-
pointsToDirection(targetX.toDouble(), targetZ.toDouble(), computers.data.position.x, computers.data.position.z).toFloat() + 180.0f,
25+
pointsToDirection(targetX.toDouble(), targetZ.toDouble(), computers.data.x, computers.data.z).toFloat() + 180.0f,
2526
ControlInput.Priority.NORMAL,
2627
Component.translatable("mode.flightassistant.lateral.direct_coordinates")
2728
)
@@ -32,27 +33,16 @@ data class TrackNavigationLateralMode(val originX: Int, val originZ: Int, overri
3233
override fun getControlInput(computers: ComputerBus): ControlInput {
3334
val targetCoordinates: Vector2d = getTargetCoordinates(computers)
3435
return ControlInput(
35-
pointsToDirection(targetCoordinates.x, targetCoordinates.y, computers.data.position.x, computers.data.position.z).toFloat() + 180.0f,
36+
pointsToDirection(targetCoordinates.x, targetCoordinates.y, computers.data.x, computers.data.z).toFloat() + 180.0f,
3637
ControlInput.Priority.NORMAL,
3738
Component.translatable("mode.flightassistant.lateral.track_navigation")
3839
)
3940
}
4041

4142
private fun getTargetCoordinates(computers: ComputerBus): Vector2d {
42-
val track = Vector2d(Vector2i(targetX - originX, targetZ - originZ))
43-
val trackLengthSquared: Double = track.lengthSquared()
44-
if (trackLengthSquared == 0.0) {
45-
return Vector2d(targetX.toDouble(), targetZ.toDouble())
46-
}
47-
48-
val fromStart = Vector2d(computers.data.position.x - originX, computers.data.position.z - originZ)
49-
val trackProgress: Double = (fromStart.x * track.x + fromStart.y * track.y) / trackLengthSquared
50-
if (trackProgress < 0) {
51-
return Vector2d(originX.toDouble(), originZ.toDouble())
52-
}
53-
if (trackProgress > 1) {
54-
return Vector2d(targetX.toDouble(), targetZ.toDouble())
55-
}
43+
val origin: Vector2d = vec2dFromInts(originX, originZ)
44+
val track: Vector2d = vec2dFromInts(targetX, targetZ).sub(origin)
45+
val trackProgress: Double = getProgressOnTrack(track, origin, Vector2d(computers.data.x, computers.data.z))
5646
val closestTrackPoint = Vector2d(originX + trackProgress * track.x, originZ + trackProgress * track.y)
5747
val trackNormalized: Vector2d = track.normalize()
5848
return closestTrackPoint.add(trackNormalized.mul(computers.data.velocityPerSecond.horizontalDistance() * 3.0))

0 commit comments

Comments
 (0)