Skip to content

Commit

Permalink
feat: heading controller API, TOGA-aware autopilot heading control
Browse files Browse the repository at this point in the history
  • Loading branch information
Octol1ttle committed Apr 18, 2024
1 parent 3b7c9ed commit 8cf2dab
Show file tree
Hide file tree
Showing 16 changed files with 189 additions and 128 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ yarn_mappings=1.20.4+build.3
floader_version=0.15.3

# Mod Properties
mod_version=2.1.0+mc1.20.x
mod_version=2.2.0-alpha.1+mc1.20.x
maven_group=ru.octol1ttle.flightassistant
archives_base_name=flightassistant

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
import ru.octol1ttle.flightassistant.computers.impl.autoflight.AutoFlightComputer;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.FireworkController;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.PitchController;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.YawController;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.pitch.AutopilotPitchComputer;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.HeadingController;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.AutopilotControlComputer;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.pitch.ProtectionsPitchController;
import ru.octol1ttle.flightassistant.computers.impl.navigation.FlightPlanner;
import ru.octol1ttle.flightassistant.computers.impl.safety.AlertController;
Expand Down Expand Up @@ -43,10 +43,10 @@ public ComputerHost(@NotNull MinecraftClient mc) {
ComputerRegistry.register(new FlightPlanner());
ComputerRegistry.register(new GroundProximityComputer());
ComputerRegistry.register(new ElytraStateController());
ComputerRegistry.register(new YawController());
ComputerRegistry.register(new HeadingController());
ComputerRegistry.register(new AutoFlightComputer());
ComputerRegistry.register(new FlightPhaseComputer());
ComputerRegistry.register(new AutopilotPitchComputer());
ComputerRegistry.register(new AutopilotControlComputer());
ComputerRegistry.register(new AlertController(mc.getSoundManager()));

CustomComputerRegistrationCallback.EVENT.invoker().registerCustomComputers();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ru.octol1ttle.flightassistant.computers.api;

public enum ControllerPriority {
HIGHEST(0),
HIGH(1),
NORMAL(2),
LOW(3),
LOWEST(4);

public final int priority;

ControllerPriority(int priority) {
this.priority = priority;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ru.octol1ttle.flightassistant.computers.api;

import net.minecraft.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public interface IHeadingController {
/**
* Gets the target heading that this controller wants
* @return a pair of two floats: the first one is the target heading, second is the delta time multiplier. If 'null', the controller doesn't want any yaw at this moment
*/
@Nullable
Pair<@NotNull Float, @NotNull Float> getControlledHeading();

ControllerPriority getPriority();
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,7 @@ public interface IPitchController {
* @return a pair of two floats: the first one is the target pitch, second is the delta time multiplier. If 'null', the controller doesn't want any pitch at this moment
*/
@Nullable
Pair<@NotNull Float, @NotNull Float> getTargetPitch();
Pair<@NotNull Float, @NotNull Float> getControlledPitch();

Priority getPriority();

enum Priority {
HIGHEST(0),
HIGH(1),
NORMAL(2),
LOW(3),
LOWEST(4);

public final int priority;

Priority(int priority) {
this.priority = priority;
}
}
ControllerPriority getPriority();
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ public class AutoFlightComputer implements ITickableComputer {
private final GroundProximityComputer gpws = ComputerRegistry.resolve(GroundProximityComputer.class);
private final FlightPlanner plan = ComputerRegistry.resolve(FlightPlanner.class);
private final FireworkController firework = ComputerRegistry.resolve(FireworkController.class);
private final YawController yaw = ComputerRegistry.resolve(YawController.class);

public boolean flightDirectorsEnabled = false;
public boolean autoFireworkEnabled = false;
Expand Down Expand Up @@ -43,8 +42,6 @@ public void tick() {
firework.activateFirework(false);
}
}

yaw.targetHeading = autoPilotEnabled ? getTargetHeading() : null;
}

public @Nullable Integer getTargetSpeed() {
Expand Down Expand Up @@ -83,7 +80,5 @@ public void reset() {
flightDirectorsEnabled = false;
disconnectAutoFirework(true);
disconnectAutopilot(true);

yaw.targetHeading = null;
}
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
package ru.octol1ttle.flightassistant.computers.impl.autoflight.pitch;
package ru.octol1ttle.flightassistant.computers.impl.autoflight;

import net.minecraft.util.Pair;
import net.minecraft.util.math.MathHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Vector2d;
import ru.octol1ttle.flightassistant.FAMathHelper;
import ru.octol1ttle.flightassistant.computers.api.ControllerPriority;
import ru.octol1ttle.flightassistant.computers.api.IPitchController;
import ru.octol1ttle.flightassistant.computers.api.ITickableComputer;
import ru.octol1ttle.flightassistant.computers.api.IHeadingController;
import ru.octol1ttle.flightassistant.computers.impl.AirDataComputer;
import ru.octol1ttle.flightassistant.computers.impl.FlightPhaseComputer;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.AutoFlightComputer;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.PitchController;
import ru.octol1ttle.flightassistant.computers.impl.navigation.FlightPlanner;
import ru.octol1ttle.flightassistant.registries.ComputerRegistry;

public class AutopilotPitchComputer implements ITickableComputer, IPitchController {
public class AutopilotControlComputer implements ITickableComputer, IPitchController, IHeadingController {
private final AirDataComputer data = ComputerRegistry.resolve(AirDataComputer.class);
private final AutoFlightComputer autoflight = ComputerRegistry.resolve(AutoFlightComputer.class);
private final FlightPhaseComputer phase = ComputerRegistry.resolve(FlightPhaseComputer.class);
private final FlightPlanner plan = ComputerRegistry.resolve(FlightPlanner.class);
public Float targetPitch;
public Float targetHeading;

@Override
public void tick() {
targetPitch = computeTargetPitch();
targetHeading = computeTargetHeading();
}

private Float computeTargetPitch() {
Expand Down Expand Up @@ -92,8 +94,16 @@ private float computeClimbPitch(float diff, Vector2d target) {
return degrees;
}

private Float computeTargetHeading() {
if (phase.phase == FlightPhaseComputer.FlightPhase.TAKEOFF || phase.phase == FlightPhaseComputer.FlightPhase.GO_AROUND) {
return data.heading();
}

return autoflight.getTargetHeading();
}

@Override
public @Nullable Pair<@NotNull Float, @NotNull Float> getTargetPitch() {
public @Nullable Pair<@NotNull Float, @NotNull Float> getControlledPitch() {
if (!autoflight.autoPilotEnabled || targetPitch == null) {
return null;
}
Expand All @@ -102,13 +112,22 @@ private float computeClimbPitch(float diff, Vector2d target) {
}

@Override
public Priority getPriority() {
return Priority.NORMAL;
public @Nullable Pair<@NotNull Float, @NotNull Float> getControlledHeading() {
if (!autoflight.autoPilotEnabled || targetHeading == null) {
return null;
}

return new Pair<>(targetHeading, 1.0f);
}

@Override
public ControllerPriority getPriority() {
return ControllerPriority.NORMAL;
}

@Override
public String getId() {
return "autopilot_pitch_ctl";
return "autopilot_ctl";
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package ru.octol1ttle.flightassistant.computers.impl.autoflight;

import java.util.ArrayList;
import java.util.List;
import net.minecraft.util.Pair;
import net.minecraft.util.math.MathHelper;
import org.jetbrains.annotations.NotNull;
import ru.octol1ttle.flightassistant.computers.api.ControllerPriority;
import ru.octol1ttle.flightassistant.computers.api.IHeadingController;
import ru.octol1ttle.flightassistant.computers.impl.AirDataComputer;
import ru.octol1ttle.flightassistant.computers.api.ITickableComputer;
import ru.octol1ttle.flightassistant.computers.impl.TimeComputer;
import ru.octol1ttle.flightassistant.registries.ComputerRegistry;
import ru.octol1ttle.flightassistant.registries.events.ComputerRegisteredCallback;

public class HeadingController implements ITickableComputer {
private final AirDataComputer data = ComputerRegistry.resolve(AirDataComputer.class);
private final TimeComputer time = ComputerRegistry.resolve(TimeComputer.class);
private final List<IHeadingController> controllers = new ArrayList<>();

public HeadingController() {
ComputerRegisteredCallback.EVENT.register((computer -> {
if (computer instanceof IHeadingController controller) {
controllers.add(controller);
}
}));
}

@Override
public void tick() {
if (!data.canAutomationsActivate()) {
return;
}

ControllerPriority lastPriority = null;
for (IHeadingController controller : controllers) {
if (lastPriority != null && controller.getPriority() != lastPriority) {
break;
}

Pair<@NotNull Float, @NotNull Float> targetPitch = controller.getControlledHeading();
if (targetPitch != null) {
smoothSetHeading(targetPitch.getLeft(), MathHelper.clamp(time.deltaTime * targetPitch.getRight(), 0.001f, 1.0f));
lastPriority = controller.getPriority();
}
}
}

private void smoothSetHeading(Float heading, float delta) {
if (heading == null) {
return;
}

float difference = heading - data.heading();
if (difference < -180.0f) {
difference += 360.0f;
}
if (difference > 180.0f) {
difference -= 360.0f;
}

float newHeading;
if (Math.abs(difference) < 0.05f) {
newHeading = heading;
} else {
newHeading = data.heading() + difference * delta;
}

data.player().setYaw(newHeading - 180.0f);
}

@Override
public String getId() {
return "heading_ctl";
}

@Override
public void reset() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.minecraft.util.Pair;
import net.minecraft.util.math.MathHelper;
import org.jetbrains.annotations.NotNull;
import ru.octol1ttle.flightassistant.computers.api.ControllerPriority;
import ru.octol1ttle.flightassistant.computers.api.IPitchController;
import ru.octol1ttle.flightassistant.computers.api.ITickableComputer;
import ru.octol1ttle.flightassistant.computers.impl.AirDataComputer;
Expand Down Expand Up @@ -39,13 +40,13 @@ public void tick() {
return;
}

IPitchController.Priority lastPriority = null;
ControllerPriority lastPriority = null;
for (IPitchController controller : controllers) {
if (lastPriority != null && controller.getPriority() != lastPriority) {
break;
}

Pair<@NotNull Float, @NotNull Float> targetPitch = controller.getTargetPitch();
Pair<@NotNull Float, @NotNull Float> targetPitch = controller.getControlledPitch();
if (targetPitch != null) {
smoothSetPitch(targetPitch.getLeft(), MathHelper.clamp(time.deltaTime * targetPitch.getRight(), 0.001f, 1.0f));
lastPriority = controller.getPriority();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.minecraft.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import ru.octol1ttle.flightassistant.computers.api.ControllerPriority;
import ru.octol1ttle.flightassistant.computers.api.IComputer;
import ru.octol1ttle.flightassistant.computers.api.IPitchController;
import ru.octol1ttle.flightassistant.computers.impl.AirDataComputer;
Expand All @@ -15,7 +16,7 @@ public class ProtectionsPitchController implements IComputer, IPitchController {
private final PitchLimitComputer limit = ComputerRegistry.resolve(PitchLimitComputer.class);

@Override
public @Nullable Pair<@NotNull Float, @NotNull Float> getTargetPitch() {
public @Nullable Pair<@NotNull Float, @NotNull Float> getControlledPitch() {
Pair<Float, Float> safePitches = limit.getSafePitches(ComputerConfig.ProtectionMode::recover);

if (data.pitch() > safePitches.getRight()) {
Expand All @@ -28,8 +29,8 @@ public class ProtectionsPitchController implements IComputer, IPitchController {
}

@Override
public Priority getPriority() {
return Priority.HIGHEST;
public ControllerPriority getPriority() {
return ControllerPriority.HIGHEST;
}

@Override
Expand Down
Loading

0 comments on commit 8cf2dab

Please sign in to comment.