diff --git a/.vscode/launch.json b/.vscode/launch.json index beb5d53..c826b57 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,5 +1,12 @@ { "configurations": [ + { + "type": "java", + "name": "Main", + "request": "launch", + "mainClass": "com.pesterenan.Main", + "projectName": "MechPeste-Java" + }, { "type": "java", "name": "Launch MechPeste", diff --git a/src/com/pesterenan/Main.java b/src/com/pesterenan/Main.java new file mode 100644 index 0000000..ceb84df --- /dev/null +++ b/src/com/pesterenan/Main.java @@ -0,0 +1,229 @@ +package com.pesterenan; + +import java.io.IOException; + +import com.pesterenan.utils.Utilities; +import com.pesterenan.utils.Vector; + +import krpc.client.Connection; +import krpc.client.RPCException; +import krpc.client.services.Drawing; +import krpc.client.services.Drawing.Line; +import krpc.client.services.SpaceCenter; +import krpc.client.services.SpaceCenter.Control; +import krpc.client.services.SpaceCenter.DockingPort; +import krpc.client.services.SpaceCenter.ReferenceFrame; +import krpc.client.services.SpaceCenter.SASMode; +import krpc.client.services.SpaceCenter.Vessel; + +public class Main { + private static Connection connection; + private static SpaceCenter spaceCenter; + private static Drawing drawing; + private static Control control; + + private static Vessel activeVessel; + private static Vessel targetVessel; + + private static ReferenceFrame orbitalRefVessel; + private static ReferenceFrame vesselRefFrame; + private static ReferenceFrame orbitalRefBody; + private static final double SPEED_LIMIT = 3.0; + private static final double DISTANCE_LIMIT = 25.0; + private static Line distanceLine; + private static Line distLineXAxis; + private static Line distLineYAxis; + private static Line distLineZAxis; + private static DockingPort myDockingPort; + private static DockingPort targetDockingPort; + private static Vector positionMyDockingPort; + private static Vector positionTargetDockingPort; + + private static void initializeParameters() { + try { + connection = Connection.newInstance(); + spaceCenter = SpaceCenter.newInstance(connection); + drawing = Drawing.newInstance(connection); + activeVessel = spaceCenter.getActiveVessel(); + targetVessel = spaceCenter.getTargetVessel(); + vesselRefFrame = activeVessel.getReferenceFrame(); + orbitalRefVessel = activeVessel.getOrbitalReferenceFrame(); + orbitalRefBody = activeVessel.getOrbit().getBody().getReferenceFrame(); + + myDockingPort = activeVessel.getParts().getDockingPorts().get(0); + targetDockingPort = targetVessel.getParts().getDockingPorts().get(0); + + positionMyDockingPort = new Vector(myDockingPort.position(orbitalRefVessel)); + positionTargetDockingPort = new Vector(targetDockingPort.position(orbitalRefVessel)); + + createLines(positionMyDockingPort, positionTargetDockingPort); + + } catch (IOException | RPCException e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) { + try { + // Initialize parameters for the script, connection and setup: + initializeParameters(); + + // Setting up the control + control = activeVessel.getControl(); + control.setSAS(true); + control.setRCS(false); + control.setSASMode(SASMode.STABILITY_ASSIST); + + Vector targetDirection = new Vector(activeVessel.position(orbitalRefVessel)) + .subtract(new Vector(targetVessel.position(orbitalRefVessel))).multiply(-1); + activeVessel.getAutoPilot().setReferenceFrame(orbitalRefVessel); + activeVessel.getAutoPilot().setTargetDirection(targetDirection.toTriplet()); + activeVessel.getAutoPilot().setTargetRoll(90); + activeVessel.getAutoPilot().engage(); + // Fazer a nave apontar usando o piloto automático, na marra + while (Math.abs(activeVessel.getAutoPilot().getError()) > 1) { + activeVessel.getAutoPilot().wait_(); + } + control.setRCS(true); + activeVessel.getAutoPilot().disengage(); + control.setSAS(true); + control.setSASMode(SASMode.STABILITY_ASSIST); + + // PRIMEIRA PARTE DO DOCKING: APROXIMAÇÃO + + Vector targetPosition = new Vector(targetVessel.position(vesselRefFrame)); + double lastXTargetPos = targetPosition.x; + double lastYTargetPos = targetPosition.y; + double lastZTargetPos = targetPosition.z; + long sleepTime = 25; + double currentXAxisSpeed = 0; + double currentYAxisSpeed = 0; + double currentZAxisSpeed = 0; + while (Math.abs(lastYTargetPos) >= DISTANCE_LIMIT) { + targetPosition = new Vector(targetVessel.position(vesselRefFrame)); + + // Atualizar posições para linhas + positionMyDockingPort = new Vector(myDockingPort.position(vesselRefFrame)); + positionTargetDockingPort = new Vector(targetDockingPort.position(vesselRefFrame)); + updateLines(positionMyDockingPort, positionTargetDockingPort); + + // Calcular velocidade de cada eixo: + currentXAxisSpeed = (targetPosition.x - lastXTargetPos) * sleepTime; + currentYAxisSpeed = (targetPosition.y - lastYTargetPos) * sleepTime; + currentZAxisSpeed = (targetPosition.z - lastZTargetPos) * sleepTime; + + // Calcular a aceleração para cada eixo no RCS: + float forwardsError = calculateThrottle(DISTANCE_LIMIT, DISTANCE_LIMIT * 2, currentYAxisSpeed, + targetPosition.y, SPEED_LIMIT); + float sidewaysError = calculateThrottle(0, 10, currentXAxisSpeed, targetPosition.x, SPEED_LIMIT); + float upwardsError = calculateThrottle(0, 10, currentZAxisSpeed, targetPosition.z, SPEED_LIMIT); + control.setForward((float) forwardsError); + control.setRight((float) sidewaysError); + control.setUp((float) -upwardsError); + + // Guardar últimas posições: + lastXTargetPos = targetPosition.x; + lastYTargetPos = targetPosition.y; + lastZTargetPos = targetPosition.z; + Thread.sleep(sleepTime); + } + + // SEGUNDA PARTE APONTAR PRO LADO CONTRARIO: + Vector direcaoContrariaDockingPortAlvo = new Vector(targetDockingPort.direction(orbitalRefVessel)) + .multiply(-1); + control.setSAS(false); + control.setRCS(false); + activeVessel.getAutoPilot().engage(); + activeVessel.getAutoPilot().setReferenceFrame(orbitalRefVessel); + activeVessel.getAutoPilot().setTargetDirection(direcaoContrariaDockingPortAlvo.toTriplet()); + activeVessel.getAutoPilot().setTargetRoll(90); + while (Math.abs(activeVessel.getAutoPilot().getError()) > 1) { + activeVessel.getAutoPilot().wait_(); + } + activeVessel.getAutoPilot().disengage(); + control.setSAS(true); + control.setSASMode(SASMode.STABILITY_ASSIST); + Thread.sleep(1000); + control.setRCS(true); + + while (targetVessel != null) { + targetPosition = new Vector(targetDockingPort.position(vesselRefFrame)); + + // Atualizar posições para linhas + positionMyDockingPort = new Vector(myDockingPort.position(vesselRefFrame)); + updateLines(positionMyDockingPort, targetPosition); + + // Calcular velocidade de cada eixo: + currentXAxisSpeed = (targetPosition.x - lastXTargetPos) * sleepTime; + currentYAxisSpeed = (targetPosition.y - lastYTargetPos) * sleepTime; + currentZAxisSpeed = (targetPosition.z - lastZTargetPos) * sleepTime; + + // Calcular a aceleração para cada eixo no RCS: + float forwardsError = calculateThrottle(5, 10, currentYAxisSpeed, + targetPosition.y, SPEED_LIMIT); + float sidewaysError = calculateThrottle(-1, 10, currentXAxisSpeed, targetPosition.x, SPEED_LIMIT); + float upwardsError = calculateThrottle(-1, 10, currentZAxisSpeed, targetPosition.z, SPEED_LIMIT); + control.setForward((float) forwardsError); + control.setRight((float) sidewaysError); + control.setUp((float) -upwardsError); + + // Guardar últimas posições: + lastXTargetPos = targetPosition.x; + lastYTargetPos = targetPosition.y; + lastZTargetPos = targetPosition.z; + Thread.sleep(sleepTime); + } + // // Close the connection when finished + // connection.close(); + } catch (RPCException | InterruptedException e) { + e.printStackTrace(); + } + } + + private static float calculateThrottle(double minDistance, double maxDistance, double currentSpeed, + double currentPosition, double speedLimit) { + double limiter = Utilities.remap(minDistance, maxDistance, 0, 1, Math.abs(currentPosition), true); + double change = (Utilities.remap(-speedLimit, speedLimit, -1.0, 1.0, + currentSpeed + (Math.signum(currentPosition) * (limiter * speedLimit)), true)); + return (float) change; + } + + private static void createLines(Vector start, Vector end) { + try { + distanceLine = drawing.addLine(start.toTriplet(), + end.toTriplet(), vesselRefFrame, true); + distLineXAxis = drawing.addLine(start.toTriplet(), + new Vector(end.x, 0.0, 0.0).toTriplet(), + vesselRefFrame, true); + distLineYAxis = drawing.addLine(start.toTriplet(), + new Vector(end.x, end.y, 0.0).toTriplet(), + vesselRefFrame, true); + distLineZAxis = drawing.addLine(start.toTriplet(), + end.toTriplet(), + vesselRefFrame, true); + distanceLine.setThickness(0.5f); + distLineXAxis.setThickness(0.25f); + distLineYAxis.setThickness(0.25f); + distLineZAxis.setThickness(0.25f); + distLineXAxis.setColor(new Vector(1.0, 0.0, 0.0).toTriplet()); + distLineYAxis.setColor(new Vector(0.0, 1.0, 0.0).toTriplet()); + distLineZAxis.setColor(new Vector(0.0, 0.0, 1.0).toTriplet()); + } catch (RPCException e) { + } + } + + private static void updateLines(Vector start, Vector end) { + // Updating drawing lines: + try { + distanceLine.setStart(start.toTriplet()); + distanceLine.setEnd(end.toTriplet()); + distLineXAxis.setStart(start.toTriplet()); + distLineXAxis.setEnd(new Vector(end.x, 0.0, 0.0).toTriplet()); + distLineYAxis.setStart(distLineXAxis.getEnd()); + distLineYAxis.setEnd(new Vector(end.x, end.y, 0.0).toTriplet()); + distLineZAxis.setStart(distLineYAxis.getEnd()); + distLineZAxis.setEnd(end.toTriplet()); + } catch (RPCException e) { + } + } +} diff --git a/src/com/pesterenan/MechPeste.java b/src/com/pesterenan/MechPeste.java index 71f917c..0367073 100644 --- a/src/com/pesterenan/MechPeste.java +++ b/src/com/pesterenan/MechPeste.java @@ -9,7 +9,8 @@ import java.util.Map; import java.util.stream.Collectors; -import javax.swing.*; +import javax.swing.DefaultListModel; +import javax.swing.ListModel; import com.pesterenan.model.ActiveVessel; import com.pesterenan.resources.Bundle; @@ -33,10 +34,6 @@ public class MechPeste { private static int currentVesselId = -1; private static ActiveVessel currentVessel = null; - private MechPeste() { - MainGui.newInstance(); - } - public static void main(String[] args) { MechPeste.newInstance().connectToKSP(); MechPeste.newInstance().checkActiveVessel(); @@ -92,32 +89,6 @@ public static ListModel getCurrentManeuvers() { return list; } - private static boolean filterVessels(Vessel vessel, String search) { - if (search == "all") { - return true; - } - double TEN_KILOMETERS = 10000.0; - try { - Vessel active = MechPeste.getSpaceCenter().getActiveVessel(); - if (vessel.getOrbit().getBody().getName().equals(active.getOrbit().getBody().getName())) { - final Vector activePos = new Vector(active.position(active.getSurfaceReferenceFrame())); - final Vector vesselPos = new Vector(vessel.position(active.getSurfaceReferenceFrame())); - final double distance = Vector.distance(activePos, vesselPos); - switch (search) { - case "closest": - if (distance < TEN_KILOMETERS) { - return true; - } - break; - case "samebody": - return true; - } - } - } catch (RPCException ignored) { - } - return false; - } - public static String getVesselInfo(int selectedIndex) { try { Vessel naveAtual = spaceCenter.getVessels().stream().filter(v -> v.hashCode() == selectedIndex).findFirst() @@ -143,35 +114,42 @@ public static void changeToVessel(int selectedIndex) { } } - public KRPC.GameScene getCurrentGameScene() throws RPCException { - return krpc.getCurrentGameScene(); + public static void cancelControl(ActionEvent e) { + currentVessel.cancelControl(); } - private void checkActiveVessel() { - while (getConnection() != null) { - try { - if (!MechPeste.newInstance().getCurrentGameScene().equals(KRPC.GameScene.FLIGHT)) { - Thread.sleep(100); - return; - } - int activeVesselId = spaceCenter.getActiveVessel().hashCode(); - // If the current active vessel changes, create a new connection - if (currentVesselId != activeVesselId) { - currentVessel = new ActiveVessel(); - currentVesselId = currentVessel.getCurrentVesselId(); - } - if (currentVesselId != -1) { - currentVessel.recordTelemetryData(); - if (currentVessel.hasModuleRunning()) { - setStatusMessage(currentVessel.getCurrentStatus()); - } - FunctionsAndTelemetryJPanel.updateTelemetry(currentVessel.getTelemetryData()); - CreateManeuverJPanel.updatePanel(getCurrentManeuvers()); + private static boolean filterVessels(Vessel vessel, String search) { + if (search == "all") { + return true; + } + double TEN_KILOMETERS = 10000.0; + try { + Vessel active = MechPeste.getSpaceCenter().getActiveVessel(); + if (vessel.getOrbit().getBody().getName().equals(active.getOrbit().getBody().getName())) { + final Vector activePos = new Vector(active.position(active.getSurfaceReferenceFrame())); + final Vector vesselPos = new Vector(vessel.position(active.getSurfaceReferenceFrame())); + final double distance = Vector.distance(activePos, vesselPos); + switch (search) { + case "closest": + if (distance < TEN_KILOMETERS) { + return true; + } + break; + case "samebody": + return true; } - Thread.sleep(100); - } catch (RPCException | InterruptedException ignored) { } + } catch (RPCException ignored) { } + return false; + } + + private MechPeste() { + MainGui.newInstance(); + } + + public KRPC.GameScene getCurrentGameScene() throws RPCException { + return krpc.getCurrentGameScene(); } public void startModule(Map commands) { @@ -205,7 +183,30 @@ public void checkConnection() { } } - public static void cancelControl(ActionEvent e) { - currentVessel.cancelControl(); + private void checkActiveVessel() { + while (getConnection() != null) { + try { + if (!MechPeste.newInstance().getCurrentGameScene().equals(KRPC.GameScene.FLIGHT)) { + Thread.sleep(100); + return; + } + int activeVesselId = spaceCenter.getActiveVessel().hashCode(); + // If the current active vessel changes, create a new connection + if (currentVesselId != activeVesselId) { + currentVessel = new ActiveVessel(); + currentVesselId = currentVessel.getCurrentVesselId(); + } + if (currentVesselId != -1) { + currentVessel.recordTelemetryData(); + if (currentVessel.hasModuleRunning()) { + setStatusMessage(currentVessel.getCurrentStatus()); + } + FunctionsAndTelemetryJPanel.updateTelemetry(currentVessel.getTelemetryData()); + CreateManeuverJPanel.updatePanel(getCurrentManeuvers()); + } + Thread.sleep(100); + } catch (RPCException | InterruptedException ignored) { + } + } } } diff --git a/src/com/pesterenan/controllers/DockingController.java b/src/com/pesterenan/controllers/DockingController.java new file mode 100644 index 0000000..eaea4b7 --- /dev/null +++ b/src/com/pesterenan/controllers/DockingController.java @@ -0,0 +1,297 @@ +package com.pesterenan.controllers; + +import static com.pesterenan.MechPeste.getConnection; +import static com.pesterenan.MechPeste.getSpaceCenter; + +import java.util.Map; + +import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Utilities; +import com.pesterenan.utils.Vector; +import com.pesterenan.views.StatusJPanel; + +import krpc.client.RPCException; +import krpc.client.services.Drawing; +import krpc.client.services.Drawing.Line; +import krpc.client.services.SpaceCenter.Control; +import krpc.client.services.SpaceCenter.DockingPort; +import krpc.client.services.SpaceCenter.ReferenceFrame; +import krpc.client.services.SpaceCenter.SASMode; +import krpc.client.services.SpaceCenter.Vessel; + +public class DockingController extends Controller { + + private Drawing drawing; + private Vessel targetVessel; + private Control control; + + private ReferenceFrame orbitalRefVessel; + private ReferenceFrame vesselRefFrame; + private ReferenceFrame orbitalRefBody; + private Line distanceLine; + private Line distLineXAxis; + private Line distLineYAxis; + private Line distLineZAxis; + private DockingPort myDockingPort; + private DockingPort targetDockingPort; + private Vector positionMyDockingPort; + private Vector positionTargetDockingPort; + + private final double DISTANCE_LIMIT = 25.0; + private double SPEED_LIMIT = 3.0; + private double currentXAxisSpeed = 0.0; + private double currentYAxisSpeed = 0.0; + private double currentZAxisSpeed = 0.0; + private double lastXTargetPos = 0.0; + private double lastYTargetPos = 0.0; + private double lastZTargetPos = 0.0; + private long sleepTime = 25; + private DOCKING_STEPS dockingStep; + + public DockingController(Map commands) { + super(); + this.commands = commands; + initializeParameters(); + } + + private void initializeParameters() { + try { + SPEED_LIMIT = Double.parseDouble(commands.get(Modulos.VELOCIDADE_MAX.get())); + drawing = Drawing.newInstance(getConnection()); + targetVessel = getSpaceCenter().getTargetVessel(); + control = getNaveAtual().getControl(); + vesselRefFrame = getNaveAtual().getReferenceFrame(); + orbitalRefVessel = getNaveAtual().getOrbitalReferenceFrame(); + orbitalRefBody = getNaveAtual().getOrbit().getBody().getReferenceFrame(); + + myDockingPort = getNaveAtual().getParts().getDockingPorts().get(0); + targetDockingPort = targetVessel.getParts().getDockingPorts().get(0); + + positionMyDockingPort = new Vector(myDockingPort.position(orbitalRefVessel)); + positionTargetDockingPort = new Vector(targetDockingPort.position(orbitalRefVessel)); + } catch (RPCException ignored) { + } + } + + @Override + public void run() { + if (commands.get(Modulos.MODULO.get()).equals(Modulos.MODULO_DOCKING.get())) { + startDocking(); + } + } + + private void pointToTarget(Vector targetDirection) throws RPCException, InterruptedException { + getNaveAtual().getAutoPilot().setReferenceFrame(orbitalRefVessel); + getNaveAtual().getAutoPilot().setTargetDirection(targetDirection.toTriplet()); + getNaveAtual().getAutoPilot().setTargetRoll(90); + getNaveAtual().getAutoPilot().engage(); + // Fazer a nave apontar usando o piloto automático, na marra + while (Math.abs(getNaveAtual().getAutoPilot().getError()) > 3) { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + Thread.sleep(100); + System.out.println(getNaveAtual().getAutoPilot().getError()); + } + getNaveAtual().getAutoPilot().disengage(); + control.setSAS(true); + control.setSASMode(SASMode.STABILITY_ASSIST); + } + + private void getCloserToTarget(Vector targetPosition) throws InterruptedException, RPCException { + lastXTargetPos = targetPosition.x; + lastYTargetPos = targetPosition.y; + lastZTargetPos = targetPosition.z; + + while (Math.abs(lastYTargetPos) >= DISTANCE_LIMIT) { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + targetPosition = new Vector(targetVessel.position(vesselRefFrame)); + controlShipRCS(targetPosition, DISTANCE_LIMIT); + Thread.sleep(sleepTime); + } + + } + + public void startDocking() { + try { + // Setting up the control + control.setSAS(true); + control.setRCS(false); + control.setSASMode(SASMode.STABILITY_ASSIST); + createLines(positionMyDockingPort, positionTargetDockingPort); + + // PRIMEIRA PARTE DO DOCKING: APROXIMAÇÃO + Vector targetPosition = new Vector(targetVessel.position(vesselRefFrame)); + if (targetPosition.magnitude() > DISTANCE_LIMIT) { + // Apontar para o alvo: + Vector targetDirection = new Vector(getNaveAtual().position(orbitalRefVessel)) + .subtract(new Vector(targetVessel.position(orbitalRefVessel))).multiply(-1); + pointToTarget(targetDirection); + + control.setRCS(true); + + getCloserToTarget(targetPosition); + } + + control.setSAS(false); + control.setRCS(false); + + // SEGUNDA PARTE FICAR DE FRENTE COM A DOCKING PORT: + Vector targetDockingPortDirection = new Vector(targetDockingPort.direction(orbitalRefVessel)) + .multiply(-1); + pointToTarget(targetDockingPortDirection); + + Thread.sleep(1000); + control.setRCS(true); + double safeDistance = 10; + while (true) { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + targetPosition = new Vector(targetDockingPort.position(vesselRefFrame)) + .subtract(new Vector(myDockingPort.position(vesselRefFrame))); + if (targetPosition.magnitude() < safeDistance) { + safeDistance = 1; + } + controlShipRCS(targetPosition, safeDistance); + Thread.sleep(sleepTime); + } + } catch (RPCException | InterruptedException | IllegalArgumentException e) { + StatusJPanel.setStatusMessage("Docking aborted."); + } + } + + /* + * Possibilidades do docking: + * primeiro: a nave ta na orientação certa, e só precisa seguir em frente X e Z + * = 0, Y positivo + * segundo: a nave ta na orientação certa, mas precisa corrigir a posição X e Z, + * Y positivo + * terceiro: a nave está atrás da docking port, precisa corrigir Y primeiro, Y + * negativo + * quarto: a nave está atrás da docking port, precisa afastar X e Z longe da + * nave primeiro, Y negativo + */ + + private enum DOCKING_STEPS { + APPROACH, LINE_UP_WITH_TARGET, GO_IN_FRONT_OF_TARGET + } + + private DOCKING_STEPS checkDockingStep(Vector targetPosition, double forwardsDistanceLimit) { + double sidewaysDistance = Math.abs(targetPosition.x); + double upwardsDistance = Math.abs(targetPosition.z); + boolean isInFrontOfTarget = Math.signum(targetPosition.y) == 1; + boolean isOnTheBackOfTarget = Math.signum(targetPosition.y) == -1 && targetPosition.y < forwardsDistanceLimit; + + if (isOnTheBackOfTarget) { + return DOCKING_STEPS.GO_IN_FRONT_OF_TARGET; + } + if (isInFrontOfTarget && (sidewaysDistance > 5 || upwardsDistance > 5)) { + return DOCKING_STEPS.LINE_UP_WITH_TARGET; + } + return DOCKING_STEPS.APPROACH; + } + + private void controlShipRCS(Vector targetPosition, double forwardsDistanceLimit) { + try { + // Atualizar posições para linhas + positionMyDockingPort = new Vector(myDockingPort.position(vesselRefFrame)); + updateLines(positionMyDockingPort, targetPosition); + + // Calcular velocidade de cada eixo: + currentXAxisSpeed = (targetPosition.x - lastXTargetPos) * sleepTime; + currentYAxisSpeed = (targetPosition.y - lastYTargetPos) * sleepTime; + currentZAxisSpeed = (targetPosition.z - lastZTargetPos) * sleepTime; + + dockingStep = checkDockingStep(targetPosition, forwardsDistanceLimit); + float forwardsError, upwardsError, sidewaysError = 0; + switch (dockingStep) { + case APPROACH: + // Calcular a aceleração para cada eixo no RCS: + forwardsError = calculateThrottle(forwardsDistanceLimit, forwardsDistanceLimit * 3, currentYAxisSpeed, + targetPosition.y, SPEED_LIMIT); + sidewaysError = calculateThrottle(0, 5, currentXAxisSpeed, targetPosition.x, SPEED_LIMIT); + upwardsError = calculateThrottle(0, 5, currentZAxisSpeed, targetPosition.z, SPEED_LIMIT); + control.setForward(forwardsError); + control.setRight(sidewaysError); + control.setUp(-upwardsError); + break; + case LINE_UP_WITH_TARGET: + forwardsError = calculateThrottle(forwardsDistanceLimit, forwardsDistanceLimit * 3, currentYAxisSpeed, + targetPosition.y, 0); + sidewaysError = calculateThrottle(0, 10, currentXAxisSpeed, targetPosition.x, SPEED_LIMIT); + upwardsError = calculateThrottle(0, 10, currentZAxisSpeed, targetPosition.z, SPEED_LIMIT); + control.setForward(forwardsError); + control.setRight(sidewaysError); + control.setUp(-upwardsError); + break; + case GO_IN_FRONT_OF_TARGET: + forwardsError = calculateThrottle(-20, -10, currentYAxisSpeed, + targetPosition.y, SPEED_LIMIT); + sidewaysError = calculateThrottle(0, 5, currentXAxisSpeed, targetPosition.x, 0); + upwardsError = calculateThrottle(0, 5, currentZAxisSpeed, targetPosition.z, 0); + control.setForward(forwardsError); + control.setRight(sidewaysError); + control.setUp(-upwardsError); + break; + } + System.out.println(dockingStep); + + // Guardar últimas posições: + lastXTargetPos = targetPosition.x; + lastYTargetPos = targetPosition.y; + lastZTargetPos = targetPosition.z; + } catch (RPCException ignored) { + } + } + + private float calculateThrottle(double minDistance, double maxDistance, double currentSpeed, + double currentPosition, double speedLimit) { + double limiter = Utilities.remap(minDistance, maxDistance, 0, 1, Math.abs(currentPosition), true); + double change = (Utilities.remap(-speedLimit, speedLimit, -1.0, 1.0, + currentSpeed + (Math.signum(currentPosition) * (limiter * speedLimit)), true)); + return (float) change; + } + + private void createLines(Vector start, Vector end) { + try { + distanceLine = drawing.addLine(start.toTriplet(), + end.toTriplet(), vesselRefFrame, true); + distLineXAxis = drawing.addLine(start.toTriplet(), + new Vector(end.x, 0.0, 0.0).toTriplet(), + vesselRefFrame, true); + distLineYAxis = drawing.addLine(start.toTriplet(), + new Vector(end.x, end.y, 0.0).toTriplet(), + vesselRefFrame, true); + distLineZAxis = drawing.addLine(start.toTriplet(), + end.toTriplet(), + vesselRefFrame, true); + distanceLine.setThickness(0.5f); + distLineXAxis.setThickness(0.25f); + distLineYAxis.setThickness(0.25f); + distLineZAxis.setThickness(0.25f); + distLineXAxis.setColor(new Vector(1.0, 0.0, 0.0).toTriplet()); + distLineYAxis.setColor(new Vector(0.0, 1.0, 0.0).toTriplet()); + distLineZAxis.setColor(new Vector(0.0, 0.0, 1.0).toTriplet()); + } catch (RPCException e) { + } + } + + private void updateLines(Vector start, Vector end) { + // Updating drawing lines: + try { + distanceLine.setStart(start.toTriplet()); + distanceLine.setEnd(end.toTriplet()); + distLineXAxis.setStart(start.toTriplet()); + distLineXAxis.setEnd(new Vector(end.x, 0.0, 0.0).toTriplet()); + distLineYAxis.setStart(distLineXAxis.getEnd()); + distLineYAxis.setEnd(new Vector(end.x, end.y, 0.0).toTriplet()); + distLineZAxis.setStart(distLineYAxis.getEnd()); + distLineZAxis.setEnd(end.toTriplet()); + } catch (RPCException e) { + } + } + +} diff --git a/src/com/pesterenan/controllers/LandingController.java b/src/com/pesterenan/controllers/LandingController.java index 4cd37eb..df9072c 100644 --- a/src/com/pesterenan/controllers/LandingController.java +++ b/src/com/pesterenan/controllers/LandingController.java @@ -1,24 +1,28 @@ package com.pesterenan.controllers; +import static com.pesterenan.MechPeste.getSpaceCenter; + +import java.util.Map; + import com.pesterenan.resources.Bundle; import com.pesterenan.utils.ControlePID; import com.pesterenan.utils.Modulos; import com.pesterenan.utils.Navigation; import com.pesterenan.utils.Utilities; + import krpc.client.RPCException; import krpc.client.StreamException; import krpc.client.services.SpaceCenter.VesselSituation; -import java.util.Map; - public class LandingController extends Controller { public static final double MAX_VELOCITY = 5; - private static final double velP = 0.025; - private static final double velI = 0.001; - private static final double velD = 0.01; - private final ControlePID altitudeCtrl = new ControlePID(); - private final ControlePID velocityCtrl = new ControlePID(); + private static final long sleepTime = 50; + private static final double velP = 0.05; + private static final double velI = 0.005; + private static final double velD = 0.001; + private ControlePID altitudeCtrl; + private ControlePID velocityCtrl; private Navigation navigation; private final int HUNDRED_PERCENT = 100; private double hoverAltitude; @@ -37,8 +41,10 @@ public LandingController(Map commands) { } private void initializeParameters() { - altitudeCtrl.adjustOutput(0, 1); - velocityCtrl.adjustOutput(0, 1); + altitudeCtrl = new ControlePID(getSpaceCenter(), sleepTime); + velocityCtrl = new ControlePID(getSpaceCenter(), sleepTime); + altitudeCtrl.setOutput(0, 1); + velocityCtrl.setOutput(0, 1); } @Override @@ -70,12 +76,11 @@ private void hoverArea() { currentMode = MODE.GOING_UP; } else { currentMode = MODE.HOVERING; - currentMode = MODE.HOVERING; } changeControlMode(); } catch (RPCException | StreamException ignored) { } - Thread.sleep(50); + Thread.sleep(sleepTime); } } catch (InterruptedException | RPCException ignored) { // disengageAfterException(Bundle.getString("status_liftoff_abort")); @@ -103,7 +108,7 @@ private void autoLanding() { } getNaveAtual().getControl().setBrakes(true); changeControlMode(); - Thread.sleep(100); + Thread.sleep(sleepTime); } } catch (RPCException | StreamException | InterruptedException e) { setCurrentStatus(Bundle.getString("status_ready")); @@ -112,7 +117,7 @@ private void autoLanding() { private void changeControlMode() throws RPCException, StreamException, InterruptedException { adjustPIDbyTWR(); - double velPID, altPID; + double velPID, altPID = 0; // Change vessel behavior depending on which mode is active switch (currentMode) { case DEORBITING: @@ -128,19 +133,22 @@ private void changeControlMode() throws RPCException, StreamException, Interrupt } break; case APPROACHING: - altitudeCtrl.adjustOutput(0, 1); - velocityCtrl.adjustOutput(0, 1); + altitudeCtrl.reset(); + velocityCtrl.reset(); + altitudeCtrl.setOutput(0, 1); + velocityCtrl.setOutput(0, 1); double currentVelocity = calculateCurrentVelocityMagnitude(); double zeroVelocity = calculateZeroVelocityMagnitude(); double landingDistanceThreshold = Math.max(hoverAltitude, getMaxAcel(maxTWR) * 3); double threshold = Utilities.clamp( ((currentVelocity + zeroVelocity) - landingDistanceThreshold) / landingDistanceThreshold, 0, 1); - altPID = altitudeCtrl.calcPID(currentVelocity / zeroVelocity * HUNDRED_PERCENT, HUNDRED_PERCENT); - velPID = velocityCtrl.calcPID(velVertical.get(), -Utilities.clamp(altitudeSup.get() * 0.1, 1, 10)); + altPID = altitudeCtrl.calculate(currentVelocity / sleepTime, zeroVelocity / sleepTime); + velPID = velocityCtrl.calculate(velVertical.get() / sleepTime, + (-Utilities.clamp(altitudeSup.get() * 0.1, 3, 20) / sleepTime)); throttle(Utilities.linearInterpolation(velPID, altPID, threshold)); navigation.aimForLanding(); - if (threshold < 0.25 || altitudeSup.get() < landingDistanceThreshold) { + if (threshold < 0.15 || altitudeSup.get() < landingDistanceThreshold) { hoverAltitude = landingDistanceThreshold; getNaveAtual().getControl().setGear(true); if (hoverAfterApproximation) { @@ -153,31 +161,39 @@ private void changeControlMode() throws RPCException, StreamException, Interrupt setCurrentStatus("Se aproximando do momento do pouso..."); break; case GOING_UP: - altitudeCtrl.adjustOutput(-0.5, 0.5); - velocityCtrl.adjustOutput(-0.5, 0.5); - altPID = altitudeCtrl.calcPID(altitudeErrorPercentage, HUNDRED_PERCENT); - velPID = velocityCtrl.calcPID(velVertical.get(), MAX_VELOCITY); + altitudeCtrl.reset(); + velocityCtrl.reset(); + altitudeCtrl.setOutput(-0.5, 0.5); + velocityCtrl.setOutput(-0.5, 0.5); + altPID = altitudeCtrl.calculate(altitudeErrorPercentage, HUNDRED_PERCENT); + velPID = velocityCtrl.calculate(velVertical.get(), MAX_VELOCITY); throttle(altPID + velPID); navigation.aimAtRadialOut(); setCurrentStatus("Subindo altitude..."); break; case GOING_DOWN: + altitudeCtrl.reset(); + velocityCtrl.reset(); controlThrottleByMatchingVerticalVelocity(-MAX_VELOCITY); navigation.aimAtRadialOut(); setCurrentStatus("Baixando altitude..."); break; case LANDING: + altitudeCtrl.reset(); + velocityCtrl.reset(); controlThrottleByMatchingVerticalVelocity( - velHorizontal.get() > 2 ? 0 : -Utilities.clamp(altitudeSup.get() * 0.1, 1, 10)); + velHorizontal.get() > 4 ? 0 : -Utilities.clamp(altitudeSup.get() * 0.1, 1, 10)); navigation.aimForLanding(); setCurrentStatus("Pousando..."); hasTheVesselLanded(); break; case HOVERING: - altitudeCtrl.adjustOutput(-0.5, 0.5); - velocityCtrl.adjustOutput(-0.5, 0.5); - altPID = altitudeCtrl.calcPID(altitudeErrorPercentage, HUNDRED_PERCENT); - velPID = velocityCtrl.calcPID(velVertical.get(), 0); + altitudeCtrl.reset(); + velocityCtrl.reset(); + altitudeCtrl.setOutput(-0.5, 0.5); + velocityCtrl.setOutput(-0.5, 0.5); + altPID = altitudeCtrl.calculate(altitudeErrorPercentage, HUNDRED_PERCENT); + velPID = velocityCtrl.calculate(velVertical.get(), 0); throttle(altPID + velPID); navigation.aimAtRadialOut(); setCurrentStatus("Sobrevoando area..."); @@ -187,8 +203,8 @@ private void changeControlMode() throws RPCException, StreamException, Interrupt private void controlThrottleByMatchingVerticalVelocity(double velocityToMatch) throws RPCException, StreamException { - velocityCtrl.adjustOutput(0, 1); - throttle(velocityCtrl.calcPID(velVertical.get(), velocityToMatch)); + velocityCtrl.setOutput(0, 1); + throttle(velocityCtrl.calculate(velVertical.get(), velocityToMatch + velHorizontal.get())); } private void deOrbitShip() throws RPCException, StreamException, InterruptedException { @@ -202,15 +218,15 @@ private void deOrbitShip() throws RPCException, StreamException, InterruptedExce navigation.aimForLanding(); setCurrentStatus(Bundle.getString("status_orienting_ship")); ap.wait_(); - Thread.sleep(100); + Thread.sleep(sleepTime); } double targetPeriapsis = currentBody.getAtmosphereDepth(); targetPeriapsis = targetPeriapsis > 0 ? targetPeriapsis / 2 : -currentBody.getEquatorialRadius() / 2; while (periastro.get() > -apoastro.get()) { navigation.aimForLanding(); - throttle(altitudeCtrl.calcPID(targetPeriapsis, periastro.get())); + throttle(altitudeCtrl.calculate(targetPeriapsis, periastro.get())); setCurrentStatus(Bundle.getString("status_lowering_periapsis")); - Thread.sleep(100); + Thread.sleep(sleepTime); } getNaveAtual().getControl().setRCS(false); throttle(0.0f); @@ -222,14 +238,11 @@ private void deOrbitShip() throws RPCException, StreamException, InterruptedExce */ private void adjustPIDbyTWR() throws RPCException, StreamException { double currentTWR = Math.min(getTWR(), maxTWR); - velocityCtrl.adjustPID(currentTWR * velP, velI, velD); - altitudeCtrl.adjustPID(currentTWR * velP, velI, velD); - } - - private double calculateCurrentVelocityMagnitude() throws RPCException, StreamException { - double timeToGround = altitudeSup.get() / velVertical.get(); - double horizontalDistance = velHorizontal.get() * timeToGround; - return calculateEllipticTrajectory(horizontalDistance, altitudeSup.get()); + // double currentTWR = getMaxAcel(maxTWR); + double pGain = currentTWR / (sleepTime); + System.out.println(pGain); + altitudeCtrl.setPIDValues(pGain * 0.1, 0.0002, pGain * 0.1 * 2); + velocityCtrl.setPIDValues(pGain * 0.1, 0.1, 0.001); } private boolean hasTheVesselLanded() throws RPCException { @@ -248,6 +261,12 @@ private boolean hasTheVesselLanded() throws RPCException { return false; } + private double calculateCurrentVelocityMagnitude() throws RPCException, StreamException { + double timeToGround = altitudeSup.get() / velVertical.get(); + double horizontalDistance = velHorizontal.get() * timeToGround; + return calculateEllipticTrajectory(horizontalDistance, altitudeSup.get()); + } + private double calculateZeroVelocityMagnitude() throws RPCException, StreamException { double zeroVelocityDistance = calculateEllipticTrajectory(velHorizontal.get(), velVertical.get()); double zeroVelocityBurnTime = zeroVelocityDistance / getMaxAcel(maxTWR); diff --git a/src/com/pesterenan/controllers/LiftoffController.java b/src/com/pesterenan/controllers/LiftoffController.java index 4f5259e..b81b0d8 100644 --- a/src/com/pesterenan/controllers/LiftoffController.java +++ b/src/com/pesterenan/controllers/LiftoffController.java @@ -1,5 +1,7 @@ package com.pesterenan.controllers; +import static com.pesterenan.MechPeste.getSpaceCenter; + import com.pesterenan.MechPeste; import com.pesterenan.resources.Bundle; import com.pesterenan.utils.ControlePID; @@ -18,7 +20,7 @@ public class LiftoffController extends Controller { private static final float PITCH_UP = 90; - private final ControlePID thrControl = new ControlePID(); + private ControlePID thrControl; private float currentPitch; private float finalApoapsisAlt; private float heading; @@ -45,7 +47,8 @@ private void initializeParameters() { setGravityCurveModel(commands.get(Modulos.INCLINACAO.get())); willOpenPanelsAndAntenna = Boolean.parseBoolean(commands.get(Modulos.ABRIR_PAINEIS.get())); willDecoupleStages = Boolean.parseBoolean(commands.get(Modulos.USAR_ESTAGIOS.get())); - thrControl.adjustOutput(0.0, 1.0); + thrControl = new ControlePID(getSpaceCenter(), 25); + thrControl.setOutput(0.0, 1.0); } @Override @@ -79,7 +82,7 @@ private void gravityCurve() throws RPCException, StreamException, InterruptedExc currentPitch = (float) (calculateCurrentPitch(altitudeProgress)); double currentMaxTWR = calculateTWRBasedOnPressure(currentPitch); ap.setTargetPitch(currentPitch); - throttle(Math.min(thrControl.calcPID(apoastro.get() / getFinalApoapsis() * 1000, 1000), + throttle(Math.min(thrControl.calculate(apoastro.get() / getFinalApoapsis() * 1000, 1000), getMaxThrottleForTWR(currentMaxTWR))); if (willDecoupleStages && isCurrentStageWithoutFuel()) { @@ -87,7 +90,7 @@ private void gravityCurve() throws RPCException, StreamException, InterruptedExc } setCurrentStatus(String.format(Bundle.getString("status_liftoff_inclination") + " %.1f", currentPitch)); - Thread.sleep(250); + Thread.sleep(25); if (Thread.interrupted()) { throw new InterruptedException(); } @@ -111,8 +114,8 @@ private void finalizeCurve() throws RPCException, StreamException, InterruptedEx throw new InterruptedException(); } navigation.aimAtPrograde(); - throttle(thrControl.calcPID(apoastro.get() / getFinalApoapsis() * 1000, 1000)); - Thread.sleep(100); + throttle(thrControl.calculate(apoastro.get() / getFinalApoapsis() * 1000, 1000)); + Thread.sleep(25); } throttle(0.0f); if (willDecoupleStages) { diff --git a/src/com/pesterenan/controllers/ManeuverController.java b/src/com/pesterenan/controllers/ManeuverController.java index 98449a5..ba85958 100644 --- a/src/com/pesterenan/controllers/ManeuverController.java +++ b/src/com/pesterenan/controllers/ManeuverController.java @@ -1,5 +1,13 @@ package com.pesterenan.controllers; +import static com.pesterenan.MechPeste.getConnection; +import static com.pesterenan.MechPeste.getSpaceCenter; + +import java.util.List; +import java.util.Map; + +import org.javatuples.Triplet; + import com.pesterenan.resources.Bundle; import com.pesterenan.utils.Attributes; import com.pesterenan.utils.ControlePID; @@ -18,19 +26,12 @@ import krpc.client.services.SpaceCenter.ReferenceFrame; import krpc.client.services.SpaceCenter.Vessel; import krpc.client.services.SpaceCenter.VesselSituation; -import org.javatuples.Triplet; - -import java.util.List; -import java.util.Map; - -import static com.pesterenan.MechPeste.getConnection; -import static com.pesterenan.MechPeste.getSpaceCenter; public class ManeuverController extends Controller { public final static float CONST_GRAV = 9.81f; - private final ControlePID ctrlRCS = new ControlePID(); - private final ControlePID ctrlManeuver = new ControlePID(); + private ControlePID ctrlRCS; + private ControlePID ctrlManeuver; private Navigation navigation; private boolean fineAdjustment; private double lowOrbitAltitude; @@ -43,7 +44,10 @@ public ManeuverController(Map commands) { } private void initializeParameters() { - ctrlRCS.adjustOutput(0.5, 1.0); + ctrlRCS = new ControlePID(getSpaceCenter(), 25); + ctrlManeuver = new ControlePID(getSpaceCenter(), 25); + ctrlManeuver.setPIDValues(1, 0.001, 0.1); + ctrlRCS.setOutput(0.5, 1.0); fineAdjustment = canFineAdjust(commands.get(Modulos.AJUSTE_FINO.get())); try { lowOrbitAltitude = new Attributes().getLowOrbitAltitude(currentBody.getName()); @@ -157,10 +161,10 @@ public void matchOrbitApoapsis() { break; } double dvPrograde = maneuver.getPrograde(); - double ctrlOutput = ctrlManeuver.calcPID(currentDeltaApo, 0); + double ctrlOutput = ctrlManeuver.calculate(currentDeltaApo, 0); maneuver.setPrograde(dvPrograde - (ctrlOutput)); - Thread.sleep(50); + Thread.sleep(25); } } catch (Exception e) { setCurrentStatus("Não foi possivel ajustar a inclinação"); @@ -205,10 +209,13 @@ private void alignPlanesWithTargetVessel() { RunManeuverJPanel.positionManeuverAt(closestIsAN ? "ascending" : "descending"); double currentInclination = Math .toDegrees(currentManeuver.getOrbit().relativeInclination(targetVesselOrbit)); + + ctrlManeuver.setTimeSample(25); while (currentInclination > 0.05) { currentInclination = Math .toDegrees(currentManeuver.getOrbit().relativeInclination(targetVesselOrbit)); - double ctrlOutput = ctrlManeuver.calcPID(currentInclination * 100, 0); + double ctrlOutput = ctrlManeuver.calculate(currentInclination * 100, 0); + currentManeuver.setNormal(currentManeuver.getNormal() + (closestIsAN ? ctrlOutput : -ctrlOutput)); Thread.sleep(25); } @@ -219,9 +226,9 @@ private void alignPlanesWithTargetVessel() { private void rendezvousWithTargetVessel() { try { - Orbit targetVesselOrbit = getSpaceCenter().getTargetVessel().getOrbit(); boolean hasManeuverNodes = getNaveAtual().getControl().getNodes().size() > 0; - java.util.List currentManeuvers = getNaveAtual().getControl().getNodes(); + List currentManeuvers = getNaveAtual().getControl().getNodes(); + Node lastManeuverNode; double lastManeuverNodeUT = 60; if (hasManeuverNodes) { @@ -234,73 +241,97 @@ private void rendezvousWithTargetVessel() { } currentManeuvers = getNaveAtual().getControl().getNodes(); lastManeuverNode = currentManeuvers.get(currentManeuvers.size() - 1); - double targetAP = targetVesselOrbit.getApoapsis(); - double targetPE = targetVesselOrbit.getPeriapsis(); - double maneuverAP = lastManeuverNode.getOrbit().getApoapsis(); - double maneuverPE = lastManeuverNode.getOrbit().getPeriapsis(); - double maneuverUT = lastManeuverNode.getUT(); - ctrlManeuver.adjustPID(0.25, 0.0, 0.01); - ctrlManeuver.adjustOutput(-100, 100); - if (targetAP < maneuverPE) { - while (Math.floor(targetAP) != Math.floor(maneuverPE)) { - lastManeuverNode.setPrograde( - lastManeuverNode.getPrograde() - + ctrlManeuver.calcPID(maneuverPE / targetAP * 1000, 1000)); - maneuverPE = lastManeuverNode.getOrbit().getPeriapsis(); - Thread.sleep(25); - } - } - if (targetPE > maneuverAP) { - while (Math.floor(targetPE) != Math.floor(maneuverAP)) { - lastManeuverNode.setPrograde( - lastManeuverNode.getPrograde() - + ctrlManeuver.calcPID(maneuverAP / targetPE * 1000, 1000)); - maneuverAP = lastManeuverNode.getOrbit().getApoapsis(); - Thread.sleep(25); + + Orbit activeVesselOrbit = getNaveAtual().getOrbit(); + Orbit targetVesselOrbit = getSpaceCenter().getTargetVessel().getOrbit(); + ReferenceFrame currentBodyRefFrame = activeVesselOrbit.getBody().getNonRotatingReferenceFrame(); + + double angularDiff = 10; + while (angularDiff >= 0.005) { + double maneuverUT = lastManeuverNode.getUT(); + double targetOrbitPosition = new Vector( + targetVesselOrbit.positionAt(maneuverUT, currentBodyRefFrame)) + .magnitude(); + double maneuverAP = lastManeuverNode.getOrbit().getApoapsis(); + double maneuverPE = lastManeuverNode.getOrbit().getPeriapsis(); + ctrlManeuver.setPIDValues(0.25, 0.0, 0.01); + ctrlManeuver.setOutput(-100, 100); + + if (targetOrbitPosition < maneuverPE) { + while (Math.floor(targetOrbitPosition) != Math.floor(maneuverPE)) { + lastManeuverNode.setPrograde( + lastManeuverNode.getPrograde() + + ctrlManeuver.calculate(maneuverPE / targetOrbitPosition * 1000, 1000)); + maneuverPE = lastManeuverNode.getOrbit().getPeriapsis(); + Thread.sleep(25); + } } - } - double mu = currentBody.getGravitationalParameter(); - double time = 1000; - - double hohmannTransferDistance = lastManeuverNode.getOrbit().getSemiMajorAxis(); - double timeOfFlight = Math.PI * Math.sqrt(Math.pow(hohmannTransferDistance, 3) / mu); - double angle = getNaveAtual().getOrbit().getMeanAnomalyAtEpoch(); - double omegaInterceptor = Math - .sqrt(mu / Math.pow(getNaveAtual().getOrbit().radiusAt(getSpaceCenter().getUT()), 3)); // rad/s - double omegaTarget = Math.sqrt(mu / Math.pow(targetVesselOrbit.radiusAt(getSpaceCenter().getUT()), 3)); // rad/s - // double leadAngle = omegaTarget * timeOfFlight; // rad - double leadAngle = targetVesselOrbit.getMeanAnomalyAtEpoch(); // rad - double phaseAngle = Math.PI - leadAngle; // rad - double calcAngle = (phaseAngle - angle); - calcAngle = calcAngle < 0 ? calcAngle + (Math.PI * 2) : calcAngle; - double waitTime = calcAngle / (omegaTarget - omegaInterceptor); - time = waitTime; - - lastManeuverNode.setUT(getSpaceCenter().getUT() + time); - ctrlManeuver.adjustOutput(-100, 100); - ctrlManeuver.adjustPID(0.05, 0.1, 0.01); - double closestApproach = lastManeuverNode.getOrbit().distanceAtClosestApproach(targetVesselOrbit); - System.out.println(closestApproach); - System.out.println("Ajustando tempo de Rendezvous..."); - while (Math.round(closestApproach) > 100) { - if (closestApproach < 100000) { - ctrlManeuver.adjustOutput(-10, 10); - } else if (closestApproach < 10000) { - ctrlManeuver.adjustOutput(-1, 1); - } else { - ctrlManeuver.adjustOutput(-100, 100); + if (targetOrbitPosition > maneuverAP) { + while (Math.floor(targetOrbitPosition) != Math.floor(maneuverAP)) { + lastManeuverNode.setPrograde( + lastManeuverNode.getPrograde() + + ctrlManeuver.calculate(maneuverAP / targetOrbitPosition * 1000, 1000)); + maneuverAP = lastManeuverNode.getOrbit().getApoapsis(); + Thread.sleep(25); + } } - maneuverUT = ctrlManeuver.calcPID(-closestApproach, 0); - lastManeuverNode.setUT(lastManeuverNode.getUT() + maneuverUT); - System.out.println("Closest " + (closestApproach)); - closestApproach = targetVesselOrbit.distanceAtClosestApproach(lastManeuverNode.getOrbit()); + angularDiff = calculatePhaseAngle(lastManeuverNode.getOrbit().positionAt(maneuverUT, currentBodyRefFrame), + getSpaceCenter().getTargetVessel().getOrbit().positionAt(maneuverUT, currentBodyRefFrame)); + maneuverUT = lastManeuverNode.getUT(); + lastManeuverNode.setUT( + lastManeuverNode.getUT() + + ctrlManeuver.calculate(-angularDiff * 100, 0)); + System.out.println(angularDiff); Thread.sleep(25); } + // double mu = currentBody.getGravitationalParameter(); + // double time = 1000; + // + // double hohmannTransferDistance = + // lastManeuverNode.getOrbit().getSemiMajorAxis(); + // double timeOfFlight = Math.PI * Math.sqrt(Math.pow(hohmannTransferDistance, + // 3) / mu); + // double angle = activeVesselOrbit.getMeanAnomalyAtEpoch(); + // double omegaInterceptor = Math + // .sqrt(mu / + // Math.pow(activeVesselOrbit.radiusAt(getSpaceCenter().getUT()), 3)); + // // rad/s + // double omegaTarget = Math.sqrt(mu / + // Math.pow(targetVesselOrbit.radiusAt(getSpaceCenter().getUT()), 3)); // rad/s + // // double leadAngle = omegaTarget * timeOfFlight; // rad + // double leadAngle = targetVesselOrbit.getMeanAnomalyAtEpoch(); // rad + // double phaseAngle = Math.PI - leadAngle; // rad + // double calcAngle = (phaseAngle - angle); + // calcAngle = calcAngle < 0 ? calcAngle + (Math.PI * 2) : calcAngle; + // double waitTime = calcAngle / (omegaTarget - omegaInterceptor); + // time = waitTime; + // + // lastManeuverNode.setUT(getSpaceCenter().getUT() + time); + // ctrlManeuver.setOutput(-100, 100); + // ctrlManeuver.setPIDValues(0.05, 0.1, 0.01); + // double closestApproach = + // lastManeuverNode.getOrbit().distanceAtClosestApproach(targetVesselOrbit); + // System.out.println(closestApproach); + // System.out.println("Ajustando tempo de Rendezvous..."); + // while (Math.round(closestApproach) > 100) { + // if (closestApproach < 100000) { + // ctrlManeuver.setOutput(-10, 10); + // } else if (closestApproach < 10000) { + // ctrlManeuver.setOutput(-1, 1); + // } else { + // ctrlManeuver.setOutput(-100, 100); + // } + // maneuverUT = ctrlManeuver.calculate(-closestApproach, 0); + // lastManeuverNode.setUT(lastManeuverNode.getUT() + maneuverUT); + // System.out.println("Closest " + (closestApproach)); + // closestApproach = + // targetVesselOrbit.distanceAtClosestApproach(lastManeuverNode.getOrbit()); + // Thread.sleep(25); + // } // lastManeuverNode.setUT(lastManeuverNode.getUT() - // lastManeuverNode.getOrbit().getPeriod() / 2); - } catch (Exception err) { - } + } catch (Exception err) {} } private double compareOrbitParameter(Orbit maneuverOrbit, Orbit targetOrbit, Compare parameter) { @@ -442,9 +473,10 @@ public void executeBurn(Node noDeManobra, double duracaoDaQueima) { } navigation.aimAtManeuver(noDeManobra); float limitValue = burnDvLeft > 100 ? 1000 : 100; - throttle(ctrlManeuver.calcPID((noDeManobra.getDeltaV() - Math.floor(burnDvLeft)) / + throttle(ctrlManeuver.calculate((noDeManobra.getDeltaV() - Math.floor(burnDvLeft)) / noDeManobra.getDeltaV() * limitValue, limitValue)); - Thread.sleep(50); + Thread.sleep(25); + } throttle(0.0f); if (fineAdjustment) { @@ -471,7 +503,7 @@ private void adjustManeuverWithRCS(Stream> remai if (Thread.interrupted()) { throw new InterruptedException(); } - getNaveAtual().getControl().setForward((float) ctrlRCS.calcPID(-remainingDeltaV.get().getValue1() * 10, + getNaveAtual().getControl().setForward((float) ctrlRCS.calculate(-remainingDeltaV.get().getValue1() * 10, 0)); Thread.sleep(25); } @@ -496,8 +528,29 @@ private boolean canFineAdjust(String string) { return false; } + private double calculatePhaseAngle(Triplet startPos, Triplet endPos) + throws RPCException, InterruptedException { + double targetPhaseAngle = 10; + double angularDifference = 15; + Vector startPosition = new Vector(startPos); + Vector endPosition = new Vector(endPos); + + // Phase angle + double dot = endPosition.dotProduct(startPosition); + double det = endPosition.determinant(startPosition); + targetPhaseAngle = Math.atan2(det, dot); + + double targetOrbit = endPosition.magnitude(); + + double activeVesselSMA = getNaveAtual().getOrbit().getSemiMajorAxis(); + angularDifference = targetPhaseAngle + Math.PI + * (1 - (1 / (2 * Math.sqrt(2))) * Math.sqrt(Math.pow((activeVesselSMA / targetOrbit + 1), 3))); + + return Math.abs(angularDifference); + } + enum Compare { INC, AP, PE } -} \ No newline at end of file +} diff --git a/src/com/pesterenan/controllers/RoverController.java b/src/com/pesterenan/controllers/RoverController.java index f094e68..aeab195 100644 --- a/src/com/pesterenan/controllers/RoverController.java +++ b/src/com/pesterenan/controllers/RoverController.java @@ -45,8 +45,8 @@ private void initializeParameters() { roverReferenceFrame = getNaveAtual().getReferenceFrame(); roverDirection = new Vector(getNaveAtual().direction(roverReferenceFrame)); pathFinding = new PathFinding(); - acelCtrl.adjustOutput(0, 1); - sterringCtrl.adjustOutput(-1, 1); + acelCtrl.setOutput(0, 1); + sterringCtrl.setOutput(-1, 1); isAutoRoverRunning = true; } catch (RPCException ignored) { } @@ -206,10 +206,10 @@ private void driveRover() throws RPCException, IOException, StreamException { double deltaAngle = Math.abs(targetAndRadarAngle - roverAngle); getNaveAtual().getControl().setSAS(deltaAngle < 1); // Control Rover Throttle - setRoverThrottle(acelCtrl.calcPID(velHorizontal.get() / maxSpeed * 50, 50)); + setRoverThrottle(acelCtrl.calculate(velHorizontal.get() / maxSpeed * 50, 50)); // Control Rover Steering if (deltaAngle > 1) { - setRoverSteering(sterringCtrl.calcPID(roverAngle / (targetAndRadarAngle) * 100, 100)); + setRoverSteering(sterringCtrl.calculate(roverAngle / (targetAndRadarAngle) * 100, 100)); } else { setRoverSteering(0.0f); } @@ -314,4 +314,4 @@ private void setRoverSteering(double steering) throws RPCException { private enum MODE { DRIVE, NEXT_POINT, CHARGING } -} \ No newline at end of file +} diff --git a/src/com/pesterenan/model/ActiveVessel.java b/src/com/pesterenan/model/ActiveVessel.java index f01f206..99efa65 100644 --- a/src/com/pesterenan/model/ActiveVessel.java +++ b/src/com/pesterenan/model/ActiveVessel.java @@ -6,6 +6,7 @@ import com.pesterenan.controllers.LiftoffController; import com.pesterenan.controllers.ManeuverController; import com.pesterenan.controllers.RoverController; +import com.pesterenan.controllers.DockingController; import com.pesterenan.resources.Bundle; import com.pesterenan.utils.Modulos; import com.pesterenan.utils.Telemetry; @@ -190,6 +191,11 @@ public void startModule(Map commands) { controller = new RoverController(commands); runningModule = true; } + if (currentFunction.equals(Modulos.MODULO_DOCKING.get())) { + controller = new DockingController(commands); + System.out.println("escolheu modulo docking"); + runningModule = true; + } controllerThread = new Thread(controller, currentVesselId + " - " + currentFunction); controllerThread.start(); } @@ -227,7 +233,7 @@ public void cancelControl() { } } - public boolean hasModuleRunning() { - return runningModule; - } + public boolean hasModuleRunning() { + return runningModule; + } } diff --git a/src/com/pesterenan/resources/MechPesteBundle.properties b/src/com/pesterenan/resources/MechPesteBundle.properties index 6035da3..03fcb5a 100644 --- a/src/com/pesterenan/resources/MechPesteBundle.properties +++ b/src/com/pesterenan/resources/MechPesteBundle.properties @@ -3,6 +3,7 @@ btn_func_liftoff = Orbital Liftoff btn_func_create_maneuver = Create Maneuvers btn_func_maneuver = Maneuvers btn_func_rover = Drive Rover +btn_func_docking = Docking btn_stat_connect = Connect installer_dialog_btn_browse = Browse... installer_dialog_btn_cancel = Cancel @@ -62,6 +63,7 @@ pnl_mnv_lbl_exec_mnv = Execute next maneuver\: pnl_rover_border = Drive Rover\: pnl_rover_btn_back = Back pnl_rover_btn_drive = Drive +pnl_rover_btn_docking = Start Docking pnl_rover_default_name = Target pnl_rover_lbl_max_speed = Max Speed\: pnl_rover_max_speed_above_3 = Max speed must be over 3m/s\u00B2 diff --git a/src/com/pesterenan/resources/MechPesteBundle_pt.properties b/src/com/pesterenan/resources/MechPesteBundle_pt.properties index fbace8b..36cb87a 100644 --- a/src/com/pesterenan/resources/MechPesteBundle_pt.properties +++ b/src/com/pesterenan/resources/MechPesteBundle_pt.properties @@ -3,6 +3,7 @@ btn_func_liftoff = Decolagem Orbital btn_func_create_maneuver = Criar Manobras btn_func_maneuver = Manobras btn_func_rover = Pilotar Rover +btn_func_docking = Acoplagem btn_stat_connect = Conectar installer_dialog_btn_browse = Escolher... installer_dialog_btn_cancel = Cancelar @@ -61,6 +62,7 @@ pnl_mnv_lbl_exec_mnv = Executar pr\u00F3xima
manobra\: pnl_rover_border = Pilotar Rover\: pnl_rover_btn_back = Voltar pnl_rover_btn_drive = Pilotar +pnl_rover_btn_docking = Iniciar Acoplagem pnl_rover_default_name = Alvo pnl_rover_lbl_max_speed = Velocidade m\u00E1xima: pnl_rover_max_speed_above_3 = A velocidade m\u00E1xima tem que ser acima de 3m/s\u00b2 diff --git a/src/com/pesterenan/utils/ControlePID.java b/src/com/pesterenan/utils/ControlePID.java index a94e5af..51ea12f 100644 --- a/src/com/pesterenan/utils/ControlePID.java +++ b/src/com/pesterenan/utils/ControlePID.java @@ -1,47 +1,82 @@ package com.pesterenan.utils; +import krpc.client.RPCException; +import krpc.client.services.SpaceCenter; + public class ControlePID { - private double limiteMin = -1; - private double limiteMax = 1; + private SpaceCenter spaceCenter = null; + private double outputMin = -1; + private double outputMax = 1; private double kp = 0.025; private double ki = 0.001; private double kd = 0.01; - private double proportionalTerm, integralTerm, derivativeTerm = 0; - private double lastValue, lastTime = 0; + private double integralTerm = 0.0; + private double previousError, previousMeasurement, lastTime = 0.0; + private double timeSample = 0.025; // 25 millisegundos + private double proportionalTerm; + private double derivativeTerm; + + public ControlePID() { + } + + public ControlePID(SpaceCenter spaceCenter, double timeSample) { + this.spaceCenter = spaceCenter; + setTimeSample(timeSample); + } + + public ControlePID(double kp, double ki, double kd, double outputMin, double outputMax) { + this.kp = kp; + this.ki = ki; + this.kd = kd; + this.outputMin = outputMin; + this.outputMax = outputMax; + } + + public void reset() { + this.previousError = 0; + this.previousMeasurement = 0; + this.proportionalTerm = 0; + this.integralTerm = 0; + this.derivativeTerm = 0; + } - public double calcPID(double currentValue, double limitValue) { - double now = System.currentTimeMillis(); - double changeInTime = now - this.lastTime; - double timeSample = 25; + public double calculate(double measurement, double setPoint) { + double now = this.getCurrentTime(); + double changeInTime = now - lastTime; if (changeInTime >= timeSample) { - double error = limitValue - currentValue; - double changeInValues = (currentValue - this.lastValue); - - this.proportionalTerm = this.kp * error; - this.integralTerm = limitOutput(this.integralTerm + ki * error); - this.derivativeTerm = kd * -changeInValues; - this.lastValue = currentValue; - this.lastTime = now; + // Error signal + double error = setPoint - measurement; + // Proportional + proportionalTerm = kp * error; + + // Integral + // integralTerm += 0.5f * ki * timeSample * (error + previousError); + // integralTerm += ki * (error + previousError); + integralTerm = ki * (integralTerm + (error * timeSample)); + integralTerm = limitOutput(integralTerm); + + derivativeTerm = kd * ((error - previousError) / timeSample); + previousError = error; + lastTime = now; } - return limitOutput(proportionalTerm + ki * this.integralTerm + derivativeTerm); + return limitOutput(proportionalTerm + integralTerm + derivativeTerm); } - private double limitOutput(double valor) { - return Utilities.clamp(valor, this.limiteMin, this.limiteMax); + private double limitOutput(double value) { + return Utilities.clamp(value, outputMin, outputMax); } - public void adjustOutput(double min, double max) { + public void setOutput(double min, double max) { if (min > max) { return; } - this.limiteMin = min; - this.limiteMax = max; - this.integralTerm = limitOutput(this.integralTerm); - + outputMin = min; + outputMax = max; + integralTerm = limitOutput(integralTerm); } - public void adjustPID(double Kp, double Ki, double Kd) { + public void setPIDValues(double Kp, double Ki, double Kd) { if (Kp > 0) { this.kp = Kp; } @@ -53,4 +88,17 @@ public void adjustPID(double Kp, double Ki, double Kd) { } } -} \ No newline at end of file + public void setTimeSample(double milliseconds) { + timeSample = milliseconds > 0 ? milliseconds / 1000 : timeSample; + } + + private double getCurrentTime() { + try { + return spaceCenter.getUT(); + } catch (RPCException | NullPointerException ignored) { + System.err.println("Não foi possível buscar o tempo do jogo, retornando do sistema"); + return System.currentTimeMillis(); + } + } + +} diff --git a/src/com/pesterenan/utils/Modulos.java b/src/com/pesterenan/utils/Modulos.java index 5bdf85c..f31f409 100644 --- a/src/com/pesterenan/utils/Modulos.java +++ b/src/com/pesterenan/utils/Modulos.java @@ -22,18 +22,19 @@ public enum Modulos { MODULO_POUSO_SOBREVOAR("HOVER"), MODULO_POUSO("LANDING"), MODULO_ROVER("ROVER"), + MODULO_DOCKING("DOCKING"), MODULO_TELEMETRIA("TELEMETRY"), MODULO("Módulo"), NAVE_ALVO("Nave alvo"), NOME_MARCADOR("Nome do marcador"), ORBITA_BAIXA("ÓRBITA BAIXA"), PERIASTRO("Periastro"), - POUSAR("Pousar nave"), + POUSAR("Pousar nave"), QUADRATICA("Quadrática"), RENDEZVOUS("Rendezvous"), ROLAGEM("Rolagem"), SINUSOIDAL("Sinusoidal"), - SOBREVOO_POS_POUSO("SOBREVOO PÓS POUSO"), + SOBREVOO_POS_POUSO("SOBREVOO PÓS POUSO"), TIPO_ALVO_ROVER("Tipo de Alvo do Rover"), USAR_ESTAGIOS("Usar Estágios"), VELOCIDADE_MAX("Velocidade Máxima"); diff --git a/src/com/pesterenan/utils/Vector.java b/src/com/pesterenan/utils/Vector.java index c47661d..06c69e4 100644 --- a/src/com/pesterenan/utils/Vector.java +++ b/src/com/pesterenan/utils/Vector.java @@ -66,7 +66,7 @@ public static double distance(Vector start, Vector end) { * @param start - Vetor contendo os componentes da posição do ponto de origem. * @param end - Vetor contendo os componentes da posição do alvo. * @return - Vetor com a soma dos valores do ponto de origem com os valores do - * alvo. + * alvo. */ public static Vector targetDirection(Vector start, Vector end) { return end.subtract(start).normalize(); @@ -78,7 +78,7 @@ public static Vector targetDirection(Vector start, Vector end) { * @param start - Tupla contendo os componentes da posição do ponto de origem. * @param end - Tupla contendo os componentes da posição do alvo. * @return - Vetor inverso, com a soma dos valores do ponto de origem com o - * negativo dos valores do alvo. + * negativo dos valores do alvo. */ public static Vector targetOppositeDirection(Vector start, Vector end) { return end.subtract(start).multiply(-1).normalize(); @@ -151,12 +151,13 @@ public Vector normalize() { * @param otherVector - Vetor para somar os componentes * @return Novo vetor com a soma dos componentes dos dois */ - public double dotP(Vector otherVector) { + + public double dotProduct(Vector otherVector) { return (x * otherVector.x + y * otherVector.y + z * otherVector.z); } public double determinant(Vector otherVector) { - return (x * otherVector.y - y * otherVector.x - z * otherVector.z); + return (x * otherVector.z - y * otherVector.y - z * otherVector.x); } /** @@ -184,8 +185,8 @@ public Vector subtract(Vector otherVector) { * * @param scalar - Fator para multiplicar os componentes * @return Novo vetor com os componentes multiplicados pela escalar. Caso a - * escalar informada for 0, o Vetor retornado terá 0 como seus - * componentes. + * escalar informada for 0, o Vetor retornado terá 0 como seus + * componentes. */ public Vector multiply(double scalar) { if (scalar != 0) { @@ -199,7 +200,7 @@ public Vector multiply(double scalar) { * * @param scalar - Fator para dividir os componentes * @return Novo vetor com os componentes divididos pela escalar. Caso a escalar - * informada for 0, o Vetor retornado terá 0 como seus componentes. + * informada for 0, o Vetor retornado terá 0 como seus componentes. */ public Vector divide(double scalar) { if (scalar != 0) { diff --git a/src/com/pesterenan/views/CreateManeuverJPanel.java b/src/com/pesterenan/views/CreateManeuverJPanel.java index db253de..8bdf2ed 100644 --- a/src/com/pesterenan/views/CreateManeuverJPanel.java +++ b/src/com/pesterenan/views/CreateManeuverJPanel.java @@ -80,7 +80,8 @@ public void initComponents() { sliderValues.put(4, 100f); sliderValues.put(5, 1000f); - ctrlManeuver.adjustOutput(-100, 100); + ctrlManeuver.setOutput(-100, 100); + } @Override diff --git a/src/com/pesterenan/views/DockingJPanel.java b/src/com/pesterenan/views/DockingJPanel.java new file mode 100644 index 0000000..8c5e975 --- /dev/null +++ b/src/com/pesterenan/views/DockingJPanel.java @@ -0,0 +1,123 @@ +package com.pesterenan.views; + +import com.pesterenan.MechPeste; +import com.pesterenan.resources.Bundle; +import com.pesterenan.utils.Modulos; + +import javax.swing.*; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.util.HashMap; +import java.util.Map; + +import static com.pesterenan.views.MainGui.BTN_DIMENSION; +import static com.pesterenan.views.MainGui.MARGIN_BORDER_10_PX_LR; +import static com.pesterenan.views.MainGui.PNL_DIMENSION; + +public class DockingJPanel extends JPanel implements UIMethods { + + private static final long serialVersionUID = 0L; + + private JLabel lblMaxSpeed; + private JTextField txfMaxSpeed; + private JButton btnBack, btnStartDocking; + + public DockingJPanel() { + initComponents(); + setupComponents(); + layoutComponents(); + } + + @Override + public void initComponents() { + // Labels: + lblMaxSpeed = new JLabel(Bundle.getString("pnl_rover_lbl_max_speed")); + + // Textfields: + txfMaxSpeed = new JTextField("3"); + + // Buttons: + btnBack = new JButton(Bundle.getString("pnl_rover_btn_back")); + btnStartDocking = new JButton(Bundle.getString("pnl_rover_btn_docking")); + } + + @Override + public void setupComponents() { + // Main Panel setup: + setBorder(new TitledBorder(null, Bundle.getString("btn_func_docking"))); + + // Setting-up components: + txfMaxSpeed.setHorizontalAlignment(SwingConstants.RIGHT); + txfMaxSpeed.setMaximumSize(BTN_DIMENSION); + txfMaxSpeed.setPreferredSize(BTN_DIMENSION); + + btnBack.addActionListener(MainGui::backToTelemetry); + btnBack.setMaximumSize(BTN_DIMENSION); + btnBack.setPreferredSize(BTN_DIMENSION); + btnStartDocking.addActionListener(this::handleStartDocking); + btnStartDocking.setMaximumSize(BTN_DIMENSION); + btnStartDocking.setPreferredSize(BTN_DIMENSION); + } + + @Override + public void layoutComponents() { + // Main Panel layout: + setPreferredSize(PNL_DIMENSION); + setSize(PNL_DIMENSION); + setLayout(new BorderLayout()); + + // Layout components: + JPanel pnlMaxSpeed = new JPanel(); + pnlMaxSpeed.setLayout(new BoxLayout(pnlMaxSpeed, BoxLayout.X_AXIS)); + pnlMaxSpeed.add(lblMaxSpeed); + pnlMaxSpeed.add(Box.createHorizontalGlue()); + pnlMaxSpeed.add(txfMaxSpeed); + + JPanel pnlRoverControls = new JPanel(); + pnlRoverControls.setLayout(new BoxLayout(pnlRoverControls, BoxLayout.Y_AXIS)); + pnlRoverControls.setBorder(MARGIN_BORDER_10_PX_LR); + pnlRoverControls.add(MainGui.createMarginComponent(0, 6)); + pnlRoverControls.add(pnlMaxSpeed); + pnlRoverControls.add(Box.createVerticalGlue()); + + JPanel pnlButtons = new JPanel(); + pnlButtons.setLayout(new BoxLayout(pnlButtons, BoxLayout.X_AXIS)); + pnlButtons.add(btnStartDocking); + pnlButtons.add(Box.createHorizontalGlue()); + pnlButtons.add(btnBack); + + JPanel pnlMain = new JPanel(); + pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS)); + pnlRoverControls.setAlignmentY(TOP_ALIGNMENT); + pnlMain.add(pnlRoverControls); + + setLayout(new BorderLayout()); + add(pnlMain, BorderLayout.CENTER); + add(pnlButtons, BorderLayout.SOUTH); + } + + private void handleStartDocking(ActionEvent e) { + System.out.println("chamou startdocking"); + Map commands = new HashMap<>(); + commands.put(Modulos.MODULO.get(), Modulos.MODULO_DOCKING.get()); + commands.put(Modulos.VELOCIDADE_MAX.get(), txfMaxSpeed.getText()); + MechPeste.newInstance().startModule(commands); + } + + private boolean validateTextFields() { + try { + if (Float.parseFloat(txfMaxSpeed.getText()) > 10) { + throw new NumberFormatException(); + } + } catch (NumberFormatException e) { + StatusJPanel.setStatusMessage(Bundle.getString("pnl_rover_max_speed_above_3")); + return false; + } catch (IllegalArgumentException e) { + StatusJPanel.setStatusMessage(Bundle.getString("pnl_rover_waypoint_name_not_empty")); + return false; + } + return true; + } +} diff --git a/src/com/pesterenan/views/FunctionsAndTelemetryJPanel.java b/src/com/pesterenan/views/FunctionsAndTelemetryJPanel.java index 3f0d9ac..0c803a7 100644 --- a/src/com/pesterenan/views/FunctionsAndTelemetryJPanel.java +++ b/src/com/pesterenan/views/FunctionsAndTelemetryJPanel.java @@ -21,7 +21,8 @@ public class FunctionsAndTelemetryJPanel extends JPanel implements UIMethods { private static final long serialVersionUID = 0L; private final Dimension btnFuncDimension = new Dimension(140, 25); - private JButton btnLiftoff, btnLanding, btnManeuvers, btnRover, btnCancel; + private JButton btnLiftoff, btnLanding, btnManeuvers, btnDocking, btnRover, btnCancel; + private static JLabel lblAltitude, lblSurfaceAlt, lblApoapsis, lblPeriapsis, lblVertSpeed, lblHorzSpeed; private static JLabel lblAltitudeValue, lblSurfaceAltValue, lblApoapsisValue; private static JLabel lblPeriapsisValue, lblVertSpeedValue, lblHorzSpeedValue; @@ -53,6 +54,7 @@ public void initComponents() { btnLanding = new JButton(Bundle.getString("btn_func_landing")); btnManeuvers = new JButton(Bundle.getString("btn_func_maneuver")); btnRover = new JButton(Bundle.getString("btn_func_rover")); + btnDocking = new JButton(Bundle.getString("btn_func_docking")); btnCancel = new JButton(Bundle.getString("pnl_tel_btn_cancel")); } @@ -83,6 +85,10 @@ public void setupComponents() { btnRover.setActionCommand(Modulos.MODULO_ROVER.get()); btnRover.setMaximumSize(btnFuncDimension); btnRover.setPreferredSize(btnFuncDimension); + btnDocking.addActionListener(this::changeFunctionPanel); + btnDocking.setActionCommand(Modulos.MODULO_DOCKING.get()); + btnDocking.setMaximumSize(btnFuncDimension); + btnDocking.setPreferredSize(btnFuncDimension); } @Override @@ -94,6 +100,8 @@ public void layoutComponents() { pnlFunctionControls.add(btnLiftoff); pnlFunctionControls.add(btnLanding); pnlFunctionControls.add(btnRover); + pnlFunctionControls.add(btnDocking); + pnlFunctionControls.add(btnManeuvers); pnlFunctionControls.add(Box.createVerticalGlue()); diff --git a/src/com/pesterenan/views/MainGui.java b/src/com/pesterenan/views/MainGui.java index 2eab916..f824d7f 100644 --- a/src/com/pesterenan/views/MainGui.java +++ b/src/com/pesterenan/views/MainGui.java @@ -33,6 +33,7 @@ public class MainGui extends JFrame implements ActionListener, UIMethods { private CreateManeuverJPanel pnlCreateManeuvers; private RunManeuverJPanel pnlRunManeuvers; private RoverJPanel pnlRover; + private DockingJPanel pnlDocking; private MainGui() { initComponents(); @@ -75,6 +76,7 @@ public void initComponents() { pnlCreateManeuvers = new CreateManeuverJPanel(); pnlRunManeuvers = new RunManeuverJPanel(); pnlRover = new RoverJPanel(); + pnlDocking = new DockingJPanel(); pnlStatus = new StatusJPanel(); } @@ -130,6 +132,7 @@ public void layoutComponents() { cardJPanels.add(pnlLanding, Modulos.MODULO_POUSO.get()); cardJPanels.add(pnlManeuverJTabbedPane, Modulos.MODULE_MANEUVER.get()); cardJPanels.add(pnlRover, Modulos.MODULO_ROVER.get()); + cardJPanels.add(pnlDocking, Modulos.MODULO_DOCKING.get()); } public void actionPerformed(ActionEvent e) {