diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml
index dd190d0..ec68e80 100644
--- a/.github/workflows/ci-workflow.yml
+++ b/.github/workflows/ci-workflow.yml
@@ -14,7 +14,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Cache the Maven packages to speed up build
- uses: actions/cache@v1
+ uses: actions/cache@v4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
diff --git a/.github/workflows/release-new-version.yml b/.github/workflows/release-new-version.yml
index 863416d..8a1f4ef 100644
--- a/.github/workflows/release-new-version.yml
+++ b/.github/workflows/release-new-version.yml
@@ -12,7 +12,7 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Cache the Maven packages to speed up build
- uses: actions/cache@v1
+ uses: actions/cache@v4
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
diff --git a/.gitignore b/.gitignore
index 7b89667..9b1d9de 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@ local.properties
workspace.xml
settings.json
target/
+GEMINI.MD
diff --git a/.settings/eclipse-java-google-style.xml b/.settings/eclipse-java-google-style.xml
new file mode 100644
index 0000000..7bb6804
--- /dev/null
+++ b/.settings/eclipse-java-google-style.xml
@@ -0,0 +1,337 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.settings/org.eclipse.jdt.apt.core.prefs b/.settings/org.eclipse.jdt.apt.core.prefs
new file mode 100644
index 0000000..d4313d4
--- /dev/null
+++ b/.settings/org.eclipse.jdt.apt.core.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=false
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 0f0bc12..1b6e1ef 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,22 +1,9 @@
-# Java Version
+eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.processAnnotations=disabled
+org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
-
-# Indentation
-org.eclipse.jdt.core.formatter.tabulation.char=space
-org.eclipse.jdt.core.formatter.tabulation.size=4
-org.eclipse.jdt.core.formatter.indentation.size=4
-
-# Braces
-org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
-org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
-
-# Line Wrapping
-org.eclipse.jdt.core.formatter.lineSplit=120
-org.eclipse.jdt.core.formatter.join_wrapped_lines=false
-
-# Other
-org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
-org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=true
diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs
new file mode 100644
index 0000000..f897a7f
--- /dev/null
+++ b/.settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1
diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml
deleted file mode 100644
index f4ef8aa..0000000
--- a/.settings/org.eclipse.wst.common.project.facet.core.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/pom.xml b/pom.xml
index 3936d8f..cc95adc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
com.pesterenan
MechPeste
- 0.8.0
+ 0.9.0
@@ -61,10 +61,9 @@
2.37.0
-
- 4.19
- ${project.basedir}/.settings/org.eclipse.jdt.core.prefs
-
+
+ 1.22.0
+
@@ -95,7 +94,7 @@
com.google.protobuf
protobuf-java
- 3.22.1
+ 4.32.0
diff --git a/src/main/java/com/pesterenan/Main.java b/src/main/java/com/pesterenan/Main.java
deleted file mode 100644
index ac0b287..0000000
--- a/src/main/java/com/pesterenan/Main.java
+++ /dev/null
@@ -1,223 +0,0 @@
-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/main/java/com/pesterenan/MechPeste.java b/src/main/java/com/pesterenan/MechPeste.java
index da9689e..89f1685 100644
--- a/src/main/java/com/pesterenan/MechPeste.java
+++ b/src/main/java/com/pesterenan/MechPeste.java
@@ -1,212 +1,47 @@
package com.pesterenan;
-import static com.pesterenan.views.StatusJPanel.isBtnConnectVisible;
-import static com.pesterenan.views.StatusJPanel.setStatusMessage;
-
-import java.awt.event.ActionEvent;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import javax.swing.DefaultListModel;
-import javax.swing.ListModel;
-
-import com.pesterenan.model.ActiveVessel;
-import com.pesterenan.resources.Bundle;
-import com.pesterenan.utils.Vector;
-import com.pesterenan.views.CreateManeuverJPanel;
+import com.pesterenan.model.ConnectionManager;
+import com.pesterenan.model.VesselManager;
import com.pesterenan.views.FunctionsAndTelemetryJPanel;
import com.pesterenan.views.MainGui;
-
-import krpc.client.Connection;
-import krpc.client.RPCException;
-import krpc.client.services.KRPC;
-import krpc.client.services.SpaceCenter;
-import krpc.client.services.SpaceCenter.Node;
-import krpc.client.services.SpaceCenter.Vessel;
+import com.pesterenan.views.StatusDisplay;
+import java.lang.reflect.InvocationTargetException;
+import javax.swing.SwingUtilities;
public class MechPeste {
- private static KRPC krpc;
- private static MechPeste mechPeste;
- private static SpaceCenter spaceCenter;
- private static Connection connection;
- private static int currentVesselId = -1;
- private static ActiveVessel currentVessel = null;
-
- public static void main(String[] args) {
- MechPeste.newInstance().connectToKSP();
- MechPeste.newInstance().checkActiveVessel();
- }
-
- public static MechPeste newInstance() {
- if (mechPeste == null) {
- mechPeste = new MechPeste();
- }
- return mechPeste;
- }
-
- public static Connection getConnection() {
- return connection;
- }
-
- public static SpaceCenter getSpaceCenter() {
- return spaceCenter;
- }
-
- public static ListModel getActiveVessels(String search) {
- DefaultListModel list = new DefaultListModel<>();
- try {
- List vessels = spaceCenter.getVessels();
- vessels = vessels.stream().filter(v -> filterVessels(v, search)).collect(Collectors.toList());
- vessels.forEach(v -> {
- try {
- String vesselName = v.hashCode() + " - \t" + v.getName();
- list.addElement(vesselName);
- } catch (RPCException ignored) {
- }
- });
- } catch (RPCException | NullPointerException ignored) {
- }
- return list;
- }
+ private ConnectionManager connectionManager = null;
+ private VesselManager vesselManager;
+ private static MechPeste instance;
- public static ListModel getCurrentManeuvers() {
- DefaultListModel list = new DefaultListModel<>();
- try {
- List maneuvers = getSpaceCenter().getActiveVessel().getControl().getNodes();
- maneuvers.forEach(m -> {
- try {
- String maneuverStr = String.format("%d - Dv: %.1f {P: %.1f, N: %.1f, R: %.1f} AP: %.1f, PE: %.1f",
- maneuvers.indexOf(m) + 1, m.getDeltaV(), m.getPrograde(), m.getNormal(), m.getRadial(),
- m.getOrbit().getApoapsisAltitude(), m.getOrbit().getPeriapsisAltitude());
- list.addElement(maneuverStr);
- } catch (RPCException ignored) {
- }
- });
- } catch (RPCException | NullPointerException ignored) {
- }
- return list;
- }
-
- public static String getVesselInfo(int selectedIndex) {
- try {
- Vessel activeVessel = spaceCenter.getVessels().stream().filter(v -> v.hashCode() == selectedIndex)
- .findFirst().get();
- String name = activeVessel.getName().length() > 40
- ? activeVessel.getName().substring(0, 40) + "..."
- : activeVessel.getName();
- String vesselInfo = String.format("Nome: %s\t\t\t | Corpo: %s", name,
- activeVessel.getOrbit().getBody().getName());
- return vesselInfo;
- } catch (RPCException | NullPointerException ignored) {
- }
- return "";
- }
-
- public static void changeToVessel(int selectedIndex) {
- try {
- Vessel activeVessel = spaceCenter.getVessels().stream().filter(v -> v.hashCode() == selectedIndex)
- .findFirst().get();
- spaceCenter.setActiveVessel(activeVessel);
- } catch (RPCException | NullPointerException e) {
- System.out.println(Bundle.getString("status_couldnt_switch_vessel"));
- }
- }
-
- public static void cancelControl(ActionEvent e) {
- currentVessel.cancelControl();
- }
+ public ConnectionManager getConnectionManager() {
+ return connectionManager;
+ }
- 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;
- }
-
- private MechPeste() {
- MainGui.newInstance();
- }
+ public VesselManager getVesselManager() {
+ return vesselManager;
+ }
- public KRPC.GameScene getCurrentGameScene() throws RPCException {
- return krpc.getCurrentGameScene();
- }
+ private MechPeste() {}
- public void startModule(Map commands) {
- currentVessel.startModule(commands);
+ public static MechPeste newInstance() {
+ if (instance == null) {
+ instance = new MechPeste();
}
+ return instance;
+ }
- public void connectToKSP() {
- setStatusMessage(Bundle.getString("status_connecting"));
- try {
- connection = Connection.newInstance("MechPeste - Pesterenan");
- krpc = KRPC.newInstance(connection);
- spaceCenter = SpaceCenter.newInstance(getConnection());
- setStatusMessage(Bundle.getString("status_connected"));
- isBtnConnectVisible(false);
- } catch (IOException e) {
- setStatusMessage(Bundle.getString("status_error_connection"));
- isBtnConnectVisible(true);
- }
+ public static void main(String[] args) {
+ MechPeste app = MechPeste.newInstance();
+ try {
+ SwingUtilities.invokeAndWait(() -> MainGui.newInstance());
+ } catch (InvocationTargetException | InterruptedException e) {
+ System.err.println("Error while invoking GUI: " + e.getMessage());
}
- public void checkConnection() {
- try {
- if (!MechPeste.newInstance().getCurrentGameScene().equals(KRPC.GameScene.FLIGHT)) {
- setStatusMessage(Bundle.getString("status_ready"));
- return;
- }
- getConnection().close();
- } catch (RPCException | NullPointerException | IOException e) {
- setStatusMessage(Bundle.getString("status_error_connection"));
- isBtnConnectVisible(true);
- }
- }
-
- 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) {
- }
- }
- }
+ StatusDisplay statusDisplay = MainGui.newInstance().getStatusPanel();
+ FunctionsAndTelemetryJPanel telemetryPanel = MainGui.newInstance().getTelemetryPanel();
+ app.connectionManager = new ConnectionManager("MechPeste - Pesterenan", statusDisplay);
+ app.vesselManager = new VesselManager(app.connectionManager, statusDisplay, telemetryPanel);
+ app.vesselManager.startTelemetryLoop();
+ }
}
diff --git a/src/main/java/com/pesterenan/controllers/Controller.java b/src/main/java/com/pesterenan/controllers/Controller.java
index c0901f7..910f770 100644
--- a/src/main/java/com/pesterenan/controllers/Controller.java
+++ b/src/main/java/com/pesterenan/controllers/Controller.java
@@ -2,22 +2,32 @@
import com.pesterenan.model.ActiveVessel;
-public class Controller extends ActiveVessel implements Runnable {
-
- public Controller() {
- super();
- }
-
- public void run() {
- try {
- while (!Thread.interrupted()) {
- long currentTime = System.currentTimeMillis();
- if (currentTime > timer + 100) {
- recordTelemetryData();
- timer = currentTime;
- }
- }
- } catch (Exception ignored) {
- }
- }
+public class Controller implements Runnable {
+ protected final ActiveVessel vessel;
+ private volatile boolean isRunning = true;
+ private String currentStatus = "";
+
+ public Controller(ActiveVessel vessel) {
+ this.vessel = vessel;
+ }
+
+ public void run() {
+ // This method should be overridden by subclasses.
+ }
+
+ public void stop() {
+ this.isRunning = false;
+ }
+
+ public boolean isRunning() {
+ return this.isRunning;
+ }
+
+ public String getCurrentStatus() {
+ return currentStatus;
+ }
+
+ public void setCurrentStatus(String status) {
+ this.currentStatus = status;
+ }
}
diff --git a/src/main/java/com/pesterenan/controllers/DockingController.java b/src/main/java/com/pesterenan/controllers/DockingController.java
index 978fb31..e6f1704 100644
--- a/src/main/java/com/pesterenan/controllers/DockingController.java
+++ b/src/main/java/com/pesterenan/controllers/DockingController.java
@@ -1,300 +1,396 @@
package com.pesterenan.controllers;
-import static com.pesterenan.MechPeste.getConnection;
-import static com.pesterenan.MechPeste.getSpaceCenter;
-
-import java.util.Map;
-
+import com.pesterenan.model.ActiveVessel;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.Module;
import com.pesterenan.utils.Utilities;
import com.pesterenan.utils.Vector;
import com.pesterenan.views.DockingJPanel;
-import com.pesterenan.views.StatusJPanel;
-
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import krpc.client.RPCException;
+import krpc.client.Stream;
+import krpc.client.StreamException;
import krpc.client.services.Drawing;
import krpc.client.services.Drawing.Line;
+import krpc.client.services.KRPC;
import krpc.client.services.SpaceCenter.Control;
import krpc.client.services.SpaceCenter.DockingPort;
+import krpc.client.services.SpaceCenter.DockingPortState;
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 Line distanceLine;
- private Line distLineXAxis;
- private Line distLineYAxis;
- private Line distLineZAxis;
- private DockingPort myDockingPort;
- private DockingPort targetDockingPort;
- private Vector positionMyDockingPort;
- private Vector positionTargetDockingPort;
-
- private double DOCKING_MAX_SPEED = 3.0;
- private double SAFE_DISTANCE = 25.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 {
- DOCKING_MAX_SPEED = Double.parseDouble(commands.get(Module.MAX_SPEED.get()));
- SAFE_DISTANCE = Double.parseDouble(commands.get(Module.SAFE_DISTANCE.get()));
- drawing = Drawing.newInstance(getConnection());
- targetVessel = getSpaceCenter().getTargetVessel();
- control = getActiveVessel().getControl();
- vesselRefFrame = getActiveVessel().getReferenceFrame();
- orbitalRefVessel = getActiveVessel().getOrbitalReferenceFrame();
-
- myDockingPort = getActiveVessel().getParts().getDockingPorts().get(0);
- targetDockingPort = targetVessel.getParts().getDockingPorts().get(0);
- dockingStep = DOCKING_STEPS.STOP_RELATIVE_SPEED;
-
- positionMyDockingPort = new Vector(myDockingPort.position(orbitalRefVessel));
- positionTargetDockingPort = new Vector(targetDockingPort.position(orbitalRefVessel));
- } catch (RPCException ignored) {
- }
- }
-
- @Override
- public void run() {
- if (commands.get(Module.MODULO.get()).equals(Module.DOCKING.get())) {
- startDocking();
- }
+ private enum DockingPhase {
+ SETUP,
+ ORIENT_TO_TARGET,
+ APPROACH_TARGET,
+ ORIENT_TO_PORT,
+ FINAL_APPROACH,
+ FINISHED
+ }
+
+ private enum DOCKING_STEPS {
+ APPROACH,
+ STOP_RELATIVE_SPEED,
+ LINE_UP_WITH_TARGET,
+ GO_IN_FRONT_OF_TARGET
+ }
+
+ private Drawing drawing;
+ private Vessel targetVessel;
+
+ private Control control;
+ private KRPC krpc;
+ private ReferenceFrame orbitalRefVessel;
+ private ReferenceFrame vesselRefFrame;
+ 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 double DOCKING_MAX_SPEED = 3.0;
+ private double SAFE_DISTANCE = 25.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;
+ private boolean isOriented = false;
+ private final Map commands;
+
+ private Stream errorStream;
+
+ private int errorCallbackTag;
+
+ private DockingPhase currentPhase;
+ private ScheduledExecutorService dockingExecutor;
+
+ public DockingController(ActiveVessel vessel, Map commands) {
+ super(vessel);
+ this.commands = commands;
+ initializeParameters();
+ }
+
+ @Override
+ public void run() {
+ if (commands.get(Module.MODULO.get()).equals(Module.DOCKING.get())) {
+ try {
+ startDocking();
+ } catch (RPCException | StreamException e) {
+ cleanup();
+ setCurrentStatus("Docking failed: " + e.getMessage());
+ }
}
-
- private void pointToTarget(Vector targetDirection) throws RPCException, InterruptedException {
- getActiveVessel().getAutoPilot().setReferenceFrame(orbitalRefVessel);
- getActiveVessel().getAutoPilot().setTargetDirection(targetDirection.toTriplet());
- getActiveVessel().getAutoPilot().setTargetRoll(90);
- getActiveVessel().getAutoPilot().engage();
- // Fazer a nave apontar usando o piloto automático, na marra
- while (Math.abs(getActiveVessel().getAutoPilot().getError()) > 3) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- Thread.sleep(100);
- System.out.println(getActiveVessel().getAutoPilot().getError());
- }
- getActiveVessel().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) >= SAFE_DISTANCE) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- targetPosition = new Vector(targetVessel.position(vesselRefFrame));
- controlShipRCS(targetPosition, SAFE_DISTANCE);
- Thread.sleep(sleepTime);
- }
-
+ }
+
+ public void startDocking() throws RPCException, StreamException {
+ krpc = KRPC.newInstance(vessel.getConnectionManager().getConnection());
+ currentPhase = DockingPhase.SETUP;
+ dockingExecutor = Executors.newSingleThreadScheduledExecutor();
+ dockingExecutor.scheduleAtFixedRate(this::updateDockingState, 0, 100, TimeUnit.MILLISECONDS);
+ }
+
+ private void initializeParameters() {
+ try {
+ DOCKING_MAX_SPEED = Double.parseDouble(commands.get(Module.MAX_SPEED.get()));
+ SAFE_DISTANCE = Double.parseDouble(commands.get(Module.SAFE_DISTANCE.get()));
+ drawing = Drawing.newInstance(vessel.getConnectionManager().getConnection());
+ targetVessel = vessel.getConnectionManager().getSpaceCenter().getTargetVessel();
+ control = vessel.getActiveVessel().getControl();
+ vesselRefFrame = vessel.getActiveVessel().getReferenceFrame();
+ orbitalRefVessel = vessel.getActiveVessel().getOrbitalReferenceFrame();
+
+ myDockingPort = vessel.getActiveVessel().getParts().getDockingPorts().get(0);
+ targetDockingPort = targetVessel.getParts().getDockingPorts().get(0);
+ dockingStep = DOCKING_STEPS.STOP_RELATIVE_SPEED;
+
+ positionMyDockingPort = new Vector(myDockingPort.position(orbitalRefVessel));
+ positionTargetDockingPort = new Vector(targetDockingPort.position(orbitalRefVessel));
+ } catch (RPCException ignored) {
}
-
- 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() > SAFE_DISTANCE) {
- // Apontar para o alvo:
- Vector targetDirection = new Vector(getActiveVessel().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);
+ }
+
+ private void updateDockingState() {
+ try {
+ if (!isRunning()) {
+ cleanup();
+ return;
+ }
+ Vector targetPosition;
+ switch (currentPhase) {
+ case SETUP:
+ setCurrentStatus("Setting up for docking...");
+ control.setSAS(true);
+ control.setRCS(false);
+ control.setSASMode(SASMode.STABILITY_ASSIST);
+ createLines(positionMyDockingPort, positionTargetDockingPort);
+ currentPhase = DockingPhase.ORIENT_TO_TARGET;
+ break;
+ case ORIENT_TO_TARGET:
+ setCurrentStatus("Orienting to target vessel...");
+ targetPosition = new Vector(targetVessel.position(vesselRefFrame));
+ if (targetPosition.magnitude() > SAFE_DISTANCE) {
+ Vector targetDirection =
+ new Vector(vessel.getActiveVessel().position(orbitalRefVessel))
+ .subtract(new Vector(targetVessel.position(orbitalRefVessel)))
+ .multiply(-1);
+ pointToTarget(targetDirection);
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 interrupted.");
- }
+ currentPhase = DockingPhase.APPROACH_TARGET;
+ } else {
+ currentPhase = DockingPhase.ORIENT_TO_PORT;
+ }
+ break;
+ case APPROACH_TARGET:
+ setCurrentStatus("Approaching target vessel...");
+ targetPosition = new Vector(targetVessel.position(vesselRefFrame));
+ if (targetPosition.magnitude() > SAFE_DISTANCE) {
+ controlShipRCS(targetPosition, SAFE_DISTANCE);
+ } else {
+ currentPhase = DockingPhase.ORIENT_TO_PORT;
+ }
+ break;
+ case ORIENT_TO_PORT:
+ setCurrentStatus("Orienting to docking port...");
+ control.setSAS(false);
+ control.setRCS(false);
+ Vector targetDockingPortDirection =
+ new Vector(targetDockingPort.direction(orbitalRefVessel)).multiply(-1);
+ pointToTarget(targetDockingPortDirection);
+ control.setRCS(true);
+ if (isOriented) {
+ currentPhase = DockingPhase.FINAL_APPROACH;
+ }
+ break;
+ case FINAL_APPROACH:
+ setCurrentStatus("Final approach...");
+ targetPosition =
+ new Vector(targetDockingPort.position(vesselRefFrame))
+ .subtract(new Vector(myDockingPort.position(vesselRefFrame)));
+ double safeDistance = targetPosition.magnitude() < 10 ? 1 : 10;
+ controlShipRCS(targetPosition, safeDistance);
+ if (myDockingPort.getState() == DockingPortState.DOCKED) {
+ setCurrentStatus("Docking successful!");
+ currentPhase = DockingPhase.FINISHED;
+ }
+ break;
+ case FINISHED:
+ stop();
+ break;
+ }
+ } catch (RPCException | StreamException | InterruptedException e) {
+ setCurrentStatus("Docking failed: " + e.getMessage());
+ cleanup();
}
-
- /*
- * 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, STOP_RELATIVE_SPEED, LINE_UP_WITH_TARGET, GO_IN_FRONT_OF_TARGET
+ }
+
+ /*
+ * 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 void pointToTarget(Vector targetDirection)
+ throws RPCException, InterruptedException, StreamException {
+ vessel.getActiveVessel().getAutoPilot().setReferenceFrame(orbitalRefVessel);
+ vessel.getActiveVessel().getAutoPilot().setTargetDirection(targetDirection.toTriplet());
+ vessel.getActiveVessel().getAutoPilot().setTargetRoll(90);
+ vessel.getActiveVessel().getAutoPilot().engage();
+ errorStream = vessel.connection.addStream(vessel.ap, "getError");
+ errorCallbackTag =
+ errorStream.addCallback(
+ (error) -> {
+ if (error < 3.0) {
+ isOriented = true;
+ errorStream.removeCallback(errorCallbackTag);
+ }
+ });
+ errorStream.start();
+ vessel.getActiveVessel().getAutoPilot().disengage();
+ control.setSAS(true);
+ control.setSASMode(SASMode.STABILITY_ASSIST);
+ }
+
+ 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;
+
+ 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;
+ 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,
+ DOCKING_MAX_SPEED);
+ sidewaysError =
+ calculateThrottle(0, 5, currentXAxisSpeed, targetPosition.x, DOCKING_MAX_SPEED);
+ upwardsError =
+ calculateThrottle(0, 5, currentZAxisSpeed, targetPosition.z, DOCKING_MAX_SPEED);
+ control.setForward(forwardsError);
+ control.setRight(sidewaysError);
+ control.setUp(-upwardsError);
+ DockingJPanel.setDockingStep(Bundle.getString("pnl_docking_step_approach"));
+ break;
+ case LINE_UP_WITH_TARGET:
+ forwardsError =
+ calculateThrottle(
+ forwardsDistanceLimit,
+ forwardsDistanceLimit * 3,
+ currentYAxisSpeed,
+ targetPosition.y,
+ 0);
+ sidewaysError =
+ calculateThrottle(0, 10, currentXAxisSpeed, targetPosition.x, DOCKING_MAX_SPEED);
+ upwardsError =
+ calculateThrottle(0, 10, currentZAxisSpeed, targetPosition.z, DOCKING_MAX_SPEED);
+ control.setForward(forwardsError);
+ control.setRight(sidewaysError);
+ control.setUp(-upwardsError);
+ DockingJPanel.setDockingStep(Bundle.getString("pnl_docking_step_line_up_with_target"));
+ break;
+ case GO_IN_FRONT_OF_TARGET:
+ forwardsError =
+ calculateThrottle(-20, -10, currentYAxisSpeed, targetPosition.y, DOCKING_MAX_SPEED);
+ 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);
+ if (isInFrontOfTarget) {
+ dockingStep = DOCKING_STEPS.STOP_RELATIVE_SPEED;
+ break;
+ }
+ DockingJPanel.setDockingStep(Bundle.getString("pnl_docking_step_go_in_front_of_target"));
+ break;
+ case STOP_RELATIVE_SPEED:
+ forwardsError = calculateThrottle(0, 5, currentYAxisSpeed, targetPosition.y, 0);
+ 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);
+ if ((Math.abs(currentXAxisSpeed) < 1)
+ && (Math.abs(currentYAxisSpeed) < 1)
+ && (Math.abs(currentZAxisSpeed) < 1)) {
+ dockingStep = DOCKING_STEPS.APPROACH;
+ break;
+ }
+ DockingJPanel.setDockingStep(Bundle.getString("pnl_docking_step_stop_relative_speed"));
+ break;
+ }
+ System.out.println(dockingStep);
+
+ // Guardar últimas posições:
+ lastXTargetPos = targetPosition.x;
+ lastYTargetPos = targetPosition.y;
+ lastZTargetPos = targetPosition.z;
+ } catch (RPCException ignored) {
}
-
- 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;
-
- 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;
- 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, DOCKING_MAX_SPEED);
- sidewaysError = calculateThrottle(0, 5, currentXAxisSpeed, targetPosition.x, DOCKING_MAX_SPEED);
- upwardsError = calculateThrottle(0, 5, currentZAxisSpeed, targetPosition.z, DOCKING_MAX_SPEED);
- control.setForward(forwardsError);
- control.setRight(sidewaysError);
- control.setUp(-upwardsError);
- DockingJPanel.setDockingStep(Bundle.getString("pnl_docking_step_approach"));
- break;
- case LINE_UP_WITH_TARGET :
- forwardsError = calculateThrottle(forwardsDistanceLimit, forwardsDistanceLimit * 3,
- currentYAxisSpeed, targetPosition.y, 0);
- sidewaysError = calculateThrottle(0, 10, currentXAxisSpeed, targetPosition.x, DOCKING_MAX_SPEED);
- upwardsError = calculateThrottle(0, 10, currentZAxisSpeed, targetPosition.z, DOCKING_MAX_SPEED);
- control.setForward(forwardsError);
- control.setRight(sidewaysError);
- control.setUp(-upwardsError);
- DockingJPanel.setDockingStep(Bundle.getString("pnl_docking_step_line_up_with_target"));
- break;
- case GO_IN_FRONT_OF_TARGET :
- forwardsError = calculateThrottle(-20, -10, currentYAxisSpeed, targetPosition.y, DOCKING_MAX_SPEED);
- 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);
- if (isInFrontOfTarget) {
- dockingStep = DOCKING_STEPS.STOP_RELATIVE_SPEED;
- break;
- }
- DockingJPanel.setDockingStep(Bundle.getString("pnl_docking_step_go_in_front_of_target"));
- break;
- case STOP_RELATIVE_SPEED :
- forwardsError = calculateThrottle(0, 5, currentYAxisSpeed, targetPosition.y, 0);
- 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);
- if ((Math.abs(currentXAxisSpeed) < 1) && (Math.abs(currentYAxisSpeed) < 1)
- && (Math.abs(currentZAxisSpeed) < 1)) {
- dockingStep = DOCKING_STEPS.APPROACH;
- break;
- }
- DockingJPanel.setDockingStep(Bundle.getString("pnl_docking_step_stop_relative_speed"));
- 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 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 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) {
}
+ }
- 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 cleanup() {
+ if (dockingExecutor != null && !dockingExecutor.isShutdown()) {
+ dockingExecutor.shutdownNow();
}
-
- 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) {
- }
+ try {
+ if (errorStream != null) {
+ errorStream.remove();
+ }
+ distanceLine.remove();
+ distLineXAxis.remove();
+ distLineYAxis.remove();
+ distLineZAxis.remove();
+ vessel.ap.disengage();
+ vessel.throttle(0);
+ } catch (RPCException | NullPointerException e) {
+ // ignore
}
-
+ }
}
diff --git a/src/main/java/com/pesterenan/controllers/LandingController.java b/src/main/java/com/pesterenan/controllers/LandingController.java
index 57cdc6f..12bf23b 100644
--- a/src/main/java/com/pesterenan/controllers/LandingController.java
+++ b/src/main/java/com/pesterenan/controllers/LandingController.java
@@ -1,284 +1,436 @@
package com.pesterenan.controllers;
-import static com.pesterenan.MechPeste.getSpaceCenter;
-
-import java.util.Map;
-
+import com.pesterenan.model.ActiveVessel;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.ControlePID;
import com.pesterenan.utils.Module;
import com.pesterenan.utils.Navigation;
import com.pesterenan.utils.Utilities;
-
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import krpc.client.RPCException;
+import krpc.client.Stream;
import krpc.client.StreamException;
+import krpc.client.services.SpaceCenter.Engine;
import krpc.client.services.SpaceCenter.VesselSituation;
public class LandingController extends Controller {
- public static final double MAX_VELOCITY = 5;
- 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;
- private boolean hoveringMode;
- private boolean hoverAfterApproximation;
- private boolean landingMode;
- private MODE currentMode;
- private double altitudeErrorPercentage;
- private float maxTWR;
-
- public LandingController(Map commands) {
- super();
- this.commands = commands;
- this.navigation = new Navigation(getActiveVessel());
- this.initializeParameters();
- }
+ private enum MODE {
+ APPROACHING,
+ DEORBITING,
+ ORIENTING_DEORBIT,
+ EXECUTING_DEORBIT_BURN,
+ GOING_DOWN,
+ GOING_UP,
+ HOVERING,
+ LANDING,
+ WAITING
+ }
- private void initializeParameters() {
- altitudeCtrl = new ControlePID(getSpaceCenter(), sleepTime);
- velocityCtrl = new ControlePID(getSpaceCenter(), sleepTime);
- altitudeCtrl.setOutput(0, 1);
- velocityCtrl.setOutput(0, 1);
- }
+ public static final double MAX_VELOCITY = 5;
+ private static final double velP = 0.05;
+ private static final double velI = 0.000001;
+ private static final double velD = 0.001;
+ private ControlePID altitudeCtrl;
+ private ControlePID velocityCtrl;
+ private Navigation navigation;
+ private final int HUNDRED_PERCENT = 100;
+ private double altitudeErrorPercentage, hoverAltitude, targetPeriapsis;
+ private boolean hoverAfterApproximation, landingMode;
+ private MODE currentMode;
+ private float maxTWR;
+ private final Map commands;
- @Override
- public void run() {
- if (commands.get(Module.MODULO.get()).equals(Module.HOVERING.get())) {
- hoverArea();
- }
- if (commands.get(Module.MODULO.get()).equals(Module.LANDING.get())) {
- autoLanding();
- }
+ private volatile boolean isDeorbitBurnDone, isOrientedForDeorbit, isFalling, wasAirborne = false;
+ private int isOrientedCallbackTag, isDeorbitBurnDoneCallbackTag, isFallingCallbackTag;
+ private Stream apErrorStream;
+ private ScheduledExecutorService landingExecutor;
+
+ public LandingController(ActiveVessel vessel, Map commands) {
+ super(vessel);
+ this.commands = commands;
+ this.navigation = new Navigation(vessel.getConnectionManager(), vessel.getActiveVessel());
+ this.initializeParameters();
+ }
+
+ @Override
+ public void run() {
+ try {
+ if (commands.get(Module.MODULO.get()).equals(Module.HOVERING.get())) {
+ hoverArea();
+ } else if (commands.get(Module.MODULO.get()).equals(Module.LANDING.get())) {
+ autoLanding();
+ }
+ landingExecutor = Executors.newSingleThreadScheduledExecutor();
+ landingExecutor.scheduleAtFixedRate(this::landingStateMachine, 0, 100, TimeUnit.MILLISECONDS);
+ } catch (RPCException | StreamException e) {
+ System.err.println("Erro no run do landingController:" + e.getMessage());
+ setCurrentStatus(Bundle.getString("status_data_unavailable"));
+ cleanup();
}
+ }
- private void hoverArea() {
- try {
- hoverAltitude = Double.parseDouble(commands.get(Module.HOVER_ALTITUDE.get()));
- hoveringMode = true;
- ap.engage();
- tuneAutoPilot();
- while (hoveringMode) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- try {
- altitudeErrorPercentage = surfaceAltitude.get() / hoverAltitude * HUNDRED_PERCENT;
- // Select which mode depending on altitude error:
- if (altitudeErrorPercentage > HUNDRED_PERCENT) {
- currentMode = MODE.GOING_DOWN;
- } else if (altitudeErrorPercentage < HUNDRED_PERCENT * 0.9) {
- currentMode = MODE.GOING_UP;
- } else {
- currentMode = MODE.HOVERING;
- }
- changeControlMode();
- } catch (RPCException | StreamException ignored) {
- }
- Thread.sleep(sleepTime);
- }
- } catch (InterruptedException | RPCException ignored) {
- // disengageAfterException(Bundle.getString("status_liftoff_abort"));
+ private void landingStateMachine() {
+ try {
+ if (!isRunning()) {
+ cleanup();
+ return;
+ }
+ if (landingMode) {
+ executeLandingStep();
+ } else {
+ altitudeErrorPercentage = vessel.surfaceAltitude.get() / hoverAltitude * HUNDRED_PERCENT;
+ if (altitudeErrorPercentage > HUNDRED_PERCENT * 1.1) {
+ currentMode = MODE.GOING_DOWN;
+ } else if (altitudeErrorPercentage < HUNDRED_PERCENT * 0.9) {
+ currentMode = MODE.GOING_UP;
+ } else {
+ currentMode = MODE.HOVERING;
}
+ executeHoverStep();
+ }
+ } catch (Exception e) {
+ System.err.println("Landing state machine error: " + e.getMessage());
+ cleanup();
}
+ }
- private void autoLanding() {
- try {
- landingMode = true;
- maxTWR = Float.parseFloat(commands.get(Module.MAX_TWR.get()));
- hoverAfterApproximation = Boolean.parseBoolean(commands.get(Module.HOVER_AFTER_LANDING.get()));
- hoverAltitude = Double.parseDouble(commands.get(Module.HOVER_ALTITUDE.get()));
- if (!hoverAfterApproximation) {
- hoverAltitude = 100;
- }
- setCurrentStatus(Bundle.getString("status_starting_landing_at") + " " + currentBody.getName());
- currentMode = MODE.DEORBITING;
- ap.engage();
- changeControlMode();
- tuneAutoPilot();
- setCurrentStatus(Bundle.getString("status_starting_landing"));
- while (landingMode) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- getActiveVessel().getControl().setBrakes(true);
- changeControlMode();
- Thread.sleep(sleepTime);
- }
- } catch (RPCException | StreamException | InterruptedException e) {
- setCurrentStatus(Bundle.getString("status_ready"));
- }
+ private void initializeParameters() {
+ maxTWR = Float.parseFloat(commands.get(Module.MAX_TWR.get()));
+ hoverAltitude = Double.parseDouble(commands.get(Module.HOVER_ALTITUDE.get()));
+ altitudeCtrl = new ControlePID(vessel.spaceCenter);
+ velocityCtrl = new ControlePID(vessel.spaceCenter);
+ altitudeCtrl.setOutput(0, 1);
+ velocityCtrl.setOutput(0, 1);
+ }
+
+ private void hoverArea() throws RPCException, StreamException {
+ landingMode = false;
+ vessel.ap.engage();
+ vessel.tuneAutoPilot();
+ setupCallbacks();
+ }
+
+ private void autoLanding() throws RPCException, StreamException {
+ landingMode = true;
+ hoverAfterApproximation = Boolean.parseBoolean(commands.get(Module.HOVER_AFTER_LANDING.get()));
+ if (!hoverAfterApproximation) {
+ hoverAltitude = 100;
}
+ altitudeCtrl.reset();
+ velocityCtrl.reset();
+ setCurrentStatus(
+ Bundle.getString("status_starting_landing_at") + " " + vessel.currentBody.getName());
+ currentMode = MODE.DEORBITING;
+ vessel.ap.engage();
+ vessel.tuneAutoPilot();
+ vessel.getActiveVessel().getControl().setBrakes(true);
+ setCurrentStatus(Bundle.getString("status_starting_landing"));
+ setupCallbacks();
+ }
- private void changeControlMode() throws RPCException, StreamException, InterruptedException {
- adjustPIDbyTWR();
- double velPID, altPID = 0;
- // Change vessel behavior depending on which mode is active
- switch (currentMode) {
- case DEORBITING :
- deOrbitShip();
- currentMode = MODE.WAITING;
- break;
- case WAITING :
- if (verticalVelocity.get() > 0) {
- setCurrentStatus(Bundle.getString("status_waiting_for_landing"));
- throttle(0.0f);
- } else {
- currentMode = MODE.APPROACHING;
- }
- break;
- case APPROACHING :
- 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.calculate(currentVelocity / sleepTime, zeroVelocity / sleepTime);
- velPID = velocityCtrl.calculate(verticalVelocity.get() / sleepTime,
- (-Utilities.clamp(surfaceAltitude.get() * 0.1, 3, 20) / sleepTime));
- throttle(Utilities.linearInterpolation(velPID, altPID, threshold));
- navigation.aimForLanding();
- if (threshold < 0.15 || surfaceAltitude.get() < landingDistanceThreshold) {
- hoverAltitude = landingDistanceThreshold;
- getActiveVessel().getControl().setGear(true);
- if (hoverAfterApproximation) {
- landingMode = false;
- hoverArea();
- break;
- }
- currentMode = MODE.LANDING;
+ private void setupCallbacks() throws RPCException, StreamException {
+ // Callback for ship orientation
+ apErrorStream = vessel.connection.addStream(vessel.ap, "getError");
+ isOrientedCallbackTag =
+ apErrorStream.addCallback(
+ (error) -> {
+ if (error <= 5.0) {
+ isOrientedForDeorbit = true;
+ apErrorStream.removeCallback(isOrientedCallbackTag);
+ }
+ });
+
+ // Callback for de-orbit burn completion
+ isDeorbitBurnDoneCallbackTag =
+ vessel.periapsis.addCallback(
+ p -> {
+ try {
+ if (isDeorbitBurnDone) return; // Stop if flag is already set
+
+ if (currentMode == MODE.EXECUTING_DEORBIT_BURN) {
+ // During de-orbit, actively control throttle
+ if (p <= targetPeriapsis) {
+ isDeorbitBurnDone = true;
+ vessel.throttle(0.0f);
+ vessel.periapsis.removeCallback(isDeorbitBurnDoneCallbackTag);
+ } else {
+ vessel.throttle(altitudeCtrl.calculate(targetPeriapsis, p));
+ }
}
- setCurrentStatus("Se aproximando do momento do pouso...");
- break;
- case GOING_UP :
- 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(verticalVelocity.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(
- horizontalVelocity.get() > 4 ? 0 : -Utilities.clamp(surfaceAltitude.get() * 0.1, 1, 10));
- navigation.aimForLanding();
- setCurrentStatus("Pousando...");
- hasTheVesselLanded();
- break;
- case HOVERING :
- 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(verticalVelocity.get(), 0);
- throttle(altPID + velPID);
- navigation.aimAtRadialOut();
- setCurrentStatus("Sobrevoando area...");
- break;
- }
- }
+ } catch (RPCException e) {
+ System.err.println("isDeorbitBurnDoneCallbackTag error: " + e.getMessage());
+ }
+ });
- private void controlThrottleByMatchingVerticalVelocity(double velocityToMatch)
- throws RPCException, StreamException {
- velocityCtrl.setOutput(0, 1);
- throttle(velocityCtrl.calculate(verticalVelocity.get(), velocityToMatch + horizontalVelocity.get()));
- }
+ // Callback for when the ship starts falling back to the ground
+ isFallingCallbackTag =
+ vessel.verticalVelocity.addCallback(
+ (vv) -> {
+ if (vv <= 0) {
+ isFalling = true;
+ vessel.verticalVelocity.removeCallback(isFallingCallbackTag);
+ }
+ });
+
+ // Start all streams
+ apErrorStream.start();
+ vessel.apoapsis.start();
+ vessel.periapsis.start();
+ vessel.verticalVelocity.start();
+ }
- private void deOrbitShip() throws RPCException, StreamException, InterruptedException {
- throttle(0.0f);
- if (getActiveVessel().getSituation().equals(VesselSituation.ORBITING)
- || getActiveVessel().getSituation().equals(VesselSituation.SUB_ORBITAL)) {
- setCurrentStatus(Bundle.getString("status_going_suborbital"));
- ap.engage();
- getActiveVessel().getControl().setRCS(true);
- while (ap.getError() > 5) {
- navigation.aimForLanding();
- setCurrentStatus(Bundle.getString("status_orienting_ship"));
- ap.wait_();
- Thread.sleep(sleepTime);
- }
- double targetPeriapsis = currentBody.getAtmosphereDepth();
- targetPeriapsis = targetPeriapsis > 0 ? targetPeriapsis / 2 : -currentBody.getEquatorialRadius() / 2;
- while (periapsis.get() > -apoapsis.get()) {
- navigation.aimForLanding();
- throttle(altitudeCtrl.calculate(targetPeriapsis, periapsis.get()));
- setCurrentStatus(Bundle.getString("status_lowering_periapsis"));
- Thread.sleep(sleepTime);
- }
- getActiveVessel().getControl().setRCS(false);
- throttle(0.0f);
+ private void executeLandingStep() throws RPCException, StreamException, InterruptedException {
+ adjustLandingPID();
+ // Change vessel behavior depending on which mode is active
+ switch (currentMode) {
+ case DEORBITING:
+ if (vessel.getActiveVessel().getSituation().equals(VesselSituation.ORBITING)
+ || vessel.getActiveVessel().getSituation().equals(VesselSituation.SUB_ORBITAL)) {
+ setCurrentStatus(Bundle.getString("status_going_suborbital"));
+ vessel.getActiveVessel().getControl().setRCS(true);
+ vessel.throttle(0.0f);
+ targetPeriapsis = vessel.currentBody.getAtmosphereDepth();
+ targetPeriapsis =
+ targetPeriapsis > 0
+ ? targetPeriapsis / 2
+ : -vessel.currentBody.getEquatorialRadius() / 2;
+ currentMode = MODE.ORIENTING_DEORBIT;
+ } else {
+ currentMode = MODE.APPROACHING;
}
- }
+ break;
+ case ORIENTING_DEORBIT:
+ setCurrentStatus(Bundle.getString("status_orienting_ship"));
+ navigation.aimForDeorbit();
+ if (isOrientedForDeorbit) {
+ currentMode = MODE.EXECUTING_DEORBIT_BURN;
+ }
+ break;
+ case EXECUTING_DEORBIT_BURN:
+ setCurrentStatus(Bundle.getString("status_lowering_periapsis"));
+ if (isDeorbitBurnDone) {
+ vessel.getActiveVessel().getControl().setRCS(false);
+ vessel.throttle(0.0f);
+ currentMode = MODE.WAITING;
+ }
+ break;
+ case WAITING:
+ if (isFalling) {
+ currentMode = MODE.APPROACHING;
+ } else {
+ setCurrentStatus(Bundle.getString("status_waiting_for_landing"));
+ vessel.throttle(0.0f);
+ }
+ break;
+ case APPROACHING:
+ for (Engine engine : vessel.getActiveVessel().getParts().getEngines()) {
+ if (engine.getPart().getStage() == vessel.getActiveVessel().getControl().getCurrentStage()
+ && !engine.getActive()) {
+ engine.setActive(true);
+ }
+ }
+ altitudeCtrl.setOutput(0, 1);
+ velocityCtrl.setOutput(0, 1);
- /**
- * Adjust altitude and velocity PID gains according to current ship TWR:
- */
- private void adjustPIDbyTWR() throws RPCException, StreamException {
- double currentTWR = Math.min(getTWR(), maxTWR);
- // 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);
- }
+ double brakingDistance = calculateBrakingDistance();
+ double surfaceAltitude = vessel.surfaceAltitude.get();
+ // The threshold is a ratio of our current altitude versus the altitude needed to brake.
+ // It's 1 when we are much higher than the braking distance, and drops to 0 as we approach
+ // it.
+ double threshold =
+ (brakingDistance > 1)
+ ? Utilities.clamp(surfaceAltitude / brakingDistance - 1, 0, 1)
+ : 0;
- private boolean hasTheVesselLanded() throws RPCException {
- if (getActiveVessel().getSituation().equals(VesselSituation.LANDED)
- || getActiveVessel().getSituation().equals(VesselSituation.SPLASHED)) {
- setCurrentStatus(Bundle.getString("status_landed"));
- hoveringMode = false;
+ double altPID = altitudeCtrl.calculate(surfaceAltitude, brakingDistance);
+ double velPID =
+ velocityCtrl.calculate(
+ vessel.verticalVelocity.get(),
+ (-Utilities.clamp(vessel.surfaceAltitude.get() * 0.1, 3, 20)));
+ vessel.throttle(Utilities.linearInterpolation(velPID, altPID, threshold));
+ navigation.aimForLanding();
+
+ double landingDistanceThreshold = Math.max(hoverAltitude, vessel.getMaxAcel(maxTWR) * 3);
+ if (surfaceAltitude < landingDistanceThreshold) {
+ vessel.getActiveVessel().getControl().setGear(true);
+ if (hoverAfterApproximation) {
landingMode = false;
- throttle(0.0f);
- getActiveVessel().getControl().setSAS(true);
- getActiveVessel().getControl().setRCS(true);
- getActiveVessel().getControl().setBrakes(false);
- ap.disengage();
- return true;
+ hoverArea();
+ break;
+ }
+ currentMode = MODE.LANDING;
}
- return false;
+ setCurrentStatus("Se aproximando do momento do pouso...");
+ break;
+
+ case LANDING:
+ if (hasTheVesselLanded()) break;
+ controlThrottleByMatchingVerticalVelocity(
+ vessel.horizontalVelocity.get() > 5
+ ? 0
+ : -Utilities.clamp(vessel.surfaceAltitude.get() * 0.1, 3, 20));
+ navigation.aimForLanding();
+ setCurrentStatus("Pousando...");
+ break;
+ default:
+ break;
}
+ }
- private double calculateCurrentVelocityMagnitude() throws RPCException, StreamException {
- double timeToGround = surfaceAltitude.get() / verticalVelocity.get();
- double horizontalDistance = horizontalVelocity.get() * timeToGround;
- return calculateEllipticTrajectory(horizontalDistance, surfaceAltitude.get());
+ private void executeHoverStep() throws RPCException, StreamException, InterruptedException {
+ if (hasTheVesselLanded()) {
+ stop();
+ return;
}
+ adjustHoverPID();
+ altitudeCtrl.setOutput(-0.5, 0.5);
+ velocityCtrl.setOutput(-0.5, 0.5);
+ switch (currentMode) {
+ case GOING_UP:
+ vessel.throttle(
+ altitudeCtrl.calculate(altitudeErrorPercentage, HUNDRED_PERCENT)
+ + velocityCtrl.calculate(vessel.verticalVelocity.get(), MAX_VELOCITY));
+ navigation.aimAtRadialOut();
+ setCurrentStatus("Subindo altitude...");
+ break;
+ case GOING_DOWN:
+ controlThrottleByMatchingVerticalVelocity(-MAX_VELOCITY);
+ navigation.aimAtRadialOut();
+ setCurrentStatus("Baixando altitude...");
+ break;
+ case HOVERING:
+ vessel.throttle(
+ altitudeCtrl.calculate(altitudeErrorPercentage, HUNDRED_PERCENT)
+ + velocityCtrl.calculate(0, -vessel.verticalVelocity.get()));
+ navigation.aimAtRadialOut();
+ setCurrentStatus("Sobrevoando area...");
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void adjustLandingPID() throws RPCException, StreamException {
+ double maxAccel = vessel.getMaxAcel(maxTWR);
+ double currentTWR = Math.min(vessel.getTWR(), maxTWR);
+
+ if (currentMode == MODE.APPROACHING) {
+ // 1. Calcula a distância de trajetória restante
+ double trajectoryLength;
+ double timeToGround = 0;
+ if (vessel.verticalVelocity.get() < -0.1) { // Apenas calcula se estiver descendo
+ timeToGround = vessel.surfaceAltitude.get() / -vessel.verticalVelocity.get();
+ }
+ if (timeToGround > 0) {
+ double horizontalDistance = vessel.horizontalVelocity.get() * timeToGround;
+ trajectoryLength =
+ calculateEllipticTrajectory(horizontalDistance, vessel.surfaceAltitude.get());
+ } else {
+ trajectoryLength = vessel.surfaceAltitude.get(); // Usa apenas a altitude como fallback
+ }
+
+ // 2. Calcula a velocidade total (vetorial)
+ double totalVelocity =
+ Math.sqrt(
+ Math.pow(vessel.verticalVelocity.get(), 2)
+ + Math.pow(vessel.horizontalVelocity.get(), 2));
- private double calculateZeroVelocityMagnitude() throws RPCException, StreamException {
- double zeroVelocityDistance = calculateEllipticTrajectory(horizontalVelocity.get(), verticalVelocity.get());
- double zeroVelocityBurnTime = zeroVelocityDistance / getMaxAcel(maxTWR);
- return zeroVelocityDistance * zeroVelocityBurnTime;
+ // 3. Calcula o tempo de impacto baseado na TRAJETÓRIA
+ double timeToImpact = 10.0; // Default seguro
+ if (totalVelocity > 1) { // Evita divisão por zero
+ timeToImpact = Utilities.clamp(trajectoryLength / totalVelocity, 0.5, 20);
+ }
+
+ // O resto da lógica permanece o mesmo, mas agora usando o novo timeToImpact
+ double Kp = (currentTWR * velP) / timeToImpact;
+ double Kd = Kp * (velD / velP);
+ double Ki = 0.0001;
+ altitudeCtrl.setPIDValues(Kp, Ki, Kd);
+ } else {
+ // Para outros modos, usa um PID mais simples e estável
+ altitudeCtrl.setPIDValues(maxAccel * velP, velI, velD);
}
- private double calculateEllipticTrajectory(double a, double b) {
- double semiMajor = Math.max(a * 2, b * 2);
- double semiMinor = Math.min(a * 2, b * 2);
- return Math.PI * Math.sqrt((semiMajor * semiMajor + semiMinor * semiMinor)) / 4;
+ // O controlador de velocidade pode usar uma sintonia mais simples
+ velocityCtrl.setPIDValues(currentTWR * velP, velI, velD);
+ }
+
+ private void adjustHoverPID() throws RPCException, StreamException {
+ double currentTWR = Math.min(vessel.getTWR(), maxTWR);
+ altitudeCtrl.setPIDValues(currentTWR * velP, currentTWR * velI, currentTWR * velD);
+ velocityCtrl.setPIDValues(currentTWR * velP, currentTWR * velI, currentTWR * velD);
+ }
+
+ private void controlThrottleByMatchingVerticalVelocity(double velocityToMatch)
+ throws RPCException, StreamException {
+ velocityCtrl.setOutput(0, 1);
+ vessel.throttle(
+ velocityCtrl.calculate(
+ vessel.verticalVelocity.get(), velocityToMatch + vessel.horizontalVelocity.get()));
+ }
+
+ private boolean hasTheVesselLanded() throws RPCException {
+ VesselSituation situation = vessel.getActiveVessel().getSituation();
+ if (wasAirborne
+ && (situation.equals(VesselSituation.LANDED)
+ || situation.equals(VesselSituation.SPLASHED))) {
+ setCurrentStatus(Bundle.getString("status_landed"));
+ stop();
+ vessel.throttle(0.0f);
+ vessel.getActiveVessel().getControl().setSAS(true);
+ vessel.getActiveVessel().getControl().setRCS(true);
+ vessel.getActiveVessel().getControl().setBrakes(false);
+ vessel.ap.disengage();
+ return true;
+ }
+ // If we are not landed, we must be airborne
+ if (!situation.equals(VesselSituation.LANDED)
+ && !situation.equals(VesselSituation.SPLASHED)
+ && !situation.equals(VesselSituation.PRE_LAUNCH)) {
+ wasAirborne = true;
+ }
+ return false;
+ }
+
+ private double calculateBrakingDistance() throws RPCException, StreamException {
+ double totalVelocity =
+ Math.sqrt(
+ Math.pow(vessel.verticalVelocity.get(), 2)
+ + Math.pow(vessel.horizontalVelocity.get(), 2));
+ // Braking distance formula: d = v^2 / (2 * a)
+ // where a is the effective deceleration (max engine acceleration - gravity)
+ double maxDeceleration = vessel.getMaxAcel(maxTWR);
+ if (maxDeceleration <= 0.1) { // Avoid division by zero or tiny numbers
+ return Double.POSITIVE_INFINITY;
}
+ return Math.pow(totalVelocity, 2) / (2 * maxDeceleration);
+ }
+
+ private double calculateEllipticTrajectory(double a, double b) {
+ double semiMajor = Math.max(a * 2, b * 2);
+ double semiMinor = Math.min(a * 2, b * 2);
+ return Math.PI * Math.sqrt((semiMajor * semiMajor + semiMinor * semiMinor)) / 4;
+ }
- private enum MODE {
- DEORBITING, APPROACHING, GOING_UP, HOVERING, GOING_DOWN, LANDING, WAITING
+ private void cleanup() {
+ if (landingExecutor != null && !landingExecutor.isShutdown()) {
+ landingExecutor.shutdownNow();
+ }
+ try {
+ if (vessel.ap != null) {
+ vessel.ap.disengage();
+ }
+ if (apErrorStream != null) {
+ apErrorStream.remove();
+ }
+ vessel.throttle(0);
+ setCurrentStatus(Bundle.getString("status_ready"));
+ } catch (RPCException | NullPointerException e) {
+ System.err.println("Erro durante a limpeza do LandingController: " + e.getMessage());
}
+ }
}
diff --git a/src/main/java/com/pesterenan/controllers/LiftoffController.java b/src/main/java/com/pesterenan/controllers/LiftoffController.java
index 2901639..2c9139d 100644
--- a/src/main/java/com/pesterenan/controllers/LiftoffController.java
+++ b/src/main/java/com/pesterenan/controllers/LiftoffController.java
@@ -1,220 +1,286 @@
package com.pesterenan.controllers;
-import static com.pesterenan.MechPeste.getSpaceCenter;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import com.pesterenan.MechPeste;
+import com.pesterenan.model.ActiveVessel;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.ControlePID;
import com.pesterenan.utils.Module;
import com.pesterenan.utils.Navigation;
import com.pesterenan.utils.Utilities;
-
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
import krpc.client.RPCException;
+import krpc.client.Stream;
import krpc.client.StreamException;
import krpc.client.services.SpaceCenter.Engine;
import krpc.client.services.SpaceCenter.Fairing;
+import krpc.client.services.SpaceCenter.VesselSituation;
public class LiftoffController extends Controller {
- private static final float PITCH_UP = 90;
- private ControlePID thrControl;
- private float currentPitch;
- private float finalApoapsisAlt;
- private float heading;
- private float roll;
- private float maxTWR;
-
- private boolean willDecoupleStages, willOpenPanelsAndAntenna;
- private String gravityCurveModel = Module.CIRCULAR.get();
- private Navigation navigation;
-
- public LiftoffController(Map commands) {
- super();
- this.commands = commands;
- this.navigation = new Navigation(getActiveVessel());
- initializeParameters();
- }
+ private enum LIFTOFF_MODE {
+ GRAVITY_TURN,
+ FINALIZE_ORBIT,
+ CIRCULARIZE
+ }
- private void initializeParameters() {
- currentPitch = PITCH_UP;
- setFinalApoapsisAlt(Float.parseFloat(commands.get(Module.APOAPSIS.get())));
- setHeading(Float.parseFloat(commands.get(Module.DIRECTION.get())));
- setRoll(Float.parseFloat(commands.get(Module.ROLL.get())));
- maxTWR = (float) Utilities.clamp(Float.parseFloat(commands.get(Module.MAX_TWR.get())), 1.2, 5.0);
- setGravityCurveModel(commands.get(Module.INCLINATION.get()));
- willOpenPanelsAndAntenna = Boolean.parseBoolean(commands.get(Module.OPEN_PANELS.get()));
- willDecoupleStages = Boolean.parseBoolean(commands.get(Module.STAGE.get()));
- thrControl = new ControlePID(getSpaceCenter(), 25);
- thrControl.setOutput(0.0, 1.0);
- }
+ private static final float PITCH_UP = 90;
+ private ControlePID thrControl;
+ private float currentPitch, finalApoapsisAlt, heading, roll, maxTWR;
+ private volatile boolean targetApoapsisReached, dynamicPressureLowEnough;
+ private int apoapsisCallbackTag, pressureCallbackTag;
+ private Stream pressureStream;
+ private boolean willDecoupleStages, willOpenPanelsAndAntenna;
+ private String gravityCurveModel = Module.CIRCULAR.get();
+ private Navigation navigation;
+ private LIFTOFF_MODE liftoffMode;
+ private double startCurveAlt;
+ private final Map commands;
+ private ScheduledExecutorService liftoffExecutor;
- @Override
- public void run() {
- try {
- tuneAutoPilot();
- liftoff();
- gravityCurve();
- finalizeCurve();
- circularizeOrbitOnApoapsis();
- } catch (RPCException | InterruptedException | StreamException ignored) {
- setCurrentStatus(Bundle.getString("status_ready"));
- }
- }
+ public LiftoffController(ActiveVessel vessel, Map commands) {
+ super(vessel);
+ this.commands = commands;
+ this.navigation = new Navigation(vessel.getConnectionManager(), vessel.getActiveVessel());
+ initializeParameters();
+ }
- private void gravityCurve() throws RPCException, StreamException, InterruptedException {
- ap.setReferenceFrame(surfaceReferenceFrame);
- ap.targetPitchAndHeading(currentPitch, getHeading());
- ap.setTargetRoll(getRoll());
- ap.engage();
- throttle(getMaxThrottleForTWR(maxTWR));
- double startCurveAlt = altitude.get();
-
- while (currentPitch > 1) {
- if (apoapsis.get() > getFinalApoapsis()) {
- throttle(0);
- break;
- }
- double altitudeProgress = Utilities.remap(startCurveAlt, getFinalApoapsis(), 1, 0.01, altitude.get(),
- false);
- currentPitch = (float) (calculateCurrentPitch(altitudeProgress));
- double currentMaxTWR = calculateTWRBasedOnPressure(currentPitch);
- ap.setTargetPitch(currentPitch);
- throttle(Math.min(thrControl.calculate(apoapsis.get() / getFinalApoapsis() * 1000, 1000),
- getMaxThrottleForTWR(currentMaxTWR)));
-
- if (willDecoupleStages && isCurrentStageWithoutFuel()) {
- decoupleStage();
- }
- setCurrentStatus(String.format(Bundle.getString("status_liftoff_inclination") + " %.1f", currentPitch));
-
- Thread.sleep(25);
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
+ @Override
+ public void run() {
+ try {
+ // Part 1: Blocking Countdown and Launch
+ if (vessel.getActiveVessel().getSituation().equals(VesselSituation.PRE_LAUNCH)) {
+ vessel.throttleUp(vessel.getMaxThrottleForTWR(1.4), 1);
+ for (double count = 5.0; count >= 0; count -= 0.1) {
+ if (!isRunning()) return;
+ setCurrentStatus(String.format(Bundle.getString("status_launching_in"), count));
+ Thread.sleep(100);
}
- }
+ setCurrentStatus(Bundle.getString("status_liftoff"));
+ vessel.getActiveVessel().getControl().activateNextStage();
+ } else {
+ vessel.throttle(1.0f);
+ }
- private double calculateTWRBasedOnPressure(float currentPitch) throws RPCException {
- float currentPressure = flightParameters.getDynamicPressure();
- if (currentPressure <= 10) {
- return Utilities.remap(90.0, 0.0, maxTWR, 5.0, currentPitch, true);
- }
- return Utilities.remap(22000.0, 10.0, maxTWR, 5.0, currentPressure, true);
- }
+ // Part 2: Async Gravity Turn
+ liftoffMode = LIFTOFF_MODE.GRAVITY_TURN; // Set initial state for async phase
+ setupCallbacks();
+ vessel.tuneAutoPilot();
+ startCurveAlt = vessel.altitude.get();
+ vessel.ap.setReferenceFrame(vessel.surfaceReferenceFrame);
+ vessel.ap.targetPitchAndHeading(currentPitch, heading);
+ vessel.ap.setTargetRoll(this.roll);
+ vessel.ap.engage();
- private void finalizeCurve() throws RPCException, StreamException, InterruptedException {
- setCurrentStatus(Bundle.getString("status_maintaining_until_orbit"));
- getActiveVessel().getControl().setRCS(true);
-
- while (flightParameters.getDynamicPressure() > 10) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- navigation.aimAtPrograde();
- throttle(thrControl.calculate(apoapsis.get() / getFinalApoapsis() * 1000, 1000));
- Thread.sleep(25);
- }
- throttle(0.0f);
- if (willDecoupleStages) {
- jettisonFairings();
- }
- if (willOpenPanelsAndAntenna) {
- openPanelsAndAntenna();
- }
- }
+ liftoffExecutor = Executors.newSingleThreadScheduledExecutor();
+ liftoffExecutor.scheduleAtFixedRate(this::handleLiftoff, 0, 100, TimeUnit.MILLISECONDS);
- private void circularizeOrbitOnApoapsis() {
- setCurrentStatus(Bundle.getString("status_planning_orbit"));
- Map commands = new HashMap<>();
- commands.put(Module.MODULO.get(), Module.MANEUVER.get());
- commands.put(Module.FUNCTION.get(), Module.APOAPSIS.get());
- commands.put(Module.FINE_ADJUST.get(), String.valueOf(false));
- MechPeste.newInstance().startModule(commands);
+ } catch (RPCException | InterruptedException | StreamException e) {
+ cleanup();
+ setCurrentStatus(Bundle.getString("status_ready"));
}
+ }
- private void jettisonFairings() throws RPCException, InterruptedException {
- List fairings = getActiveVessel().getParts().getFairings();
- if (fairings.size() > 0) {
- setCurrentStatus(Bundle.getString("status_jettisoning_shields"));
- for (Fairing f : fairings) {
- if (f.getJettisoned()) {
- // Overly complicated way of getting the event from the button in the fairing
- // to jettison the fairing, since the jettison method doesn't work.
- String eventName = f.getPart().getModules().get(0).getEvents().get(0);
- f.getPart().getModules().get(0).triggerEvent(eventName);
- Thread.sleep(10000);
- }
- }
- }
- }
+ public void setHeading(float heading) {
+ final int MIN_HEADING = 0;
+ final int MAX_HEADING = 360;
+ this.heading = (float) Utilities.clamp(heading, MIN_HEADING, MAX_HEADING);
+ }
- private void openPanelsAndAntenna() throws RPCException, InterruptedException {
- getActiveVessel().getControl().setSolarPanels(true);
- getActiveVessel().getControl().setRadiators(true);
- getActiveVessel().getControl().setAntennas(true);
- }
+ public void setRoll(float roll) {
+ final int MIN_ROLL = 0;
+ final int MAX_ROLL = 360;
+ this.roll = (float) Utilities.clamp(roll, MIN_ROLL, MAX_ROLL);
+ }
- private double calculateCurrentPitch(double currentAltitude) {
- if (gravityCurveModel.equals(Module.QUADRATIC.get())) {
- return Utilities.easeInQuad(currentAltitude) * PITCH_UP;
- }
- if (gravityCurveModel.equals(Module.CUBIC.get())) {
- return Utilities.easeInCubic(currentAltitude) * PITCH_UP;
- }
- if (gravityCurveModel.equals(Module.SINUSOIDAL.get())) {
- return Utilities.easeInSine(currentAltitude) * PITCH_UP;
- }
- if (gravityCurveModel.equals(Module.EXPONENCIAL.get())) {
- return Utilities.easeInExpo(currentAltitude) * PITCH_UP;
- }
- return Utilities.easeInCirc(currentAltitude) * PITCH_UP;
- }
+ public void setFinalApoapsisAlt(float finalApoapsisAlt) {
+ final int MIN_FINAL_APOAPSIS = 10000;
+ final int MAX_FINAL_APOAPSIS = 2000000;
+ this.finalApoapsisAlt =
+ (float) Utilities.clamp(finalApoapsisAlt, MIN_FINAL_APOAPSIS, MAX_FINAL_APOAPSIS);
+ }
- private boolean isCurrentStageWithoutFuel() throws RPCException {
- for (Engine engine : getActiveVessel().getParts().getEngines()) {
- if (engine.getPart().getStage() == getActiveVessel().getControl().getCurrentStage()
- && !engine.getHasFuel()) {
- return true;
- }
- }
- return false;
+ private void initializeParameters() {
+ currentPitch = PITCH_UP;
+ setFinalApoapsisAlt(Float.parseFloat(commands.get(Module.APOAPSIS.get())));
+ setHeading(Float.parseFloat(commands.get(Module.DIRECTION.get())));
+ setRoll(Float.parseFloat(commands.get(Module.ROLL.get())));
+ maxTWR =
+ (float) Utilities.clamp(Float.parseFloat(commands.get(Module.MAX_TWR.get())), 1.2, 5.0);
+ gravityCurveModel = commands.get(Module.INCLINATION.get());
+ willOpenPanelsAndAntenna = Boolean.parseBoolean(commands.get(Module.OPEN_PANELS.get()));
+ willDecoupleStages = Boolean.parseBoolean(commands.get(Module.STAGE.get()));
+ thrControl = new ControlePID(vessel.getConnectionManager().getSpaceCenter());
+ thrControl.setOutput(0.0, 1.0);
+ }
+
+ private void setupCallbacks() throws RPCException, StreamException {
+ apoapsisCallbackTag =
+ vessel.apoapsis.addCallback(
+ (apo) -> {
+ if (apo >= finalApoapsisAlt) {
+ targetApoapsisReached = true;
+ }
+ });
+ vessel.apoapsis.start();
+
+ pressureStream = vessel.connection.addStream(vessel.flightParameters, "getDynamicPressure");
+ pressureCallbackTag =
+ pressureStream.addCallback(
+ (pressure) -> {
+ if (pressure <= 10) {
+ dynamicPressureLowEnough = true;
+ }
+ });
+ pressureStream.start();
+ }
+
+ private void handleLiftoff() {
+ try {
+ if (!isRunning()) {
+ cleanup();
+ return;
+ }
+ switch (liftoffMode) {
+ case GRAVITY_TURN:
+ gravityTurn();
+ break;
+ case FINALIZE_ORBIT:
+ finalizeOrbit();
+ break;
+ case CIRCULARIZE:
+ circularizeOrbitOnApoapsis();
+ stop();
+ break;
+ }
+ } catch (RPCException | StreamException | InterruptedException e) {
+ System.err.println("Liftoff error: " + e.getMessage());
+ cleanup();
}
+ }
+
+ private void gravityTurn() throws RPCException, StreamException, InterruptedException {
+ if (currentPitch > 1 && !targetApoapsisReached) {
+ double altitudeProgress =
+ Utilities.remap(startCurveAlt, finalApoapsisAlt, 1, 0.01, vessel.altitude.get(), false);
+ currentPitch = (float) (calculateCurrentPitch(altitudeProgress));
+ double currentMaxTWR = calculateTWRBasedOnPressure(currentPitch);
+ vessel.ap.setTargetPitch(currentPitch);
+ double throttleValue =
+ Math.min(
+ thrControl.calculate(vessel.apoapsis.get() / finalApoapsisAlt * 1000, 1000),
+ vessel.getMaxThrottleForTWR(currentMaxTWR));
+ vessel.throttle(Utilities.clamp(throttleValue, 0.05, 1.0));
- public float getHeading() {
- return heading;
+ if (willDecoupleStages && isCurrentStageWithoutFuel()) {
+ vessel.decoupleStage();
+ }
+ setCurrentStatus(
+ String.format(Bundle.getString("status_liftoff_inclination") + " %.1f", currentPitch));
+ } else {
+ vessel.throttle(0);
+ liftoffMode = LIFTOFF_MODE.FINALIZE_ORBIT;
}
+ }
- public void setHeading(float heading) {
- final int MIN_HEADING = 0;
- final int MAX_HEADING = 360;
- this.heading = (float) Utilities.clamp(heading, MIN_HEADING, MAX_HEADING);
+ private void finalizeOrbit() throws RPCException, StreamException, InterruptedException {
+ if (!dynamicPressureLowEnough) {
+ setCurrentStatus(Bundle.getString("status_maintaining_until_orbit"));
+ vessel.getActiveVessel().getControl().setRCS(true);
+ navigation.aimAtPrograde();
+ vessel.throttle(thrControl.calculate(vessel.apoapsis.get() / finalApoapsisAlt * 1000, 1000));
+ } else {
+ vessel.throttle(0.0f);
+ if (willDecoupleStages) {
+ jettisonFairings();
+ }
+ if (willOpenPanelsAndAntenna) {
+ openPanelsAndAntenna();
+ }
+ vessel.apoapsis.removeCallback(apoapsisCallbackTag);
+ pressureStream.removeCallback(pressureCallbackTag);
+ liftoffMode = LIFTOFF_MODE.CIRCULARIZE;
}
+ }
- public float getFinalApoapsis() {
- return finalApoapsisAlt;
+ private void cleanup() {
+ try {
+ if (liftoffExecutor != null && !liftoffExecutor.isShutdown()) {
+ liftoffExecutor.shutdownNow();
+ }
+ vessel.apoapsis.removeCallback(apoapsisCallbackTag);
+ pressureStream.removeCallback(pressureCallbackTag);
+ pressureStream.remove();
+ vessel.ap.disengage();
+ vessel.throttle(0);
+ } catch (RPCException | NullPointerException e) {
+ // ignore
}
+ }
- public float getRoll() {
- return this.roll;
+ private double calculateTWRBasedOnPressure(float currentPitch) throws RPCException {
+ float currentPressure = vessel.flightParameters.getDynamicPressure();
+ if (currentPressure <= 10) {
+ return Utilities.remap(90.0, 0.0, maxTWR, 5.0, currentPitch, true);
}
+ return Utilities.remap(22000.0, 10.0, maxTWR, 5.0, currentPressure, true);
+ }
- public void setRoll(float roll) {
- final int MIN_ROLL = 0;
- final int MAX_ROLL = 360;
- this.roll = (float) Utilities.clamp(roll, MIN_ROLL, MAX_ROLL);
+ private void circularizeOrbitOnApoapsis() {
+ setCurrentStatus(Bundle.getString("status_planning_orbit"));
+ Map commands = new HashMap<>();
+ commands.put(Module.MODULO.get(), Module.MANEUVER.get());
+ commands.put(Module.FUNCTION.get(), Module.APOAPSIS.get());
+ commands.put(Module.FINE_ADJUST.get(), String.valueOf(false));
+ vessel.getVesselManager().startModule(commands);
+ }
+
+ private void jettisonFairings() throws RPCException, InterruptedException {
+ List fairings = vessel.getActiveVessel().getParts().getFairings();
+ if (fairings.size() > 0) {
+ setCurrentStatus(Bundle.getString("status_jettisoning_shields"));
+ for (Fairing f : fairings) {
+ if (f.getJettisoned()) {
+ String eventName = f.getPart().getModules().get(0).getEvents().get(0);
+ f.getPart().getModules().get(0).triggerEvent(eventName);
+ Thread.sleep(5000);
+ }
+ }
}
+ }
- private void setGravityCurveModel(String model) {
- this.gravityCurveModel = model;
+ private void openPanelsAndAntenna() throws RPCException, InterruptedException {
+ vessel.getActiveVessel().getControl().setSolarPanels(true);
+ vessel.getActiveVessel().getControl().setRadiators(true);
+ vessel.getActiveVessel().getControl().setAntennas(true);
+ }
+
+ private double calculateCurrentPitch(double currentAltitude) {
+ if (gravityCurveModel.equals(Module.QUADRATIC.get())) {
+ return Utilities.easeInQuad(currentAltitude) * PITCH_UP;
+ }
+ if (gravityCurveModel.equals(Module.CUBIC.get())) {
+ return Utilities.easeInCubic(currentAltitude) * PITCH_UP;
+ }
+ if (gravityCurveModel.equals(Module.SINUSOIDAL.get())) {
+ return Utilities.easeInSine(currentAltitude) * PITCH_UP;
+ }
+ if (gravityCurveModel.equals(Module.EXPONENCIAL.get())) {
+ return Utilities.easeInExpo(currentAltitude) * PITCH_UP;
}
+ return Utilities.easeInCirc(currentAltitude) * PITCH_UP;
+ }
- public void setFinalApoapsisAlt(float finalApoapsisAlt) {
- final int MIN_FINAL_APOAPSIS = 10000;
- final int MAX_FINAL_APOAPSIS = 2000000;
- this.finalApoapsisAlt = (float) Utilities.clamp(finalApoapsisAlt, MIN_FINAL_APOAPSIS, MAX_FINAL_APOAPSIS);
+ private boolean isCurrentStageWithoutFuel() throws RPCException {
+ for (Engine engine : vessel.getActiveVessel().getParts().getEngines()) {
+ if (engine.getPart().getStage() == vessel.getActiveVessel().getControl().getCurrentStage()
+ && !engine.getHasFuel()) {
+ return true;
+ }
}
+ return false;
+ }
}
diff --git a/src/main/java/com/pesterenan/controllers/ManeuverController.java b/src/main/java/com/pesterenan/controllers/ManeuverController.java
index 40356e9..8ce85aa 100644
--- a/src/main/java/com/pesterenan/controllers/ManeuverController.java
+++ b/src/main/java/com/pesterenan/controllers/ManeuverController.java
@@ -1,21 +1,18 @@
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.model.ActiveVessel;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.Attributes;
import com.pesterenan.utils.ControlePID;
import com.pesterenan.utils.Module;
import com.pesterenan.utils.Navigation;
import com.pesterenan.utils.Vector;
-import com.pesterenan.views.RunManeuverJPanel;
-
+import com.pesterenan.views.MainGui;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import krpc.client.RPCException;
import krpc.client.Stream;
import krpc.client.StreamException;
@@ -26,526 +23,695 @@
import krpc.client.services.SpaceCenter.ReferenceFrame;
import krpc.client.services.SpaceCenter.Vessel;
import krpc.client.services.SpaceCenter.VesselSituation;
+import org.javatuples.Triplet;
public class ManeuverController extends Controller {
- public final static float CONST_GRAV = 9.81f;
- private ControlePID ctrlRCS;
- private ControlePID ctrlManeuver;
- private Navigation navigation;
- private boolean fineAdjustment;
- private double lowOrbitAltitude;
-
- public ManeuverController(Map commands) {
- super();
- this.commands = commands;
- this.navigation = new Navigation(getActiveVessel());
- initializeParameters();
+ enum Compare {
+ INC,
+ AP,
+ PE
+ }
+
+ private enum RendezvousPhase {
+ SETUP,
+ CHECK_ANGULAR_DIFFERENCE,
+ ADJUST_PERIAPSIS,
+ ADJUST_APOAPSIS,
+ ADJUST_UT,
+ DONE
+ }
+
+ private static class RendezvousState {
+ final Node maneuverNode;
+ RendezvousPhase phase = RendezvousPhase.SETUP;
+ double targetOrbitPosition;
+ double maneuverAP;
+ double maneuverPE;
+
+ RendezvousState(Node maneuverNode) {
+ this.maneuverNode = maneuverNode;
}
-
- private void initializeParameters() {
- 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(Module.FINE_ADJUST.get()));
- try {
- lowOrbitAltitude = new Attributes().getLowOrbitAltitude(currentBody.getName());
- System.out.println("lowOrbitAltitude: " + lowOrbitAltitude);
- } catch (RPCException e) {
- }
+ }
+
+ public static final float CONST_GRAV = 9.81f;
+ private ControlePID ctrlManeuver, ctrlRCS;
+
+ private Navigation navigation;
+ private boolean fineAdjustment;
+ private double lowOrbitAltitude;
+ private Stream headingErrorStream;
+ private Stream pitchErrorStream;
+ private Stream timeToNodeStream;
+
+ private Stream rollErrorStream;
+
+ private Stream> remainingBurnStream;
+
+ private double lastBurnDv = Double.MAX_VALUE;
+ private final Map commands;
+
+ public ManeuverController(ActiveVessel vessel, Map commands) {
+ super(vessel);
+ this.commands = commands;
+ this.navigation = new Navigation(vessel.getConnectionManager(), vessel.getActiveVessel());
+ initializeParameters();
+ }
+
+ @Override
+ public void run() {
+ try {
+ calculateManeuver();
+ if (!(commands.get(Module.FUNCTION.get()).equals(Module.RENDEZVOUS.get())
+ || commands.get(Module.FUNCTION.get()).equals(Module.LOW_ORBIT.get())
+ || commands.get(Module.FUNCTION.get()).equals(Module.ADJUST.get()))) {
+ executeNextManeuver();
+ }
+ } catch (ClassCastException | InterruptedException e) {
+ System.out.println("INFO: Interrompendo Controle de Manobras. Erro: " + e.getMessage());
+ cleanup();
}
-
- @Override
- public void run() {
- calculateManeuver();
- if (!(commands.get(Module.FUNCTION.get()).equals(Module.RENDEZVOUS.get())
- || commands.get(Module.FUNCTION.get()).equals(Module.LOW_ORBIT.get())
- || commands.get(Module.FUNCTION.get()).equals(Module.ADJUST.get()))) {
- executeNextManeuver();
- }
+ }
+
+ public void calculateManeuver() {
+ try {
+ vessel.tuneAutoPilot();
+ if (commands.get(Module.FUNCTION.get()).equals(Module.EXECUTE.get())) {
+ return;
+ }
+ if (vessel.getActiveVessel().getSituation() == VesselSituation.LANDED
+ || vessel.getActiveVessel().getSituation() == VesselSituation.SPLASHED) {
+ throw new InterruptedException();
+ }
+ if (commands.get(Module.FUNCTION.get()).equals(Module.ADJUST.get())) {
+ this.alignPlanesWithTargetVessel();
+ return;
+ }
+ if (commands.get(Module.FUNCTION.get()).equals(Module.RENDEZVOUS.get())) {
+ this.rendezvousWithTargetVessel();
+ return;
+ }
+ if (commands.get(Module.FUNCTION.get()).equals(Module.LOW_ORBIT.get())) {
+ biEllipticTransferToOrbit(
+ lowOrbitAltitude, vessel.getActiveVessel().getOrbit().getTimeToPeriapsis());
+ return;
+ }
+ double gravParameter = vessel.currentBody.getGravitationalParameter();
+ double startingAltitutde = 0, timeUntilAltitude = 0;
+ if (commands.get(Module.FUNCTION.get()).equals(Module.APOAPSIS.get())) {
+ startingAltitutde = vessel.getActiveVessel().getOrbit().getApoapsis();
+ timeUntilAltitude = vessel.getActiveVessel().getOrbit().getTimeToApoapsis();
+ }
+ if (commands.get(Module.FUNCTION.get()).equals(Module.PERIAPSIS.get())) {
+ startingAltitutde = vessel.getActiveVessel().getOrbit().getPeriapsis();
+ timeUntilAltitude = vessel.getActiveVessel().getOrbit().getTimeToPeriapsis();
+ }
+
+ double semiMajorAxis = vessel.getActiveVessel().getOrbit().getSemiMajorAxis();
+ double currentOrbitalVelocity =
+ Math.sqrt(gravParameter * ((2.0 / startingAltitutde) - (1.0 / semiMajorAxis)));
+ double targetOrbitalVelocity =
+ Math.sqrt(gravParameter * ((2.0 / startingAltitutde) - (1.0 / startingAltitutde)));
+ double maneuverDeltaV = targetOrbitalVelocity - currentOrbitalVelocity;
+ double[] deltaV = {maneuverDeltaV, 0, 0};
+ createManeuver(timeUntilAltitude, deltaV);
+ } catch (RPCException | InterruptedException e) {
+ setCurrentStatus(Bundle.getString("status_maneuver_not_possible"));
}
+ }
+
+ public void executeNextManeuver() throws InterruptedException {
+ try {
+ Node maneuverNode = vessel.getActiveVessel().getControl().getNodes().get(0);
+ double burnTime = calculateBurnTime(maneuverNode);
+ executeBurn(maneuverNode, burnTime);
+ } catch (UnsupportedOperationException e) {
+ System.err.println("Manobras ainda não desbloqueadas: " + e.getMessage());
+ setCurrentStatus(Bundle.getString("status_maneuver_not_unlocked"));
+ } catch (IndexOutOfBoundsException e) {
+ System.err.println("Erro de index: " + e.getMessage());
+ setCurrentStatus(Bundle.getString("status_maneuver_unavailable"));
+ } catch (RPCException e) {
+ System.err.println("Erro de Stream ou RPC: " + e.getMessage());
+ setCurrentStatus(Bundle.getString("status_data_unavailable"));
+ } catch (InterruptedException e) {
+ System.err.println("Cancelando executar manobra");
+ setCurrentStatus(Bundle.getString("status_couldnt_orient"));
+ throw e;
+ }
+ }
- private Node biEllipticTransferToOrbit(double targetAltitude, double timeToStart) {
- double[] totalDv = {0, 0, 0};
- try {
- Orbit currentOrbit = getActiveVessel().getOrbit();
- double startingRadius = currentOrbit.getApoapsis();
- double gravParameter = currentBody.getGravitationalParameter();
-
- // Delta-v required to leave the current orbit
- double deltaV1 = Math.sqrt(2 * gravParameter / startingRadius) - Math.sqrt(gravParameter / startingRadius);
-
- // Calculate the intermediate radius for the intermediate orbit
- double intermediateRadius = currentBody.getEquatorialRadius() + targetAltitude;
-
- // Delta-v required to enter the intermediate orbit
- double deltaV2 = Math.sqrt(gravParameter / intermediateRadius)
- - Math.sqrt(2 * gravParameter / intermediateRadius);
+ public void orientToManeuverNode(Node maneuverNode)
+ throws RPCException, StreamException, InterruptedException {
+ setCurrentStatus(Bundle.getString("status_orienting_ship"));
+ vessel.ap.engage();
+ vessel.ap.setReferenceFrame(maneuverNode.getReferenceFrame());
- // Calculate the final radius for the target orbit
- double targetRadius = currentBody.getEquatorialRadius() + targetAltitude;
+ // --- STAGE 1: ORIENT TO MANEUVER (PITCH/HEADING) ---
+ try {
+ setCurrentStatus(Bundle.getString("status_orienting_to_maneuver"));
+ vessel.ap.setTargetDirection(new Triplet<>(0.0, 1.0, 0.0)); // Prograde in node's frame
+ vessel.ap.setTargetRoll(Float.NaN); // Disable roll control
- // Delta-v required to leave the intermediate orbit and enter the target orbit
- double deltaV3 = Math.sqrt(2 * gravParameter / intermediateRadius)
- - Math.sqrt(gravParameter / intermediateRadius);
- double deltaV4 = Math.sqrt(gravParameter / targetRadius) - Math.sqrt(2 * gravParameter / targetRadius);
+ final CountDownLatch directionLatch = new CountDownLatch(1);
+ this.headingErrorStream = vessel.connection.addStream(vessel.ap, "getHeadingError");
+ this.pitchErrorStream = vessel.connection.addStream(vessel.ap, "getPitchError");
- // Total delta-v for the bi-elliptic transfer
- totalDv[0] = deltaV1 + deltaV2 + deltaV3 + deltaV4;
- } catch (RPCException e) {
- // Handle the exception
- }
- return createManeuver(timeToStart, totalDv);
- }
+ final Stream finalHeadingErrorStream = this.headingErrorStream;
+ final Stream finalPitchErrorStream = this.pitchErrorStream;
- public void calculateManeuver() {
- try {
- tuneAutoPilot();
- System.out.println(commands + " calculate maneuvers");
- if (commands.get(Module.FUNCTION.get()).equals(Module.EXECUTE.get())) {
- return;
- }
- if (getActiveVessel().getSituation() == VesselSituation.LANDED
- || getActiveVessel().getSituation() == VesselSituation.SPLASHED) {
- throw new InterruptedException();
- }
- if (commands.get(Module.FUNCTION.get()).equals(Module.ADJUST.get())) {
- this.alignPlanesWithTargetVessel();
- return;
- }
- if (commands.get(Module.FUNCTION.get()).equals(Module.RENDEZVOUS.get())) {
- this.rendezvousWithTargetVessel();
- return;
- }
- if (commands.get(Module.FUNCTION.get()).equals(Module.LOW_ORBIT.get())) {
- biEllipticTransferToOrbit(lowOrbitAltitude, getActiveVessel().getOrbit().getTimeToPeriapsis());
- return;
- }
- double gravParameter = currentBody.getGravitationalParameter();
- double startingAltitutde = 0, timeUntilAltitude = 0;
- if (commands.get(Module.FUNCTION.get()).equals(Module.APOAPSIS.get())) {
- startingAltitutde = getActiveVessel().getOrbit().getApoapsis();
- timeUntilAltitude = getActiveVessel().getOrbit().getTimeToApoapsis();
- }
- if (commands.get(Module.FUNCTION.get()).equals(Module.PERIAPSIS.get())) {
- startingAltitutde = getActiveVessel().getOrbit().getPeriapsis();
- timeUntilAltitude = getActiveVessel().getOrbit().getTimeToPeriapsis();
+ Runnable checkOrientation =
+ () -> {
+ try {
+ if (directionLatch.getCount() > 0
+ && Math.abs(finalHeadingErrorStream.get()) < 1
+ && Math.abs(finalPitchErrorStream.get()) < 1) {
+ directionLatch.countDown();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ directionLatch.countDown();
}
-
- double semiMajorAxis = getActiveVessel().getOrbit().getSemiMajorAxis();
- double currentOrbitalVelocity = Math
- .sqrt(gravParameter * ((2.0 / startingAltitutde) - (1.0 / semiMajorAxis)));
- double targetOrbitalVelocity = Math
- .sqrt(gravParameter * ((2.0 / startingAltitutde) - (1.0 / startingAltitutde)));
- double maneuverDeltaV = targetOrbitalVelocity - currentOrbitalVelocity;
- double[] deltaV = {maneuverDeltaV, 0, 0};
- createManeuver(timeUntilAltitude, deltaV);
- } catch (RPCException | InterruptedException e) {
- setCurrentStatus(Bundle.getString("status_maneuver_not_possible"));
- }
+ };
+
+ this.headingErrorStream.addCallback(v -> checkOrientation.run());
+ this.pitchErrorStream.addCallback(v -> checkOrientation.run());
+ this.headingErrorStream.start();
+ this.pitchErrorStream.start();
+
+ if (!directionLatch.await(60, TimeUnit.SECONDS)) {
+ System.err.println("Timeout waiting for direction stabilization.");
+ }
+ } finally {
+ if (this.headingErrorStream != null) {
+ this.headingErrorStream.remove();
+ }
+ if (this.pitchErrorStream != null) {
+ this.pitchErrorStream.remove();
+ }
}
- public void matchOrbitApoapsis() {
- try {
- Orbit targetOrbit = getTargetOrbit();
- System.out.println(targetOrbit.getApoapsis() + "-- APO");
- Node maneuver = biEllipticTransferToOrbit(targetOrbit.getApoapsis(),
- getActiveVessel().getOrbit().getTimeToPeriapsis());
- while (true) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
+ // --- STAGE 2: STABILIZE ROLL ---
+ try {
+ setCurrentStatus(Bundle.getString("status_stabilizing_roll"));
+ vessel.ap.setTargetRoll(0.0f);
+ final CountDownLatch rollLatch = new CountDownLatch(1);
+ this.rollErrorStream = vessel.connection.addStream(vessel.ap, "getRollError");
+ final Stream finalRollErrorStream = this.rollErrorStream;
+ final int[] rollCallbackTag = new int[1];
+ rollCallbackTag[0] =
+ finalRollErrorStream.addCallback(
+ error -> {
+ try {
+ if (Math.abs(error) < 1.0) {
+ rollLatch.countDown();
+ finalRollErrorStream.removeCallback(rollCallbackTag[0]);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ rollLatch.countDown();
}
- double currentDeltaApo = compareOrbitParameter(maneuver.getOrbit(), targetOrbit, Compare.AP);
- String deltaApoFormatted = String.format("%.2f", currentDeltaApo);
- System.out.println(deltaApoFormatted);
- if (deltaApoFormatted.equals(String.format("%.2f", 0.00))) {
- break;
- }
- double dvPrograde = maneuver.getPrograde();
- double ctrlOutput = ctrlManeuver.calculate(currentDeltaApo, 0);
-
- maneuver.setPrograde(dvPrograde - (ctrlOutput));
- Thread.sleep(25);
- }
- } catch (Exception e) {
- setCurrentStatus("Não foi possivel ajustar a inclinação");
- }
+ });
+ this.rollErrorStream.start();
+ if (!rollLatch.await(20, TimeUnit.SECONDS)) {
+ System.err.println("Timeout waiting for roll stabilization.");
+ }
+ } finally {
+ if (this.rollErrorStream != null) {
+ this.rollErrorStream.remove();
+ }
}
-
- private Node createManeuverAtClosestIncNode(Orbit targetOrbit) {
- double uTatClosestNode = 1;
- double[] dv = {0, 0, 0};
- try {
- double[] incNodesUt = getTimeToIncNodes(targetOrbit);
- uTatClosestNode = Math.min(incNodesUt[0], incNodesUt[1]) - getSpaceCenter().getUT();
- } catch (Exception ignored) {
+ }
+
+ public double calculateBurnTime(Node maneuverNode) {
+ try {
+ List engines = vessel.getActiveVessel().getParts().getEngines();
+ for (Engine engine : engines) {
+ if (engine.getPart().getStage() == vessel.getActiveVessel().getControl().getCurrentStage()
+ && !engine.getActive()) {
+ engine.setActive(true);
}
- return createManeuver(uTatClosestNode, dv);
+ }
+ } catch (RPCException e) {
+ System.err.println("Não foi possível ativar os motores." + e.getMessage());
}
-
- private double[] getTimeToIncNodes(Orbit targetOrbit) throws RPCException {
- Orbit vesselOrbit = getActiveVessel().getOrbit();
- double ascendingNode = vesselOrbit.trueAnomalyAtAN(targetOrbit);
- double descendingNode = vesselOrbit.trueAnomalyAtDN(targetOrbit);
- return new double[]{vesselOrbit.uTAtTrueAnomaly(ascendingNode), vesselOrbit.uTAtTrueAnomaly(descendingNode)};
+ double burnDuration = 0;
+ try {
+ double thrust = vessel.getActiveVessel().getAvailableThrust();
+ double isp = vessel.getActiveVessel().getSpecificImpulse() * CONST_GRAV;
+ double totalMass = vessel.getActiveVessel().getMass();
+ double dryMass = totalMass / Math.exp(maneuverNode.getDeltaV() / isp);
+ double burnRatio = thrust / isp;
+ burnDuration = (totalMass - dryMass) / burnRatio;
+ } catch (RPCException e) {
+ System.err.println("Não foi possível calcular o tempo de queima." + e.getMessage());
}
-
- private void alignPlanesWithTargetVessel() {
- try {
- Vessel vessel = getActiveVessel();
- Orbit vesselOrbit = getActiveVessel().getOrbit();
- Orbit targetVesselOrbit = getSpaceCenter().getTargetVessel().getOrbit();
- boolean hasManeuverNodes = vessel.getControl().getNodes().size() > 0;
- System.out.println("hasManeuverNodes: " + hasManeuverNodes);
- if (!hasManeuverNodes) {
- RunManeuverJPanel.createManeuver();
+ setCurrentStatus("Tempo de Queima da Manobra: " + burnDuration + " segundos.");
+ return burnDuration;
+ }
+
+ public void executeBurn(Node maneuverNode, double burnDuration) throws InterruptedException {
+ try {
+ // 1. PRE-WARP ORIENTATION
+ orientToManeuverNode(maneuverNode);
+
+ // 2. WARP AND COUNTDOWN
+ // Wait until it's time to burn
+ final CountDownLatch timeToBurnLatch = new CountDownLatch(1);
+ timeToNodeStream = vessel.connection.addStream(maneuverNode, "getTimeTo");
+ timeToNodeStream.addCallback(
+ (time) -> {
+ // Countdown for the last 5 seconds of warp
+ double timeToWarp = time - (burnDuration / 2.0) - 30;
+ if (timeToWarp > 0) {
+ setCurrentStatus(String.format("Warping in: %.1f seconds...", timeToWarp));
+ return;
}
- java.util.List currentManeuvers = vessel.getControl().getNodes();
- Node currentManeuver = currentManeuvers.get(0);
- double[] incNodesUt = {vesselOrbit.uTAtTrueAnomaly(vesselOrbit.trueAnomalyAtAN(targetVesselOrbit)),
- vesselOrbit.uTAtTrueAnomaly(vesselOrbit.trueAnomalyAtDN(targetVesselOrbit))};
- boolean closestIsAN = incNodesUt[0] < incNodesUt[1];
- 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.calculate(currentInclination * 100, 0);
- currentManeuver.setNormal(currentManeuver.getNormal() + (closestIsAN ? ctrlOutput : -ctrlOutput));
- Thread.sleep(25);
+ // Countdown for ignition
+ double timeToBurnStart = time - (burnDuration / 2.0);
+ setCurrentStatus(
+ String.format(Bundle.getString("status_maneuver_ignition_in"), timeToBurnStart));
+ if (timeToBurnStart <= 0) {
+ try {
+ timeToBurnLatch.countDown();
+ timeToNodeStream.remove();
+ } catch (RPCException e) {
+ }
}
- } catch (Exception err) {
- System.err.println(err);
- }
- }
+ });
+ timeToNodeStream.start();
+
+ double burnStartTime = maneuverNode.getTimeTo() - (burnDuration / 2.0) - 30;
+ if (burnStartTime > 0) {
+ setCurrentStatus(Bundle.getString("status_maneuver_warp"));
+ vessel
+ .getConnectionManager()
+ .getSpaceCenter()
+ .warpTo(
+ (vessel.getConnectionManager().getSpaceCenter().getUT() + burnStartTime),
+ 100000,
+ 4);
+ }
+
+ // 2. ORIENT (AFTER WARP)
+ orientToManeuverNode(maneuverNode);
+
+ // 3. FINAL COUNTDOWN
+ while (timeToBurnLatch.getCount() > 0) {
+ if (Thread.interrupted()) throw new InterruptedException();
+ if (timeToBurnLatch.await(100, TimeUnit.MILLISECONDS)) break;
+ }
+
+ // 4. EXECUTE THE BURN
+ final CountDownLatch burnCompleteLatch = new CountDownLatch(1);
+ remainingBurnStream =
+ vessel.connection.addStream(
+ maneuverNode, "remainingBurnVector", maneuverNode.getReferenceFrame());
+ remainingBurnStream.addCallback(
+ (burn) -> {
+ try {
+ double burnDvLeft = burn.getValue1();
- private void rendezvousWithTargetVessel() {
- try {
- boolean hasManeuverNodes = getActiveVessel().getControl().getNodes().size() > 0;
- List currentManeuvers = getActiveVessel().getControl().getNodes();
- Node lastManeuverNode;
- double lastManeuverNodeUT = 60;
- if (hasManeuverNodes) {
- currentManeuvers = getActiveVessel().getControl().getNodes();
- lastManeuverNode = currentManeuvers.get(currentManeuvers.size() - 1);
- lastManeuverNodeUT += lastManeuverNode.getUT();
- RunManeuverJPanel.createManeuver(lastManeuverNodeUT);
- } else {
- RunManeuverJPanel.createManeuver();
- }
- currentManeuvers = getActiveVessel().getControl().getNodes();
- lastManeuverNode = currentManeuvers.get(currentManeuvers.size() - 1);
-
- Orbit activeVesselOrbit = getActiveVessel().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);
- }
- }
+ // SAFETY STOP: Check if dV is increasing
+ if (burnDvLeft > lastBurnDv + 0.1) { // Using a 0.1m/s tolerance
+ System.err.println("Maneuver failed: Delta-V increasing. Aborting burn.");
+ vessel.throttle(0);
+ burnCompleteLatch.countDown();
+ return;
+ }
+ lastBurnDv = burnDvLeft; // Update last known dV
- 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);
- }
- }
- 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);
+ if (burnDvLeft < (fineAdjustment ? 2 : 0.75)) {
+ burnCompleteLatch.countDown();
+ return;
+ }
+ navigation.aimAtManeuverNode(maneuverNode);
+ vessel.throttle(ctrlManeuver.calculate(0, burnDvLeft / 100.0));
+ } catch (Exception e) {
+ e.printStackTrace();
+ burnCompleteLatch.countDown();
}
- // 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) {
- }
+ });
+ remainingBurnStream.start();
+
+ setCurrentStatus(Bundle.getString("status_maneuver_executing"));
+ burnCompleteLatch.await();
+ vessel.throttle(0.0f);
+ remainingBurnStream.remove();
+
+ if (fineAdjustment) {
+ adjustManeuverWithRCS(maneuverNode);
+ }
+
+ vessel.ap.setReferenceFrame(vessel.surfaceReferenceFrame);
+ vessel.ap.disengage();
+ vessel.getActiveVessel().getControl().setSAS(true);
+ vessel.getActiveVessel().getControl().setRCS(false);
+ maneuverNode.remove();
+ setCurrentStatus(Bundle.getString("status_ready"));
+ } catch (RPCException | StreamException e) {
+ setCurrentStatus(Bundle.getString("status_data_unavailable"));
+ } catch (InterruptedException e) {
+ setCurrentStatus(Bundle.getString("status_maneuver_cancelled"));
+ throw e;
}
-
- private double compareOrbitParameter(Orbit maneuverOrbit, Orbit targetOrbit, Compare parameter) {
- double maneuverParameter;
- double targetParameter;
- double delta = 0;
- try {
- switch (parameter) {
- case INC :
- maneuverParameter = maneuverOrbit.getInclination();
- System.out.println(maneuverParameter + " maneuver");
- targetParameter = targetOrbit.getInclination();
- System.out.println(targetParameter + " target");
- delta = (maneuverParameter / targetParameter) * 10;
- break;
- case AP :
- maneuverParameter = Math.round(maneuverOrbit.getApoapsis() / 100000.0);
- targetParameter = Math.round(targetOrbit.getApoapsis() / 100000.0);
- delta = (targetParameter - maneuverParameter);
- break;
- case PE :
- maneuverParameter = Math.round(maneuverOrbit.getPeriapsis()) / 100.0;
- targetParameter = Math.round(targetOrbit.getPeriapsis()) / 100.0;
- delta = (targetParameter - maneuverParameter);
- break;
- default :
- break;
- }
-
- } catch (RPCException e) {
- e.printStackTrace();
- }
- return delta;
+ }
+
+ private void initializeParameters() {
+ ctrlRCS = new ControlePID(vessel.getConnectionManager().getSpaceCenter());
+ ctrlManeuver = new ControlePID(vessel.getConnectionManager().getSpaceCenter());
+ ctrlManeuver.setPIDValues(1, 0.001, 0.1);
+ ctrlManeuver.setOutput(0.1, 1.0);
+ ctrlRCS.setOutput(0.5, 1.0);
+ fineAdjustment = canFineAdjust(commands.get(Module.FINE_ADJUST.get()));
+ try {
+ lowOrbitAltitude = new Attributes().getLowOrbitAltitude(vessel.currentBody.getName());
+ } catch (RPCException e) {
}
-
- private Orbit getTargetOrbit() throws RPCException {
- if (getSpaceCenter().getTargetBody() != null) {
- return getSpaceCenter().getTargetBody().getOrbit();
- }
- if (getSpaceCenter().getTargetVessel() != null) {
- return getSpaceCenter().getTargetVessel().getOrbit();
- }
- return null;
+ }
+
+ private Node biEllipticTransferToOrbit(double targetAltitude, double timeToStart) {
+ double[] totalDv = {0, 0, 0};
+ try {
+ Orbit currentOrbit = vessel.getActiveVessel().getOrbit();
+ double startingRadius = currentOrbit.getApoapsis();
+ double gravParameter = vessel.currentBody.getGravitationalParameter();
+ double deltaV1 =
+ Math.sqrt(2 * gravParameter / startingRadius) - Math.sqrt(gravParameter / startingRadius);
+ double intermediateRadius = vessel.currentBody.getEquatorialRadius() + targetAltitude;
+ double deltaV2 =
+ Math.sqrt(gravParameter / intermediateRadius)
+ - Math.sqrt(2 * gravParameter / intermediateRadius);
+ double targetRadius = vessel.currentBody.getEquatorialRadius() + targetAltitude;
+ double deltaV3 =
+ Math.sqrt(2 * gravParameter / intermediateRadius)
+ - Math.sqrt(gravParameter / intermediateRadius);
+ double deltaV4 =
+ Math.sqrt(gravParameter / targetRadius) - Math.sqrt(2 * gravParameter / targetRadius);
+ totalDv[0] = deltaV1 + deltaV2 + deltaV3 + deltaV4;
+ } catch (RPCException e) {
+ System.err.println("ERRO: Cálculo de Transferência de Órbita" + e.getMessage());
}
-
- private Node createManeuver(double laterTime, double[] deltaV) {
- Node maneuverNode = null;
- try {
- getActiveVessel().getControl().addNode(getSpaceCenter().getUT() + laterTime, (float) deltaV[0],
- (float) deltaV[1], (float) deltaV[2]);
- List currentNodes = getActiveVessel().getControl().getNodes();
- maneuverNode = currentNodes.get(currentNodes.size() - 1);
- } catch (UnsupportedOperationException | RPCException e) {
- setCurrentStatus(Bundle.getString("status_maneuver_not_possible"));
- }
- return maneuverNode;
+ return createManeuver(timeToStart, totalDv);
+ }
+
+ private void alignPlanesWithTargetVessel() throws InterruptedException, RPCException {
+ final int[] utCallbackTag = new int[1];
+ try {
+ Vessel vesselObj = this.vessel.getActiveVessel();
+ Orbit vesselOrbit = this.vessel.getActiveVessel().getOrbit();
+ Orbit targetVesselOrbit =
+ this.vessel.getConnectionManager().getSpaceCenter().getTargetVessel().getOrbit();
+ if (vesselObj.getControl().getNodes().isEmpty()) {
+ MainGui.newInstance().getCreateManeuverPanel().createManeuver();
+ }
+ java.util.List currentManeuvers = vesselObj.getControl().getNodes();
+ Node currentManeuver = currentManeuvers.get(0);
+ double[] incNodesUt = {
+ vesselOrbit.uTAtTrueAnomaly(vesselOrbit.trueAnomalyAtAN(targetVesselOrbit)),
+ vesselOrbit.uTAtTrueAnomaly(vesselOrbit.trueAnomalyAtDN(targetVesselOrbit))
+ };
+ boolean closestIsAN = incNodesUt[0] < incNodesUt[1];
+ MainGui.newInstance()
+ .getCreateManeuverPanel()
+ .positionManeuverAt(closestIsAN ? "ascending" : "descending");
+
+ ctrlManeuver.setTimeSample(25);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ utCallbackTag[0] =
+ vessel.missionTime.addCallback(
+ (ut) -> {
+ try {
+ double currentInclination =
+ Math.toDegrees(
+ currentManeuver.getOrbit().relativeInclination(targetVesselOrbit));
+ if (currentInclination <= 0.05) {
+ latch.countDown();
+ return;
+ }
+ double ctrlOutput = ctrlManeuver.calculate(currentInclination * 100, 0);
+ currentManeuver.setNormal(
+ currentManeuver.getNormal() + (closestIsAN ? ctrlOutput : -ctrlOutput));
+ } catch (Exception e) {
+ e.printStackTrace();
+ latch.countDown();
+ }
+ });
+ latch.await(); // Wait until the alignment is done
+ } catch (Exception err) {
+ if (err instanceof InterruptedException) {
+ throw (InterruptedException) err;
+ }
+ System.err.println("Error aligning planes: " + err);
+ } finally {
+ vessel.missionTime.removeCallback(utCallbackTag[0]);
}
-
- public void executeNextManeuver() {
- try {
- Node maneuverNode = getActiveVessel().getControl().getNodes().get(0);
- double burnTime = calculateBurnTime(maneuverNode);
- orientToManeuverNode(maneuverNode);
- executeBurn(maneuverNode, burnTime);
- } catch (UnsupportedOperationException e) {
- setCurrentStatus(Bundle.getString("status_maneuver_not_unlocked"));
- } catch (IndexOutOfBoundsException e) {
- setCurrentStatus(Bundle.getString("status_maneuver_unavailable"));
- } catch (RPCException e) {
- setCurrentStatus(Bundle.getString("status_data_unavailable"));
- } catch (InterruptedException e) {
- setCurrentStatus(Bundle.getString("status_couldnt_orient"));
- }
+ }
+
+ private void rendezvousWithTargetVessel() throws InterruptedException, RPCException {
+ final int[] utCallbackTag = new int[1];
+ try {
+ List currentManeuvers = vessel.getActiveVessel().getControl().getNodes();
+ Node lastManeuverNode;
+ if (currentManeuvers.isEmpty()) {
+ MainGui.newInstance().getCreateManeuverPanel().createManeuver();
+ currentManeuvers = vessel.getActiveVessel().getControl().getNodes();
+ } else {
+ double lastManeuverNodeUT = 60 + currentManeuvers.get(currentManeuvers.size() - 1).getUT();
+ MainGui.newInstance().getCreateManeuverPanel().createManeuver(lastManeuverNodeUT);
+ currentManeuvers = vessel.getActiveVessel().getControl().getNodes();
+ }
+ lastManeuverNode = currentManeuvers.get(currentManeuvers.size() - 1);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ final RendezvousState state = new RendezvousState(lastManeuverNode);
+
+ utCallbackTag[0] =
+ vessel.missionTime.addCallback(
+ ut -> {
+ try {
+ updateRendezvousState(state, latch, utCallbackTag[0]);
+ } catch (Exception e) {
+ e.printStackTrace();
+ System.err.println("Error in rendezvous update: " + e);
+ latch.countDown();
+ }
+ });
+ latch.await();
+ } catch (Exception err) {
+ if (err instanceof InterruptedException) {
+ throw (InterruptedException) err;
+ }
+ System.err.println("Error during rendezvous: " + err);
+ } finally {
+ vessel.missionTime.removeCallback(utCallbackTag[0]);
}
-
- public void orientToManeuverNode(Node maneuverNode) throws InterruptedException, RPCException {
- setCurrentStatus(Bundle.getString("status_orienting_ship"));
- ap.engage();
- while (ap.getHeadingError() > 3 || ap.getPitchError() > 3) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- navigation.aimAtManeuver(maneuverNode);
- Thread.sleep(100);
+ }
+
+ private void updateRendezvousState(
+ RendezvousState state, CountDownLatch latch, int callbackTag)
+ throws RPCException, IOException {
+ Orbit targetVesselOrbit =
+ vessel.getConnectionManager().getSpaceCenter().getTargetVessel().getOrbit();
+ ReferenceFrame currentBodyRefFrame =
+ vessel.getActiveVessel().getOrbit().getBody().getNonRotatingReferenceFrame();
+
+ switch (state.phase) {
+ case SETUP:
+ ctrlManeuver.setPIDValues(1, 0.001, 0.01);
+ ctrlManeuver.setOutput(-100, 100);
+ state.phase = RendezvousPhase.CHECK_ANGULAR_DIFFERENCE;
+ break;
+
+ case CHECK_ANGULAR_DIFFERENCE:
+ double maneuverUT = state.maneuverNode.getUT();
+ double angularDiff =
+ calculatePhaseAngle(
+ state.maneuverNode.getOrbit().positionAt(maneuverUT, currentBodyRefFrame),
+ targetVesselOrbit.positionAt(maneuverUT, currentBodyRefFrame));
+ if (angularDiff < 0.005) {
+ state.phase = RendezvousPhase.DONE;
+ break;
}
-
- }
-
- public double calculateBurnTime(Node maneuverNode) throws RPCException {
-
- List engines = getActiveVessel().getParts().getEngines();
- for (Engine engine : engines) {
- if (engine.getPart().getStage() == getActiveVessel().getControl().getCurrentStage()
- && !engine.getActive()) {
- engine.setActive(true);
- }
+ state.targetOrbitPosition =
+ new Vector(targetVesselOrbit.positionAt(maneuverUT, currentBodyRefFrame)).magnitude();
+ state.maneuverAP = state.maneuverNode.getOrbit().getApoapsis();
+ state.maneuverPE = state.maneuverNode.getOrbit().getPeriapsis();
+
+ if (state.targetOrbitPosition < state.maneuverPE) {
+ state.phase = RendezvousPhase.ADJUST_PERIAPSIS;
+ } else if (state.targetOrbitPosition > state.maneuverAP) {
+ state.phase = RendezvousPhase.ADJUST_APOAPSIS;
+ } else {
+ state.phase = RendezvousPhase.ADJUST_UT;
}
- double thrust = getActiveVessel().getAvailableThrust();
- double isp = getActiveVessel().getSpecificImpulse() * CONST_GRAV;
- double totalMass = getActiveVessel().getMass();
- double dryMass = totalMass / Math.exp(maneuverNode.getDeltaV() / isp);
- double burnRatio = thrust / isp;
- double burnDuration = (totalMass - dryMass) / burnRatio;
-
- setCurrentStatus("Tempo de Queima da Manobra: " + burnDuration + " segundos");
- return burnDuration;
- }
+ break;
- public void executeBurn(Node maneuverNode, double burnDuration) {
- try {
- double burnStartTime = maneuverNode.getTimeTo() - (burnDuration / 2.0) - (fineAdjustment ? 5 : 0);
- setCurrentStatus(Bundle.getString("status_maneuver_warp"));
- if (burnStartTime > 30) {
- getSpaceCenter().warpTo((getSpaceCenter().getUT() + burnStartTime - 10), 100000, 4);
- }
- // Mostrar tempo de ignição:
- setCurrentStatus(String.format(Bundle.getString("status_maneuver_duration"), burnDuration));
- while (burnStartTime > 0) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- burnStartTime = Math.max(maneuverNode.getTimeTo() - (burnDuration / 2.0), 0.0);
- navigation.aimAtManeuver(maneuverNode);
- setCurrentStatus(String.format(Bundle.getString("status_maneuver_ignition_in"), burnStartTime));
- Thread.sleep(100);
- }
- // Executar a manobra:
- Stream> remainingBurn = getConnection().addStream(maneuverNode,
- "remainingBurnVector", maneuverNode.getReferenceFrame());
- setCurrentStatus(Bundle.getString("status_maneuver_executing"));
- while (maneuverNode != null) {
- double burnDvLeft = remainingBurn.get().getValue1();
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- if (burnDvLeft < (fineAdjustment ? 2 : 0.5)) {
- throttle(0.0f);
- break;
- }
- navigation.aimAtManeuver(maneuverNode);
- float limitValue = burnDvLeft > 100 ? 1000 : 100;
- throttle(ctrlManeuver.calculate(
- (maneuverNode.getDeltaV() - Math.floor(burnDvLeft)) / maneuverNode.getDeltaV() * limitValue,
- limitValue));
- Thread.sleep(25);
- }
- throttle(0.0f);
- if (fineAdjustment) {
- adjustManeuverWithRCS(remainingBurn);
- }
- ap.setReferenceFrame(surfaceReferenceFrame);
- ap.disengage();
- getActiveVessel().getControl().setSAS(true);
- getActiveVessel().getControl().setRCS(false);
- remainingBurn.remove();
- maneuverNode.remove();
- setCurrentStatus(Bundle.getString("status_ready"));
- } catch (StreamException | RPCException e) {
- setCurrentStatus(Bundle.getString("status_data_unavailable"));
- } catch (InterruptedException e) {
- setCurrentStatus(Bundle.getString("status_maneuver_cancelled"));
+ case ADJUST_PERIAPSIS:
+ if (Math.floor(state.targetOrbitPosition) == Math.floor(state.maneuverPE)) {
+ state.phase = RendezvousPhase.ADJUST_UT;
+ break;
}
- }
-
- private void adjustManeuverWithRCS(Stream> remainingDeltaV)
- throws RPCException, StreamException, InterruptedException {
- getActiveVessel().getControl().setRCS(true);
- while (Math.floor(remainingDeltaV.get().getValue1()) > 0.2) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- getActiveVessel().getControl()
- .setForward((float) ctrlRCS.calculate(-remainingDeltaV.get().getValue1() * 10, 0));
- Thread.sleep(25);
+ state.maneuverNode.setPrograde(
+ state.maneuverNode.getPrograde()
+ + ctrlManeuver.calculate(
+ state.maneuverPE / state.targetOrbitPosition * 1000, 1000));
+ state.maneuverPE = state.maneuverNode.getOrbit().getPeriapsis();
+ break;
+
+ case ADJUST_APOAPSIS:
+ if (Math.floor(state.targetOrbitPosition) == Math.floor(state.maneuverAP)) {
+ state.phase = RendezvousPhase.ADJUST_UT;
+ break;
}
- getActiveVessel().getControl().setForward(0);
+ state.maneuverNode.setPrograde(
+ state.maneuverNode.getPrograde()
+ + ctrlManeuver.calculate(
+ state.maneuverAP / state.targetOrbitPosition * 1000, 1000));
+ state.maneuverAP = state.maneuverNode.getOrbit().getApoapsis();
+ break;
+
+ case ADJUST_UT:
+ double maneuverUT_adjust = state.maneuverNode.getUT();
+ double angularDiff_adjust =
+ calculatePhaseAngle(
+ state.maneuverNode.getOrbit().positionAt(maneuverUT_adjust, currentBodyRefFrame),
+ targetVesselOrbit.positionAt(maneuverUT_adjust, currentBodyRefFrame));
+ state.maneuverNode.setUT(
+ state.maneuverNode.getUT() + ctrlManeuver.calculate(-angularDiff_adjust * 100, 0));
+ state.phase = RendezvousPhase.CHECK_ANGULAR_DIFFERENCE;
+ break;
+
+ case DONE:
+ latch.countDown();
+ break;
}
-
- private boolean canFineAdjust(String string) {
- if (string.equals("true")) {
- try {
- List rcsEngines = getActiveVessel().getParts().getRCS();
- if (rcsEngines.size() > 0) {
- for (RCS rcs : rcsEngines) {
- if (rcs.getHasFuel()) {
- return true;
- }
- }
+ }
+
+ private Node createManeuver(double laterTime, double[] deltaV) {
+ Node maneuverNode = null;
+ try {
+ vessel
+ .getActiveVessel()
+ .getControl()
+ .addNode(
+ vessel.getConnectionManager().getSpaceCenter().getUT() + laterTime,
+ (float) deltaV[0],
+ (float) deltaV[1],
+ (float) deltaV[2]);
+ List currentNodes = vessel.getActiveVessel().getControl().getNodes();
+ maneuverNode = currentNodes.get(currentNodes.size() - 1);
+ } catch (UnsupportedOperationException | RPCException e) {
+ setCurrentStatus(Bundle.getString("status_maneuver_not_possible"));
+ }
+ return maneuverNode;
+ }
+
+ private void cleanup() {
+ try {
+ if (headingErrorStream != null) headingErrorStream.remove();
+ if (pitchErrorStream != null) pitchErrorStream.remove();
+ if (rollErrorStream != null) rollErrorStream.remove();
+ if (timeToNodeStream != null) timeToNodeStream.remove();
+ if (remainingBurnStream != null) remainingBurnStream.remove();
+ if (vessel.ap != null) vessel.ap.disengage();
+ vessel.throttle(0);
+ } catch (RPCException | NullPointerException e) {
+ // ignore
+ }
+ }
+
+ private void adjustManeuverWithRCS(Node maneuverNode)
+ throws RPCException, StreamException, InterruptedException {
+ setCurrentStatus("Fine tuning with RCS...");
+ vessel.getActiveVessel().getControl().setRCS(true);
+ final CountDownLatch rcsLatch = new CountDownLatch(1);
+
+ Stream> rcsStream = null;
+ try {
+ rcsStream =
+ vessel.connection.addStream(
+ maneuverNode, "remainingBurnVector", maneuverNode.getReferenceFrame());
+ final Stream> finalRcsStream = rcsStream;
+ final int[] rcsCallbackTag = new int[1];
+
+ rcsCallbackTag[0] =
+ finalRcsStream.addCallback(
+ (burn) -> {
+ try {
+ double progradeDv = burn.getValue1();
+ if (progradeDv <= 0.1) {
+ rcsLatch.countDown();
+ finalRcsStream.removeCallback(rcsCallbackTag[0]);
+ return;
+ }
+ // Use the RCS PID controller to gently burn off remaining dV
+ vessel
+ .getActiveVessel()
+ .getControl()
+ .setForward((float) ctrlRCS.calculate(-progradeDv, 0));
+ } catch (Exception e) {
+ e.printStackTrace();
+ rcsLatch.countDown();
}
- return false;
- } catch (RPCException ignored) {
+ });
+ rcsStream.start();
+
+ // Wait for RCS burn to complete, with a timeout
+ if (!rcsLatch.await(60, TimeUnit.SECONDS)) {
+ System.err.println("Timeout during RCS fine tuning.");
+ }
+ } finally {
+ vessel.getActiveVessel().getControl().setForward(0);
+ if (rcsStream != null) {
+ rcsStream.remove();
+ }
+ }
+ }
+
+ private boolean canFineAdjust(String string) {
+ if ("true".equals(string)) {
+ try {
+ List rcsEngines = vessel.getActiveVessel().getParts().getRCS();
+ if (rcsEngines.size() > 0) {
+ for (RCS rcs : rcsEngines) {
+ if (rcs.getHasFuel()) {
+ return true;
}
+ }
}
return false;
+ } catch (RPCException e) {
+ System.err.println("ERRO: Ajuste fino de manobra." + e.getMessage());
+ }
}
-
- 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 = getActiveVessel().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
- }
-
+ return false;
+ }
+
+ private double calculatePhaseAngle(
+ Triplet startPos, Triplet endPos)
+ throws RPCException {
+ 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 = vessel.getActiveVessel().getOrbit().getSemiMajorAxis();
+ angularDifference =
+ targetPhaseAngle
+ + Math.PI
+ * (1
+ - (1 / (2 * Math.sqrt(2)))
+ * Math.sqrt(Math.pow((activeVesselSMA / targetOrbit + 1), 3)));
+
+ return Math.abs(angularDifference);
+ }
}
diff --git a/src/main/java/com/pesterenan/controllers/RoverController.java b/src/main/java/com/pesterenan/controllers/RoverController.java
index 64ad213..4fb2e9c 100644
--- a/src/main/java/com/pesterenan/controllers/RoverController.java
+++ b/src/main/java/com/pesterenan/controllers/RoverController.java
@@ -1,12 +1,21 @@
package com.pesterenan.controllers;
+import com.pesterenan.model.ActiveVessel;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.ControlePID;
import com.pesterenan.utils.Module;
import com.pesterenan.utils.PathFinding;
import com.pesterenan.utils.Utilities;
import com.pesterenan.utils.Vector;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import krpc.client.RPCException;
+import krpc.client.Stream;
import krpc.client.StreamException;
import krpc.client.services.SpaceCenter.ReferenceFrame;
import krpc.client.services.SpaceCenter.SolarPanel;
@@ -14,291 +23,396 @@
import org.javatuples.Pair;
import org.javatuples.Triplet;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import static com.pesterenan.MechPeste.getSpaceCenter;
-
public class RoverController extends Controller {
- private final ControlePID sterringCtrl = new ControlePID();
- private final ControlePID acelCtrl = new ControlePID();
- float distanceFromTargetLimit = 50;
- private float maxSpeed = 3;
- private ReferenceFrame roverReferenceFrame;
- private boolean isAutoRoverRunning;
- private PathFinding pathFinding;
- private Vector targetPoint = new Vector();
- private Vector roverDirection = new Vector();
- private MODE currentMode;
-
- public RoverController(Map commands) {
- super();
- this.commands = commands;
- initializeParameters();
+ private final ControlePID sterringCtrl = new ControlePID();
+ private final ControlePID acelCtrl = new ControlePID();
+ float distanceFromTargetLimit = 50;
+ private float maxSpeed = 3;
+ private ReferenceFrame roverReferenceFrame;
+ private PathFinding pathFinding;
+ private Vector targetPoint = new Vector();
+ private Vector roverDirection = new Vector();
+ private MODE currentMode;
+ private final Map commands;
+
+ private volatile double currentDistanceToTarget = 0;
+ private volatile float currentChargePercentage = 100;
+ private volatile float currentChargeAmount = 0;
+ private int distanceCallbackTag, chargeCallbackTag;
+ private Stream> positionStream;
+ private Stream chargeAmountStream;
+ private ScheduledExecutorService roverExecutor;
+
+ public RoverController(ActiveVessel vessel, Map commands) {
+ super(vessel);
+ this.commands = commands;
+ initializeParameters();
+ }
+
+ private void initializeParameters() {
+ try {
+ maxSpeed = Float.parseFloat(commands.get(Module.MAX_SPEED.get()));
+ roverReferenceFrame = vessel.getActiveVessel().getReferenceFrame();
+ roverDirection = new Vector(vessel.getActiveVessel().direction(roverReferenceFrame));
+ pathFinding = new PathFinding(vessel.getConnectionManager(), vessel.getVesselManager());
+ acelCtrl.setOutput(0, 1);
+ sterringCtrl.setOutput(-1, 1);
+ } catch (RPCException ignored) {
}
+ }
- private void initializeParameters() {
- try {
- maxSpeed = Float.parseFloat(commands.get(Module.MAX_SPEED.get()));
- roverReferenceFrame = getActiveVessel().getReferenceFrame();
- roverDirection = new Vector(getActiveVessel().direction(roverReferenceFrame));
- pathFinding = new PathFinding();
- acelCtrl.setOutput(0, 1);
- sterringCtrl.setOutput(-1, 1);
- isAutoRoverRunning = true;
- } catch (RPCException ignored) {
- }
+ private boolean isSolarPanelNotBroken(SolarPanel sp) {
+ try {
+ return sp.getState() != SolarPanelState.BROKEN;
+ } catch (RPCException e) {
+ return false;
}
-
- private boolean isSolarPanelNotBroken(SolarPanel sp) {
- try {
- return sp.getState() != SolarPanelState.BROKEN;
- } catch (RPCException e) {
- return false;
- }
- }
-
- @Override
- public void run() {
- if (commands.get(Module.MODULO.get()).equals(Module.ROVER.get())) {
- setTarget();
- driveRoverToTarget();
- }
- }
-
- private void setTarget() {
- try {
- if (commands.get(Module.ROVER_TARGET_TYPE.get()).equals(Module.MAP_MARKER.get())) {
- pathFinding.addWaypointsOnSameBody(commands.get(Module.MARKER_NAME.get()));
- setCurrentStatus("Calculando rota até o alvo...");
- pathFinding.buildPathToTarget(pathFinding.findNearestWaypoint());
- }
- if (commands.get(Module.ROVER_TARGET_TYPE.get()).equals(Module.TARGET_VESSEL.get())) {
- Vector targetVesselPosition = new Vector(
- getSpaceCenter().getTargetVessel().position(orbitalReferenceFrame));
- setCurrentStatus("Calculando rota até o alvo...");
- pathFinding.buildPathToTarget(targetVesselPosition);
- }
- } catch (RPCException | IOException | InterruptedException ignored) {
- }
- }
-
- private void changeControlMode() throws RPCException, IOException, StreamException, InterruptedException {
- switch (currentMode) {
- case DRIVE :
- driveRover();
- break;
- case CHARGING :
- rechargeRover();
- break;
- case NEXT_POINT :
- setNextPointInPath();
- break;
- }
+ }
+
+ @Override
+ public void run() {
+ if (commands.get(Module.MODULO.get()).equals(Module.ROVER.get())) {
+ setTarget();
+ currentMode = MODE.NEXT_POINT;
+ try {
+ setupCallbacks();
+ roverExecutor = Executors.newSingleThreadScheduledExecutor();
+ roverExecutor.scheduleAtFixedRate(this::roverStateMachine, 0, 100, TimeUnit.MILLISECONDS);
+ } catch (IOException | RPCException | StreamException e) {
+ cleanup();
+ }
}
-
- private void driveRoverToTarget() {
+ }
+
+ private void roverStateMachine() {
+ try {
+ if (!isRunning()) {
+ cleanup();
+ return;
+ }
+ changeControlMode();
+ if (isFarFromTarget()) {
+ currentMode = needToChargeBatteries() ? MODE.CHARGING : MODE.DRIVE;
+ } else { // Rover arrived at destiny
currentMode = MODE.NEXT_POINT;
- try {
- while (isAutoRoverRunning) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- changeControlMode();
- if (isFarFromTarget()) {
- currentMode = needToChargeBatteries() ? MODE.CHARGING : MODE.DRIVE;
- } else { // Rover arrived at destiny
- currentMode = MODE.NEXT_POINT;
- }
- Thread.sleep(100);
- }
- } catch (InterruptedException | RPCException | IOException | StreamException ignored) {
- try {
- getActiveVessel().getControl().setBrakes(true);
- pathFinding.removeDrawnPath();
- isAutoRoverRunning = false;
- setCurrentStatus(Bundle.getString("lbl_stat_ready"));
- } catch (RPCException ignored2) {
- }
- }
+ }
+ } catch (RPCException | IOException | StreamException | InterruptedException e) {
+ cleanup();
}
-
- private void setNextPointInPath() throws RPCException, IOException, InterruptedException {
- pathFinding.removePathsCurrentPoint();
- getActiveVessel().getControl().setBrakes(true);
- if (pathFinding.isPathToTargetEmpty()) {
- if (commands.get(Module.ROVER_TARGET_TYPE.get()).equals(Module.MAP_MARKER.get())) {
- pathFinding.removeWaypointFromList();
- if (pathFinding.isWaypointsToReachEmpty()) {
- throw new InterruptedException();
- }
- pathFinding.buildPathToTarget(pathFinding.findNearestWaypoint());
- }
-
- } else {
- targetPoint = pathFinding.getPathsFirstPoint();
- }
+ }
+
+ private void setupCallbacks() throws RPCException, IOException, StreamException {
+ positionStream =
+ vessel.connection.addStream(
+ vessel.getActiveVessel(), "position", vessel.orbitalReferenceFrame);
+ distanceCallbackTag =
+ positionStream.addCallback(
+ (pos) -> {
+ currentDistanceToTarget = Vector.distance(new Vector(pos), targetPoint);
+ });
+ positionStream.start();
+
+ chargeAmountStream =
+ vessel.connection.addStream(
+ vessel.getActiveVessel().getResources(), "amount", "ElectricCharge");
+ chargeCallbackTag =
+ chargeAmountStream.addCallback(
+ (amount) -> {
+ try {
+ currentChargeAmount = amount;
+ float totalCharge = vessel.getActiveVessel().getResources().max("ElectricCharge");
+ currentChargePercentage = (float) Math.ceil(amount * 100 / totalCharge);
+ } catch (RPCException e) {
+ }
+ });
+ chargeAmountStream.start();
+ }
+
+ private void setTarget() {
+ try {
+ if (commands.get(Module.ROVER_TARGET_TYPE.get()).equals(Module.MAP_MARKER.get())) {
+ pathFinding.addWaypointsOnSameBody(commands.get(Module.MARKER_NAME.get()));
+ setCurrentStatus("Calculando rota até o alvo...");
+ pathFinding.buildPathToTarget(pathFinding.findNearestWaypoint());
+ }
+ if (commands.get(Module.ROVER_TARGET_TYPE.get()).equals(Module.TARGET_VESSEL.get())) {
+ Vector targetVesselPosition =
+ new Vector(
+ vessel
+ .getConnectionManager()
+ .getSpaceCenter()
+ .getTargetVessel()
+ .position(vessel.orbitalReferenceFrame));
+ setCurrentStatus("Calculando rota até o alvo...");
+ pathFinding.buildPathToTarget(targetVesselPosition);
+ }
+ } catch (RPCException | IOException | InterruptedException ignored) {
}
-
- private boolean isFarFromTarget() throws RPCException {
- double distance = Vector.distance(new Vector(getActiveVessel().position(orbitalReferenceFrame)), targetPoint);
- return distance > distanceFromTargetLimit;
+ }
+
+ private void changeControlMode()
+ throws RPCException, IOException, StreamException, InterruptedException {
+ switch (currentMode) {
+ case DRIVE:
+ driveRover();
+ break;
+ case CHARGING:
+ rechargeRover();
+ break;
+ case NEXT_POINT:
+ setNextPointInPath();
+ break;
}
-
- private boolean needToChargeBatteries() throws RPCException, IOException, StreamException, InterruptedException {
- float totalCharge = getActiveVessel().getResources().max("ElectricCharge");
- float currentCharge = getActiveVessel().getResources().amount("ElectricCharge");
- float minChargeLevel = 10.0f;
- float chargePercentage = (float) Math.ceil(currentCharge * 100 / totalCharge);
- return (chargePercentage < minChargeLevel);
+ }
+
+ private void cleanup() {
+ try {
+ if (roverExecutor != null && !roverExecutor.isShutdown()) {
+ roverExecutor.shutdownNow();
+ }
+ vessel.getActiveVessel().getControl().setBrakes(true);
+ pathFinding.removeDrawnPath();
+ if (positionStream != null) {
+ positionStream.removeCallback(distanceCallbackTag);
+ positionStream.remove();
+ }
+ if (chargeAmountStream != null) {
+ chargeAmountStream.removeCallback(chargeCallbackTag);
+ chargeAmountStream.remove();
+ }
+ setCurrentStatus(Bundle.getString("lbl_stat_ready"));
+ } catch (RPCException ignored) {
}
-
- private void rechargeRover() throws RPCException, StreamException, InterruptedException {
-
- float totalCharge = getActiveVessel().getResources().max("ElectricCharge");
- float currentCharge = getActiveVessel().getResources().amount("ElectricCharge");
-
- setRoverThrottle(0);
- getActiveVessel().getControl().setLights(false);
- getActiveVessel().getControl().setBrakes(true);
-
- if (horizontalVelocity.get() < 1 && getActiveVessel().getControl().getBrakes()) {
- Thread.sleep(1000);
- double chargeTime;
- double totalEnergyFlow = 0;
- List solarPanels = getActiveVessel().getParts().getSolarPanels().stream()
- .filter(this::isSolarPanelNotBroken).collect(Collectors.toList());
-
- for (SolarPanel sp : solarPanels) {
- totalEnergyFlow += sp.getEnergyFlow();
- }
- chargeTime = ((totalCharge - currentCharge) / totalEnergyFlow);
- setCurrentStatus("Segundos de Carga: " + chargeTime);
- if (chargeTime < 1 || chargeTime > 21600) {
- chargeTime = 3600;
- }
- getSpaceCenter().warpTo((getSpaceCenter().getUT() + chargeTime), 10000, 4);
- getActiveVessel().getControl().setLights(true);
+ }
+
+ private void setNextPointInPath() throws RPCException, IOException {
+ pathFinding.removePathsCurrentPoint();
+ vessel.getActiveVessel().getControl().setBrakes(true);
+ if (pathFinding.isPathToTargetEmpty()) {
+ if (commands.get(Module.ROVER_TARGET_TYPE.get()).equals(Module.MAP_MARKER.get())) {
+ pathFinding.removeWaypointFromList();
+ if (pathFinding.isWaypointsToReachEmpty()) {
+ stop();
+ return;
}
- }
-
- private void driveRover() throws RPCException, IOException, StreamException {
- Vector targetDirection = posSurfToRover(posOrbToSurf(targetPoint)).normalize();
- Vector radarSourcePosition = posRoverToSurf(
- new Vector(getActiveVessel().position(roverReferenceFrame)).sum(new Vector(0.0, 3.0, 0.0)));
-
- double roverAngle = (roverDirection.heading());
- // fazer um raycast pra frente e verificar a distancia
- double obstacleAhead = pathFinding.raycastDistance(radarSourcePosition, transformDirection(roverDirection),
- surfaceReferenceFrame, 30);
- double steeringPower = Utilities.remap(3, 30, 0.1, 0.5, obstacleAhead, true);
- // usar esse valor pra muiltiplicar a direcao alvo
- double targetAndRadarAngle = (targetDirection.multiply(steeringPower)
- .sum(directionFromRadar(getActiveVessel().boundingBox(roverReferenceFrame))).normalize()).heading();
- double deltaAngle = Math.abs(targetAndRadarAngle - roverAngle);
- getActiveVessel().getControl().setSAS(deltaAngle < 1);
- // Control Rover Throttle
- setRoverThrottle(acelCtrl.calculate(horizontalVelocity.get() / maxSpeed * 50, 50));
- // Control Rover Steering
- if (deltaAngle > 1) {
- setRoverSteering(sterringCtrl.calculate(roverAngle / (targetAndRadarAngle) * 100, 100));
- } else {
- setRoverSteering(0.0f);
+ try {
+ pathFinding.buildPathToTarget(pathFinding.findNearestWaypoint());
+ } catch (InterruptedException e) {
+ stop();
}
- setCurrentStatus("Driving... " + deltaAngle);
- }
+ }
- private Vector directionFromRadar(
- Pair,Triplet> boundingBox)
- throws RPCException, IOException {
- // PONTO REF ROVER: X = DIREITA, Y = FRENTE, Z = BAIXO;
- // Bounding box points from rover (LBU: Left, Back, Up - RFD: Right, Front,
- // Down):
- Vector LBU = new Vector(boundingBox.getValue0());
- Vector RFD = new Vector(boundingBox.getValue1());
-
- // Pre-calculated bbox positions
- Vector lateralLeft = new Vector(LBU.x, LBU.y * 0.5 + RFD.y * 0.5, LBU.z * 0.5 + RFD.z * 0.5);
- Vector latFrontLeft = new Vector(LBU.x, RFD.y * 0.5, LBU.z * 0.5 + RFD.z * 0.5);
- Vector frontLeft = new Vector(LBU.x, RFD.y, LBU.z * 0.5 + RFD.z * 0.5);
- Vector frontLeft2 = new Vector(LBU.x * 0.5, RFD.y, LBU.z * 0.5 + RFD.z * 0.5);
- Vector front = new Vector(LBU.x * 0.5 + RFD.x * 0.5, RFD.y, LBU.z * 0.5 + RFD.z * 0.5);
- Vector frontRight2 = new Vector(RFD.x * 0.5, RFD.y, LBU.z * 0.5 + RFD.z * 0.5);
- Vector frontRight = new Vector(RFD.x, RFD.y, LBU.z * 0.5 + RFD.z * 0.5);
- Vector latFrontRight = new Vector(RFD.x, RFD.y * 0.5, LBU.z * 0.5 + RFD.z * 0.5);
- Vector lateralRight = new Vector(RFD.x, LBU.y * 0.5 + RFD.y * 0.5, LBU.z * 0.5 + RFD.z * 0.5);
-
- // Pre-calculated bbox directions
- Vector lateralLeftAngle = new Vector(-Math.sin(Math.toRadians(90)), Math.cos(Math.toRadians(90)), 0.0);
- Vector latFrontLeftAngle = new Vector(-Math.sin(Math.toRadians(67.5)), Math.cos(Math.toRadians(67.5)), 0.0);
- Vector frontLeftAngle = new Vector(-Math.sin(Math.toRadians(45)), Math.cos(Math.toRadians(45)), 0.0);
- Vector frontLeftAngle2 = new Vector(-Math.sin(Math.toRadians(22.5)), Math.cos(Math.toRadians(22.5)), 0.0);
- Vector frontAngle = new Vector(0.0, 1.0, 0.0);
- Vector frontRightAngle2 = new Vector(Math.sin(Math.toRadians(22.5)), Math.cos(Math.toRadians(22.5)), 0.0);
- Vector frontRightAngle = new Vector(Math.sin(Math.toRadians(45)), Math.cos(Math.toRadians(45)), 0.0);
- Vector latFrontRightAngle = new Vector(Math.sin(Math.toRadians(67.5)), Math.cos(Math.toRadians(67.5)), 0.0);
- Vector lateralRightAngle = new Vector(Math.sin(Math.toRadians(90)), Math.cos(Math.toRadians(90)), 0.0);
-
- // Raytracing distance from points:
- Vector lateralLeftRay = calculateRaycastDirection(lateralLeft, lateralLeftAngle, 15);
- Vector lateralFrontLeftRay = calculateRaycastDirection(latFrontLeft, latFrontLeftAngle, 19);
- Vector frontLeftRay = calculateRaycastDirection(frontLeft, frontLeftAngle, 23);
- Vector frontLeftRay2 = calculateRaycastDirection(frontLeft2, frontLeftAngle2, 27);
- Vector frontRay = calculateRaycastDirection(front, frontAngle, 35);
- Vector frontRightRay2 = calculateRaycastDirection(frontRight2, frontRightAngle2, 27);
- Vector frontRightRay = calculateRaycastDirection(frontRight, frontRightAngle, 23);
- Vector lateralFrontRightRay = calculateRaycastDirection(latFrontRight, latFrontRightAngle, 19);
- Vector lateralRightRay = calculateRaycastDirection(lateralRight, lateralRightAngle, 15);
-
- Vector calculatedDirection = new Vector().sum(lateralLeftRay).sum(lateralFrontLeftRay).sum(frontLeftRay)
- .sum(frontLeftRay2).sum(frontRay).sum(frontRightRay2).sum(frontRightRay).sum(lateralFrontRightRay)
- .sum(lateralRightRay);
-
- return (calculatedDirection.normalize());
+ } else {
+ targetPoint = pathFinding.getPathsFirstPoint();
}
-
- private Vector calculateRaycastDirection(Vector point, Vector direction, double distance) throws RPCException {
- double raycast = pathFinding.raycastDistance(posRoverToSurf(point), transformDirection(direction),
- surfaceReferenceFrame, distance);
- return direction.multiply(raycast);
- }
-
- private Vector transformDirection(Vector vector) throws RPCException {
- return new Vector(
- getSpaceCenter().transformDirection(vector.toTriplet(), roverReferenceFrame, surfaceReferenceFrame));
- }
-
- private Vector posSurfToRover(Vector vector) throws RPCException {
- return new Vector(
- getSpaceCenter().transformPosition(vector.toTriplet(), surfaceReferenceFrame, roverReferenceFrame));
- }
-
- private Vector posRoverToSurf(Vector vector) throws RPCException {
- return new Vector(
- getSpaceCenter().transformPosition(vector.toTriplet(), roverReferenceFrame, surfaceReferenceFrame));
+ }
+
+ private boolean isFarFromTarget() {
+ return currentDistanceToTarget > distanceFromTargetLimit;
+ }
+
+ private boolean needToChargeBatteries() {
+ float minChargeLevel = 10.0f;
+ return (currentChargePercentage < minChargeLevel);
+ }
+
+ private void rechargeRover() throws RPCException, StreamException, InterruptedException {
+
+ float totalCharge = vessel.getActiveVessel().getResources().max("ElectricCharge");
+
+ setRoverThrottle(0);
+ vessel.getActiveVessel().getControl().setLights(false);
+ vessel.getActiveVessel().getControl().setBrakes(true);
+
+ if (vessel.horizontalVelocity.get() < 1 && vessel.getActiveVessel().getControl().getBrakes()) {
+ Thread.sleep(1000);
+ double chargeTime;
+ double totalEnergyFlow = 0;
+ List solarPanels =
+ vessel.getActiveVessel().getParts().getSolarPanels().stream()
+ .filter(this::isSolarPanelNotBroken)
+ .collect(Collectors.toList());
+
+ for (SolarPanel sp : solarPanels) {
+ totalEnergyFlow += sp.getEnergyFlow();
+ }
+ chargeTime = ((totalCharge - currentChargeAmount) / totalEnergyFlow);
+ setCurrentStatus("Segundos de Carga: " + chargeTime);
+ if (chargeTime < 1 || chargeTime > 21600) {
+ chargeTime = 3600;
+ }
+ vessel
+ .getConnectionManager()
+ .getSpaceCenter()
+ .warpTo((vessel.getConnectionManager().getSpaceCenter().getUT() + chargeTime), 10000, 4);
+ vessel.getActiveVessel().getControl().setLights(true);
}
-
- private Vector posOrbToSurf(Vector vector) throws RPCException {
- return new Vector(
- getSpaceCenter().transformPosition(vector.toTriplet(), orbitalReferenceFrame, surfaceReferenceFrame));
+ }
+
+ private void driveRover() throws RPCException, IOException, StreamException {
+ Vector targetDirection = posSurfToRover(posOrbToSurf(targetPoint)).normalize();
+ Vector radarSourcePosition =
+ posRoverToSurf(
+ new Vector(vessel.getActiveVessel().position(roverReferenceFrame))
+ .sum(new Vector(0.0, 3.0, 0.0)));
+
+ double roverAngle = (roverDirection.heading());
+ // fazer um raycast pra frente e verificar a distancia
+ double obstacleAhead =
+ pathFinding.raycastDistance(
+ radarSourcePosition,
+ transformDirection(roverDirection),
+ vessel.surfaceReferenceFrame,
+ 30);
+ double steeringPower = Utilities.remap(3, 30, 0.1, 0.5, obstacleAhead, true);
+ // usar esse valor pra muiltiplicar a direcao alvo
+ double targetAndRadarAngle =
+ (targetDirection
+ .multiply(steeringPower)
+ .sum(directionFromRadar(vessel.getActiveVessel().boundingBox(roverReferenceFrame)))
+ .normalize())
+ .heading();
+ double deltaAngle = Math.abs(targetAndRadarAngle - roverAngle);
+ vessel.getActiveVessel().getControl().setSAS(deltaAngle < 1);
+ // Control Rover Throttle
+ setRoverThrottle(acelCtrl.calculate(vessel.horizontalVelocity.get() / maxSpeed * 50, 50));
+ // Control Rover Steering
+ if (deltaAngle > 1) {
+ setRoverSteering(sterringCtrl.calculate(roverAngle / (targetAndRadarAngle) * 100, 100));
+ } else {
+ setRoverSteering(0.0f);
}
-
- private void setRoverThrottle(double throttle) throws RPCException, StreamException {
- if (horizontalVelocity.get() < (maxSpeed * 1.01)) {
- getActiveVessel().getControl().setBrakes(false);
- getActiveVessel().getControl().setWheelThrottle((float) throttle);
- } else {
- getActiveVessel().getControl().setBrakes(true);
- }
+ setCurrentStatus("Driving... " + deltaAngle);
+ }
+
+ private Vector directionFromRadar(
+ Pair, Triplet> boundingBox)
+ throws RPCException, IOException {
+ // PONTO REF ROVER: X = DIREITA, Y = FRENTE, Z = BAIXO;
+ // Bounding box points from rover (LBU: Left, Back, Up - RFD: Right, Front,
+ // Down):
+ Vector LBU = new Vector(boundingBox.getValue0());
+ Vector RFD = new Vector(boundingBox.getValue1());
+
+ // Pre-calculated bbox positions
+ Vector lateralLeft = new Vector(LBU.x, LBU.y * 0.5 + RFD.y * 0.5, LBU.z * 0.5 + RFD.z * 0.5);
+ Vector latFrontLeft = new Vector(LBU.x, RFD.y * 0.5, LBU.z * 0.5 + RFD.z * 0.5);
+ Vector frontLeft = new Vector(LBU.x, RFD.y, LBU.z * 0.5 + RFD.z * 0.5);
+ Vector frontLeft2 = new Vector(LBU.x * 0.5, RFD.y, LBU.z * 0.5 + RFD.z * 0.5);
+ Vector front = new Vector(LBU.x * 0.5 + RFD.x * 0.5, RFD.y, LBU.z * 0.5 + RFD.z * 0.5);
+ Vector frontRight2 = new Vector(RFD.x * 0.5, RFD.y, LBU.z * 0.5 + RFD.z * 0.5);
+ Vector frontRight = new Vector(RFD.x, RFD.y, LBU.z * 0.5 + RFD.z * 0.5);
+ Vector latFrontRight = new Vector(RFD.x, RFD.y * 0.5, LBU.z * 0.5 + RFD.z * 0.5);
+ Vector lateralRight = new Vector(RFD.x, LBU.y * 0.5 + RFD.y * 0.5, LBU.z * 0.5 + RFD.z * 0.5);
+
+ // Pre-calculated bbox directions
+ Vector lateralLeftAngle =
+ new Vector(-Math.sin(Math.toRadians(90)), Math.cos(Math.toRadians(90)), 0.0);
+ Vector latFrontLeftAngle =
+ new Vector(-Math.sin(Math.toRadians(67.5)), Math.cos(Math.toRadians(67.5)), 0.0);
+ Vector frontLeftAngle =
+ new Vector(-Math.sin(Math.toRadians(45)), Math.cos(Math.toRadians(45)), 0.0);
+ Vector frontLeftAngle2 =
+ new Vector(-Math.sin(Math.toRadians(22.5)), Math.cos(Math.toRadians(22.5)), 0.0);
+ Vector frontAngle = new Vector(0.0, 1.0, 0.0);
+ Vector frontRightAngle2 =
+ new Vector(Math.sin(Math.toRadians(22.5)), Math.cos(Math.toRadians(22.5)), 0.0);
+ Vector frontRightAngle =
+ new Vector(Math.sin(Math.toRadians(45)), Math.cos(Math.toRadians(45)), 0.0);
+ Vector latFrontRightAngle =
+ new Vector(Math.sin(Math.toRadians(67.5)), Math.cos(Math.toRadians(67.5)), 0.0);
+ Vector lateralRightAngle =
+ new Vector(Math.sin(Math.toRadians(90)), Math.cos(Math.toRadians(90)), 0.0);
+
+ // Raytracing distance from points:
+ Vector lateralLeftRay = calculateRaycastDirection(lateralLeft, lateralLeftAngle, 15);
+ Vector lateralFrontLeftRay = calculateRaycastDirection(latFrontLeft, latFrontLeftAngle, 19);
+ Vector frontLeftRay = calculateRaycastDirection(frontLeft, frontLeftAngle, 23);
+ Vector frontLeftRay2 = calculateRaycastDirection(frontLeft2, frontLeftAngle2, 27);
+ Vector frontRay = calculateRaycastDirection(front, frontAngle, 35);
+ Vector frontRightRay2 = calculateRaycastDirection(frontRight2, frontRightAngle2, 27);
+ Vector frontRightRay = calculateRaycastDirection(frontRight, frontRightAngle, 23);
+ Vector lateralFrontRightRay = calculateRaycastDirection(latFrontRight, latFrontRightAngle, 19);
+ Vector lateralRightRay = calculateRaycastDirection(lateralRight, lateralRightAngle, 15);
+
+ Vector calculatedDirection =
+ new Vector()
+ .sum(lateralLeftRay)
+ .sum(lateralFrontLeftRay)
+ .sum(frontLeftRay)
+ .sum(frontLeftRay2)
+ .sum(frontRay)
+ .sum(frontRightRay2)
+ .sum(frontRightRay)
+ .sum(lateralFrontRightRay)
+ .sum(lateralRightRay);
+
+ return (calculatedDirection.normalize());
+ }
+
+ private Vector calculateRaycastDirection(Vector point, Vector direction, double distance)
+ throws RPCException {
+ double raycast =
+ pathFinding.raycastDistance(
+ posRoverToSurf(point),
+ transformDirection(direction),
+ vessel.surfaceReferenceFrame,
+ distance);
+ return direction.multiply(raycast);
+ }
+
+ private Vector transformDirection(Vector vector) throws RPCException {
+ return new Vector(
+ vessel
+ .getConnectionManager()
+ .getSpaceCenter()
+ .transformDirection(
+ vector.toTriplet(), roverReferenceFrame, vessel.surfaceReferenceFrame));
+ }
+
+ private Vector posSurfToRover(Vector vector) throws RPCException {
+ return new Vector(
+ vessel
+ .getConnectionManager()
+ .getSpaceCenter()
+ .transformPosition(
+ vector.toTriplet(), vessel.surfaceReferenceFrame, roverReferenceFrame));
+ }
+
+ private Vector posRoverToSurf(Vector vector) throws RPCException {
+ return new Vector(
+ vessel
+ .getConnectionManager()
+ .getSpaceCenter()
+ .transformPosition(
+ vector.toTriplet(), roverReferenceFrame, vessel.surfaceReferenceFrame));
+ }
+
+ private Vector posOrbToSurf(Vector vector) throws RPCException {
+ return new Vector(
+ vessel
+ .getConnectionManager()
+ .getSpaceCenter()
+ .transformPosition(
+ vector.toTriplet(), vessel.orbitalReferenceFrame, vessel.surfaceReferenceFrame));
+ }
+
+ private void setRoverThrottle(double throttle) throws RPCException, StreamException {
+ if (vessel.horizontalVelocity.get() < (maxSpeed * 1.01)) {
+ vessel.getActiveVessel().getControl().setBrakes(false);
+ vessel.getActiveVessel().getControl().setWheelThrottle((float) throttle);
+ } else {
+ vessel.getActiveVessel().getControl().setBrakes(true);
}
+ }
- private void setRoverSteering(double steering) throws RPCException {
- getActiveVessel().getControl().setWheelSteering((float) steering);
- }
+ private void setRoverSteering(double steering) throws RPCException {
+ vessel.getActiveVessel().getControl().setWheelSteering((float) steering);
+ }
- private enum MODE {
- DRIVE, NEXT_POINT, CHARGING
- }
+ private enum MODE {
+ DRIVE,
+ NEXT_POINT,
+ CHARGING
+ }
}
diff --git a/src/main/java/com/pesterenan/model/ActiveVessel.java b/src/main/java/com/pesterenan/model/ActiveVessel.java
index 849d94f..9a65eee 100644
--- a/src/main/java/com/pesterenan/model/ActiveVessel.java
+++ b/src/main/java/com/pesterenan/model/ActiveVessel.java
@@ -1,19 +1,22 @@
package com.pesterenan.model;
-import com.pesterenan.MechPeste;
import com.pesterenan.controllers.Controller;
+import com.pesterenan.controllers.DockingController;
import com.pesterenan.controllers.LandingController;
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.Module;
import com.pesterenan.utils.Telemetry;
import com.pesterenan.utils.Vector;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import krpc.client.Connection;
import krpc.client.RPCException;
import krpc.client.Stream;
import krpc.client.StreamException;
+import krpc.client.services.SpaceCenter;
import krpc.client.services.SpaceCenter.AutoPilot;
import krpc.client.services.SpaceCenter.CelestialBody;
import krpc.client.services.SpaceCenter.Flight;
@@ -21,218 +24,298 @@
import krpc.client.services.SpaceCenter.Vessel;
import krpc.client.services.SpaceCenter.VesselSituation;
-import java.util.HashMap;
-import java.util.Map;
+public class ActiveVessel {
-import static com.pesterenan.MechPeste.getConnection;
-import static com.pesterenan.MechPeste.getSpaceCenter;
+ public Vessel activeVessel;
+ public SpaceCenter spaceCenter;
+ public Connection connection;
+ private final Map telemetryData = new ConcurrentHashMap<>();
+ public AutoPilot ap;
+ public Flight flightParameters;
+ public ReferenceFrame orbitalReferenceFrame;
+ public Stream totalMass;
+ public ReferenceFrame surfaceReferenceFrame;
+ public float totalCharge;
+ public double gravityAcel;
+ public CelestialBody currentBody;
+ public Stream altitude;
+ public Stream surfaceAltitude;
+ public Stream apoapsis;
+ public Stream periapsis;
+ public Stream verticalVelocity;
+ public Stream missionTime;
+ public Stream horizontalVelocity;
+ public Map commands;
+ public int currentVesselId = 0;
+ public Thread controllerThread = null;
+ public Controller controller;
+ public long timer = 0;
+ private String currentStatus = Bundle.getString("status_ready");
+ private boolean runningModule;
+ private ConnectionManager connectionManager;
+ private VesselManager vesselManager;
-public class ActiveVessel {
+ public ActiveVessel(ConnectionManager connectionManager, VesselManager vesselManager) {
+ this.connectionManager = connectionManager;
+ this.vesselManager = vesselManager;
+ this.connection = connectionManager.getConnection();
+ this.spaceCenter = connectionManager.getSpaceCenter();
+ reinitialize();
+ }
- protected Vessel activeVessel;
- private final Map telemetryData = new HashMap<>();
- public AutoPilot ap;
- public Flight flightParameters;
- public ReferenceFrame orbitalReferenceFrame;
- protected Stream totalMass;
- public ReferenceFrame surfaceReferenceFrame;
- public float totalCharge;
- public double gravityAcel;
- public CelestialBody currentBody;
- public Stream altitude;
- public Stream surfaceAltitude;
- public Stream apoapsis;
- public Stream periapsis;
- public Stream verticalVelocity;
- public Stream missionTime;
- public Stream horizontalVelocity;
- public Map commands;
- protected int currentVesselId = 0;
- protected Thread controllerThread = null;
- protected Controller controller;
- protected long timer = 0;
- private String currentStatus = Bundle.getString("status_ready");
- private boolean runningModule;
-
- public ActiveVessel() {
- initializeParameters();
- }
+ public ConnectionManager getConnectionManager() {
+ return connectionManager;
+ }
- private void initializeParameters() {
- try {
- setActiveVessel(getSpaceCenter().getActiveVessel());
- currentVesselId = getActiveVessel().hashCode();
- ap = getActiveVessel().getAutoPilot();
- currentBody = getActiveVessel().getOrbit().getBody();
- gravityAcel = currentBody.getSurfaceGravity();
- orbitalReferenceFrame = currentBody.getReferenceFrame();
- surfaceReferenceFrame = getActiveVessel().getSurfaceReferenceFrame();
- flightParameters = getActiveVessel().flight(orbitalReferenceFrame);
- totalMass = getConnection().addStream(getActiveVessel(), "getMass");
- altitude = getConnection().addStream(flightParameters, "getMeanAltitude");
- surfaceAltitude = getConnection().addStream(flightParameters, "getSurfaceAltitude");
- apoapsis = getConnection().addStream(getActiveVessel().getOrbit(), "getApoapsisAltitude");
- periapsis = getConnection().addStream(getActiveVessel().getOrbit(), "getPeriapsisAltitude");
- verticalVelocity = getConnection().addStream(flightParameters, "getVerticalSpeed");
- horizontalVelocity = getConnection().addStream(flightParameters, "getHorizontalSpeed");
- } catch (RPCException | StreamException e) {
- MechPeste.newInstance().checkConnection();
- }
- }
+ public VesselManager getVesselManager() {
+ return vesselManager;
+ }
- public String getCurrentStatus() {
- if (controller != null) {
- return controller.getCurrentStatus();
- }
- return currentStatus;
+ public String getCurrentStatus() {
+ if (controller != null) {
+ return controller.getCurrentStatus();
}
+ return currentStatus;
+ }
- public void setCurrentStatus(String status) {
- currentStatus = status;
+ public void setCurrentStatus(String status) {
+ if (controller != null) {
+ controller.setCurrentStatus(status);
+ } else {
+ this.currentStatus = status;
}
+ }
- public int getCurrentVesselId() {
- return currentVesselId;
- }
+ public int getCurrentVesselId() {
+ return currentVesselId;
+ }
- public Vessel getActiveVessel() {
- return activeVessel;
- }
+ public Vessel getActiveVessel() {
+ return activeVessel;
+ }
- public void setActiveVessel(Vessel currentVessel) {
- activeVessel = currentVessel;
- }
+ public void setActiveVessel(Vessel currentVessel) {
+ activeVessel = currentVessel;
+ }
- public void throttle(float acel) throws RPCException {
- getActiveVessel().getControl().setThrottle(Math.min(acel, 1.0f));
- }
+ public void throttle(float acel) throws RPCException {
+ getActiveVessel().getControl().setThrottle(Math.min(acel, 1.0f));
+ }
- public void throttle(double acel) throws RPCException {
- throttle((float) acel);
- }
+ public void throttle(double acel) throws RPCException {
+ throttle((float) acel);
+ }
- public void tuneAutoPilot() throws RPCException {
- ap.setTimeToPeak(new Vector(2, 2, 2).toTriplet());
- ap.setDecelerationTime(new Vector(5, 5, 5).toTriplet());
- }
+ public void tuneAutoPilot() throws RPCException {
+ ap.setTimeToPeak(new Vector(2, 2, 2).toTriplet());
+ ap.setDecelerationTime(new Vector(5, 5, 5).toTriplet());
+ }
- public void liftoff() {
- try {
- getActiveVessel().getControl().setSAS(true);
- throttleUp(getMaxThrottleForTWR(2.0), 1);
- if (getActiveVessel().getSituation().equals(VesselSituation.PRE_LAUNCH)) {
- for (double count = 5.0; count >= 0; count -= 0.1) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- setCurrentStatus(String.format(Bundle.getString("status_launching_in"), count));
- Thread.sleep(100);
- }
- getSpaceCenter().setActiveVessel(activeVessel);
- getActiveVessel().getControl().activateNextStage();
- }
- setCurrentStatus(Bundle.getString("status_liftoff"));
- } catch (RPCException | InterruptedException | StreamException ignored) {
- setCurrentStatus(Bundle.getString("status_liftoff_abort"));
+ public void liftoff() {
+ try {
+ getActiveVessel().getControl().setSAS(true);
+ throttleUp(getMaxThrottleForTWR(2.0), 1);
+ if (getActiveVessel().getSituation().equals(VesselSituation.PRE_LAUNCH)) {
+ for (double count = 5.0; count >= 0; count -= 0.1) {
+ if (Thread.interrupted()) {
+ throw new InterruptedException();
+ }
+ setCurrentStatus(String.format(Bundle.getString("status_launching_in"), count));
+ Thread.sleep(100);
}
- }
-
- protected void decoupleStage() throws RPCException, InterruptedException {
- setCurrentStatus(Bundle.getString("status_separating_stage"));
- MechPeste.getSpaceCenter().setActiveVessel(getActiveVessel());
- double currentThrottle = getActiveVessel().getControl().getThrottle();
- throttle(0);
- Thread.sleep(1000);
+ spaceCenter.setActiveVessel(activeVessel);
getActiveVessel().getControl().activateNextStage();
- throttleUp(currentThrottle, 1);
+ }
+ setCurrentStatus(Bundle.getString("status_liftoff"));
+ } catch (RPCException | InterruptedException | StreamException ignored) {
+ setCurrentStatus(Bundle.getString("status_liftoff_abort"));
}
+ }
- protected void throttleUp(double throttleAmount, double seconds) throws RPCException, InterruptedException {
- double secondsElapsed = 0;
- while (secondsElapsed < seconds) {
- throttle(secondsElapsed / seconds * throttleAmount);
- secondsElapsed += 0.1;
- Thread.sleep(100);
- }
- }
+ public double getTWR() throws RPCException, StreamException {
+ return getActiveVessel().getAvailableThrust() / (totalMass.get() * gravityAcel);
+ }
- public double getTWR() throws RPCException, StreamException {
- return getActiveVessel().getAvailableThrust() / (totalMass.get() * gravityAcel);
- }
+ public double getMaxThrottleForTWR(double targetTWR) throws RPCException, StreamException {
+ return targetTWR / getTWR();
+ }
- public double getMaxThrottleForTWR(double targetTWR) throws RPCException, StreamException {
- return targetTWR / getTWR();
- }
+ public double getMaxAcel(float maxTWR) throws RPCException, StreamException {
+ return Math.min(maxTWR, getTWR()) * gravityAcel - gravityAcel;
+ }
- public double getMaxAcel(float maxTWR) throws RPCException, StreamException {
- return Math.min(maxTWR, getTWR()) * gravityAcel - gravityAcel;
+ public void startModule(Map commands) {
+ String currentFunction = commands.get(Module.MODULO.get());
+ if (controllerThread != null) {
+ controllerThread.interrupt();
+ runningModule = false;
+ try {
+ controllerThread.join(); // Wait for the previous thread to finish
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
}
-
- public void startModule(Map commands) {
- String currentFunction = commands.get(Module.MODULO.get());
- if (controllerThread != null) {
- controllerThread.interrupt();
- runningModule = false;
- }
- if (currentFunction.equals(Module.LIFTOFF.get())) {
- controller = new LiftoffController(commands);
- runningModule = true;
- }
- if (currentFunction.equals(Module.HOVERING.get()) || currentFunction.equals(Module.LANDING.get())) {
- controller = new LandingController(commands);
- runningModule = true;
- }
- if (currentFunction.equals(Module.MANEUVER.get())) {
- controller = new ManeuverController(commands);
- runningModule = true;
- }
- if (currentFunction.equals(Module.ROVER.get())) {
- controller = new RoverController(commands);
- runningModule = true;
- }
- if (currentFunction.equals(Module.DOCKING.get())) {
- controller = new DockingController(commands);
- System.out.println("escolheu modulo docking");
- runningModule = true;
- }
- controllerThread = new Thread(controller, currentVesselId + " - " + currentFunction);
- controllerThread.start();
+ if (currentFunction.equals(Module.LIFTOFF.get())) {
+ controller = new LiftoffController(this, commands);
+ runningModule = true;
}
+ if (currentFunction.equals(Module.HOVERING.get())
+ || currentFunction.equals(Module.LANDING.get())) {
+ controller = new LandingController(this, commands);
+ runningModule = true;
+ }
+ if (currentFunction.equals(Module.MANEUVER.get())) {
+ controller = new ManeuverController(this, commands);
+ runningModule = true;
+ }
+ if (currentFunction.equals(Module.ROVER.get())) {
+ controller = new RoverController(this, commands);
+ runningModule = true;
+ }
+ if (currentFunction.equals(Module.DOCKING.get())) {
+ controller = new DockingController(this, commands);
+ runningModule = true;
+ }
+ String controllerThreadName = "MP_CTRL_" + currentFunction + "_" + currentVesselId;
+ controllerThread = new Thread(controller, controllerThreadName);
+ controllerThread.start();
+ }
- public void recordTelemetryData() throws RPCException {
- if (getActiveVessel().getOrbit().getBody() != currentBody) {
- initializeParameters();
- }
- synchronized (telemetryData) {
- try {
- telemetryData.put(Telemetry.ALTITUDE, altitude.get() < 0 ? 0 : altitude.get());
- telemetryData.put(Telemetry.ALT_SURF, surfaceAltitude.get() < 0 ? 0 : surfaceAltitude.get());
- telemetryData.put(Telemetry.APOAPSIS, apoapsis.get() < 0 ? 0 : apoapsis.get());
- telemetryData.put(Telemetry.PERIAPSIS, periapsis.get() < 0 ? 0 : periapsis.get());
- telemetryData.put(Telemetry.VERT_SPEED, verticalVelocity.get());
- telemetryData.put(Telemetry.HORZ_SPEED, horizontalVelocity.get() < 0 ? 0 : horizontalVelocity.get());
- } catch (RPCException | StreamException ignored) {
- }
- }
+ public Thread getControllerThread() {
+ return controllerThread;
+ }
+
+ public void cancelControl() {
+ if (controller != null) {
+ controller.stop();
+ runningModule = false;
}
+ }
- public Map getTelemetryData() {
- return telemetryData;
+ public void removeStreams() {
+ // Interrupt any running controller thread
+ if (controllerThread != null && controllerThread.isAlive()) {
+ controllerThread.interrupt();
+ runningModule = false;
+ }
+ // Close all streams safely
+ synchronized (connection) {
+ try {
+ if (totalMass != null) totalMass.remove();
+ } catch (Exception e) {
+ /* ignore */
+ }
+ try {
+ if (altitude != null) altitude.remove();
+ } catch (Exception e) {
+ /* ignore */
+ }
+ try {
+ if (surfaceAltitude != null) surfaceAltitude.remove();
+ } catch (Exception e) {
+ /* ignore */
+ }
+ try {
+ if (apoapsis != null) apoapsis.remove();
+ } catch (Exception e) {
+ /* ignore */
+ }
+ try {
+ if (periapsis != null) periapsis.remove();
+ } catch (Exception e) {
+ /* ignore */
+ }
+ try {
+ if (verticalVelocity != null) verticalVelocity.remove();
+ } catch (Exception e) {
+ /* ignore */
+ }
+ try {
+ if (horizontalVelocity != null) horizontalVelocity.remove();
+ } catch (Exception e) {
+ /* ignore */
+ }
}
+ // Clear the telemetry data map
+ telemetryData.clear();
+ }
- public void cancelControl() {
- try {
- ap.disengage();
- throttle(0);
- if (controllerThread != null) {
- controllerThread.interrupt();
- runningModule = false;
- }
- } catch (RPCException ignored) {
- }
+ public Map getTelemetryData() {
+ return telemetryData;
+ }
+
+ public boolean hasModuleRunning() {
+ return runningModule;
+ }
+
+ public void decoupleStage() throws RPCException, InterruptedException {
+ setCurrentStatus(Bundle.getString("status_separating_stage"));
+ spaceCenter.setActiveVessel(getActiveVessel());
+ double currentThrottle = getActiveVessel().getControl().getThrottle();
+ throttle(0);
+ Thread.sleep(1000);
+ getActiveVessel().getControl().activateNextStage();
+ throttleUp(currentThrottle, 1);
+ }
+
+ public void throttleUp(double throttleAmount, double seconds)
+ throws RPCException, InterruptedException {
+ double secondsElapsed = 0;
+ while (secondsElapsed < seconds) {
+ throttle(secondsElapsed / seconds * throttleAmount);
+ secondsElapsed += 0.1;
+ Thread.sleep(100);
}
+ }
+
+ public void reinitialize() {
+ // Clean up any existing streams or threads before creating new ones
+ removeStreams();
+
+ System.out.println("DEBUG: Re-initializing ActiveVessel parameters...");
+ try {
+ setActiveVessel(spaceCenter.getActiveVessel());
+ currentVesselId = getActiveVessel().hashCode();
+ ap = getActiveVessel().getAutoPilot();
+ currentBody = getActiveVessel().getOrbit().getBody();
+ gravityAcel = currentBody.getSurfaceGravity();
+ orbitalReferenceFrame = currentBody.getReferenceFrame();
+ surfaceReferenceFrame = getActiveVessel().getSurfaceReferenceFrame();
+ flightParameters = getActiveVessel().flight(orbitalReferenceFrame);
+
+ System.out.println("DEBUG: Basic parameters set. Creating streams...");
+ synchronized (connection) {
+ altitude = connection.addStream(flightParameters, "getMeanAltitude");
+ apoapsis = connection.addStream(getActiveVessel().getOrbit(), "getApoapsisAltitude");
+ horizontalVelocity = connection.addStream(flightParameters, "getHorizontalSpeed");
+ periapsis = connection.addStream(getActiveVessel().getOrbit(), "getPeriapsisAltitude");
+ surfaceAltitude = connection.addStream(flightParameters, "getSurfaceAltitude");
+ totalMass = connection.addStream(getActiveVessel(), "getMass");
+ verticalVelocity = connection.addStream(flightParameters, "getVerticalSpeed");
+ missionTime = connection.addStream(spaceCenter.getClass(), "getUT");
+
+ altitude.addCallback(val -> telemetryData.put(Telemetry.ALTITUDE, val < 0 ? 0 : val));
+ apoapsis.addCallback(val -> telemetryData.put(Telemetry.APOAPSIS, val < 0 ? 0 : val));
+ horizontalVelocity.addCallback(
+ val -> telemetryData.put(Telemetry.HORZ_SPEED, val < 0 ? 0 : val));
+ periapsis.addCallback(val -> telemetryData.put(Telemetry.PERIAPSIS, val < 0 ? 0 : val));
+ surfaceAltitude.addCallback(val -> telemetryData.put(Telemetry.ALT_SURF, val < 0 ? 0 : val));
+ verticalVelocity.addCallback(val -> telemetryData.put(Telemetry.VERT_SPEED, val));
- public boolean hasModuleRunning() {
- return runningModule;
+ altitude.start();
+ apoapsis.start();
+ horizontalVelocity.start();
+ periapsis.start();
+ surfaceAltitude.start();
+ totalMass.start();
+ verticalVelocity.start();
+ missionTime.start();
+ }
+ System.out.println("DEBUG: All streams created successfully.");
+ } catch (RPCException | StreamException e) {
+ System.err.println(
+ "DEBUG: CRITICAL ERROR while re-initializing parameters for active vessel: "
+ + e.getMessage());
}
+ }
}
diff --git a/src/main/java/com/pesterenan/model/ConnectionListener.java b/src/main/java/com/pesterenan/model/ConnectionListener.java
new file mode 100644
index 0000000..707d869
--- /dev/null
+++ b/src/main/java/com/pesterenan/model/ConnectionListener.java
@@ -0,0 +1,8 @@
+package com.pesterenan.model;
+
+import krpc.client.Connection;
+import krpc.client.services.SpaceCenter;
+
+public interface ConnectionListener {
+ void onConnectionChanged(Connection newConnection, SpaceCenter newSpaceCenter);
+}
diff --git a/src/main/java/com/pesterenan/model/ConnectionManager.java b/src/main/java/com/pesterenan/model/ConnectionManager.java
new file mode 100644
index 0000000..e961598
--- /dev/null
+++ b/src/main/java/com/pesterenan/model/ConnectionManager.java
@@ -0,0 +1,136 @@
+package com.pesterenan.model;
+
+import com.pesterenan.resources.Bundle;
+import com.pesterenan.views.StatusDisplay;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import javax.swing.SwingUtilities;
+import krpc.client.Connection;
+import krpc.client.RPCException;
+import krpc.client.services.KRPC;
+import krpc.client.services.SpaceCenter;
+
+public class ConnectionManager {
+ private KRPC krpc;
+ private Connection connection;
+ private SpaceCenter spaceCenter;
+ private StatusDisplay statusDisplay;
+ private volatile boolean isConnecting = false;
+ private ScheduledExecutorService connectionMonitor;
+ private String connectionName;
+ private final List listeners = new ArrayList<>();
+
+ public ConnectionManager(final String connectionName, final StatusDisplay statusDisplay) {
+ this.statusDisplay = statusDisplay;
+ this.connectionName = connectionName;
+ startMonitoring();
+ }
+
+ public void addListener(ConnectionListener listener) {
+ listeners.add(listener);
+ }
+
+ private void notifyListeners() {
+ for (ConnectionListener listener : listeners) {
+ listener.onConnectionChanged(connection, spaceCenter);
+ }
+ }
+
+ public Connection getConnection() {
+ return connection;
+ }
+
+ public SpaceCenter getSpaceCenter() {
+ return spaceCenter;
+ }
+
+ public KRPC getKRPC() {
+ return krpc;
+ }
+
+ public void connect() {
+ attemptConnection();
+ }
+
+ public void disconnect() {
+ try {
+ if (connection != null) {
+ connection.close();
+ }
+ } catch (IOException e) {
+ System.err.println("Error closing connection: " + e.getMessage());
+ }
+ if (connectionMonitor != null && !connectionMonitor.isShutdown()) {
+ connectionMonitor.shutdown();
+ }
+ }
+
+ private void startMonitoring() {
+ if (connectionMonitor != null && !connectionMonitor.isShutdown()) return;
+ connectionMonitor =
+ Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "MP_CONNECTION_MONITOR"));
+ connectionMonitor.scheduleAtFixedRate(
+ () -> {
+ if (!isConnectionAlive()) {
+ attemptConnection();
+ }
+ },
+ 0,
+ 5,
+ TimeUnit.SECONDS);
+ }
+
+ private void attemptConnection() {
+ if (isConnecting) return;
+ try {
+ isConnecting = true;
+ SwingUtilities.invokeLater(
+ () -> {
+ statusDisplay.setStatusMessage(Bundle.getString("status_connecting"));
+ statusDisplay.setBtnConnectVisible(false);
+ });
+
+ connection = Connection.newInstance(connectionName);
+ krpc = KRPC.newInstance(connection);
+ spaceCenter = SpaceCenter.newInstance(connection);
+ notifyListeners(); // Notify listeners of the new connection
+
+ SwingUtilities.invokeLater(
+ () -> statusDisplay.setStatusMessage(Bundle.getString("status_connected")));
+ } catch (IOException e) {
+ connection = null;
+ krpc = null;
+ spaceCenter = null;
+ SwingUtilities.invokeLater(
+ () -> {
+ statusDisplay.setStatusMessage(Bundle.getString("status_error_connection"));
+ statusDisplay.setBtnConnectVisible(true);
+ });
+ } finally {
+ isConnecting = false;
+ }
+ }
+
+ public boolean isConnectionAlive() {
+ try {
+ if (krpc == null || connection == null) return false;
+ krpc.getStatus();
+ return true;
+ } catch (RPCException e) {
+ return false;
+ }
+ }
+
+ public boolean isOnFlightScene() {
+ try {
+ if (krpc == null) return false;
+ return krpc.getCurrentGameScene().equals(KRPC.GameScene.FLIGHT);
+ } catch (final RPCException e) {
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/com/pesterenan/model/VesselManager.java b/src/main/java/com/pesterenan/model/VesselManager.java
new file mode 100644
index 0000000..08b8390
--- /dev/null
+++ b/src/main/java/com/pesterenan/model/VesselManager.java
@@ -0,0 +1,245 @@
+package com.pesterenan.model;
+
+import com.pesterenan.resources.Bundle;
+import com.pesterenan.utils.Vector;
+import com.pesterenan.views.FunctionsAndTelemetryJPanel;
+import com.pesterenan.views.CreateManeuverJPanel;
+import com.pesterenan.views.MainGui;
+import com.pesterenan.views.StatusDisplay;
+import java.awt.event.ActionEvent;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import javax.swing.DefaultListModel;
+import javax.swing.ListModel;
+import javax.swing.SwingUtilities;
+import krpc.client.Connection;
+import krpc.client.RPCException;
+import krpc.client.services.SpaceCenter;
+import krpc.client.services.SpaceCenter.Node;
+import krpc.client.services.SpaceCenter.Vessel;
+
+public class VesselManager implements ConnectionListener {
+ private ActiveVessel currentVessel;
+ private ConnectionManager connectionManager;
+ private FunctionsAndTelemetryJPanel telemetryPanel;
+ private StatusDisplay statusDisplay;
+ private SpaceCenter spaceCenter;
+ private int currentVesselId = -1;
+ private ScheduledExecutorService telemetryMonitor;
+
+ public VesselManager(
+ final ConnectionManager connectionManager,
+ final StatusDisplay statusDisplay,
+ final FunctionsAndTelemetryJPanel telemetryPanel) {
+ this.connectionManager = connectionManager;
+ this.statusDisplay = statusDisplay;
+ this.telemetryPanel = telemetryPanel;
+ this.connectionManager.addListener(this);
+ }
+
+ @Override
+ public void onConnectionChanged(Connection newConnection, SpaceCenter newSpaceCenter) {
+ this.spaceCenter = newSpaceCenter;
+ clearVessel();
+ System.out.println("DEBUG: Connection changed. Vessel cleared.");
+ }
+
+ public Connection getConnection() {
+ return connectionManager.getConnection();
+ }
+
+ public SpaceCenter getSpaceCenter() {
+ return spaceCenter;
+ }
+
+ public ActiveVessel getCurrentVessel() {
+ return currentVessel;
+ }
+
+ public int getCurrentVesselId() {
+ return currentVesselId;
+ }
+
+ public void startTelemetryLoop() {
+ if (telemetryMonitor != null && !telemetryMonitor.isShutdown()) return;
+ telemetryMonitor =
+ Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "MP_TELEMETRY_UPDATER"));
+ telemetryMonitor.scheduleAtFixedRate(
+ () -> {
+ if (connectionManager.isConnectionAlive()) {
+ checkAndUpdateActiveVessel();
+ }
+ if (currentVessel != null && connectionManager.isOnFlightScene()) {
+ updateUI();
+ }
+ },
+ 0,
+ 100,
+ TimeUnit.MILLISECONDS);
+ }
+
+ public ListModel getCurrentManeuvers() {
+ DefaultListModel list = new DefaultListModel<>();
+ try {
+ List maneuvers = getSpaceCenter().getActiveVessel().getControl().getNodes();
+ maneuvers.forEach(
+ m -> {
+ try {
+ String maneuverStr =
+ String.format(
+ "%d - Dv: %.1f {P: %.1f, N: %.1f, R: %.1f} AP: %.1f, PE: %.1f",
+ maneuvers.indexOf(m) + 1,
+ m.getDeltaV(),
+ m.getPrograde(),
+ m.getNormal(),
+ m.getRadial(),
+ m.getOrbit().getApoapsisAltitude(),
+ m.getOrbit().getPeriapsisAltitude());
+ list.addElement(maneuverStr);
+ } catch (RPCException ignored) {
+ }
+ });
+ } catch (RPCException | NullPointerException | UnsupportedOperationException e) {
+ System.err.println("ERRO: Não foi possivel atualizar as manobras atuais. " + e.getClass().getSimpleName());
+ }
+ return list;
+ }
+
+ public void startModule(Map commands) {
+ currentVessel.startModule(commands);
+ }
+
+ public ListModel getActiveVessels(String search) {
+ DefaultListModel list = new DefaultListModel<>();
+ try {
+ List vessels = getSpaceCenter().getVessels();
+ vessels = vessels.stream().filter(v -> filterVessels(v, search)).collect(Collectors.toList());
+ vessels.forEach(
+ v -> {
+ try {
+ String vesselName = v.hashCode() + " - \t" + v.getName();
+ list.addElement(vesselName);
+ } catch (RPCException e) {
+ System.err.println(
+ "ERRO: Não foi possível adicionar nave na lista. " + e.getMessage());
+ }
+ });
+ } catch (RPCException | NullPointerException e) {
+ System.err.println("ERRO: Não foi possível buscar lista de naves. " + e.getMessage());
+ }
+ return list;
+ }
+
+ public String getVesselInfo(int selectedIndex) {
+ try {
+ Vessel activeVessel =
+ getSpaceCenter().getVessels().stream()
+ .filter(v -> v.hashCode() == selectedIndex)
+ .findFirst()
+ .get();
+ String name =
+ activeVessel.getName().length() > 40
+ ? activeVessel.getName().substring(0, 40) + "..."
+ : activeVessel.getName();
+ String vesselInfo =
+ String.format(
+ "Nome: %s\t\t\t | Corpo: %s", name, activeVessel.getOrbit().getBody().getName());
+ return vesselInfo;
+ } catch (RPCException | NullPointerException e) {
+ System.err.println("ERRO: Não foi possível buscar informações da nave. " + e.getMessage());
+ }
+ return "";
+ }
+
+ public void changeToVessel(int selectedIndex) {
+ try {
+ Vessel activeVessel =
+ getSpaceCenter().getVessels().stream()
+ .filter(v -> v.hashCode() == selectedIndex)
+ .findFirst()
+ .get();
+ getSpaceCenter().setActiveVessel(activeVessel);
+ } catch (RPCException | NullPointerException e) {
+ System.out.println(Bundle.getString("status_couldnt_switch_vessel"));
+ }
+ }
+
+ public void cancelControl(ActionEvent e) {
+ if (currentVessel != null) {
+ currentVessel.cancelControl();
+ }
+ }
+
+ private void checkAndUpdateActiveVessel() {
+ try {
+ int activeVesselId = getSpaceCenter().getActiveVessel().hashCode();
+ if (currentVesselId != activeVesselId) {
+ System.out.println("DEBUG: Active vessel changed. Re-initializing...");
+ if (currentVessel != null) {
+ currentVessel.reinitialize();
+ } else {
+ currentVessel = new ActiveVessel(connectionManager, this);
+ }
+ currentVesselId = currentVessel.getCurrentVesselId();
+ MainGui.getInstance().setVesselManager(this);
+ }
+ } catch (IllegalArgumentException e) {
+ } catch (RPCException e) {
+ System.out.println("DEBUG: Could not get active vessel. Cleaning up.");
+ clearVessel();
+ }
+ }
+
+ public void clearVessel() {
+ if (currentVessel != null) {
+ currentVessel.removeStreams();
+ }
+ currentVessel = null;
+ currentVesselId = -1;
+ }
+
+ private void updateUI() {
+ SwingUtilities.invokeLater(
+ () -> {
+ if (currentVessel != null && telemetryPanel != null) {
+ telemetryPanel.updateTelemetry(currentVessel.getTelemetryData());
+ CreateManeuverJPanel createManeuverPanel = MainGui.getInstance().getCreateManeuverPanel();
+ if (createManeuverPanel.isShowing()) {
+ createManeuverPanel.updatePanel(getCurrentManeuvers());
+ }
+ if (currentVessel.hasModuleRunning()) {
+ statusDisplay.setStatusMessage(currentVessel.getCurrentStatus());
+ }
+ }
+ }); }
+
+ private boolean filterVessels(Vessel vessel, String search) {
+ if ("all".equals(search)) {
+ return true;
+ }
+ double TEN_KILOMETERS = 10000.0;
+ try {
+ Vessel active = 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;
+ }
+}
diff --git a/src/main/java/com/pesterenan/resources/Bundle.java b/src/main/java/com/pesterenan/resources/Bundle.java
index 1d4e53b..42e493d 100644
--- a/src/main/java/com/pesterenan/resources/Bundle.java
+++ b/src/main/java/com/pesterenan/resources/Bundle.java
@@ -5,17 +5,16 @@
import java.util.ResourceBundle;
public class Bundle {
- public static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle("MechPesteBundle",
- Locale.getDefault());
+ public static final ResourceBundle RESOURCE_BUNDLE =
+ ResourceBundle.getBundle("MechPesteBundle", Locale.getDefault());
- private Bundle() {
- }
+ private Bundle() {}
- public static String getString(String key) {
- try {
- return RESOURCE_BUNDLE.getString(key);
- } catch (MissingResourceException e) {
- return '!' + key + '!';
- }
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+ } catch (MissingResourceException e) {
+ return '!' + key + '!';
}
+ }
}
diff --git a/src/main/java/com/pesterenan/updater/KrpcInstaller.java b/src/main/java/com/pesterenan/updater/KrpcInstaller.java
index f7ca60b..3feebec 100644
--- a/src/main/java/com/pesterenan/updater/KrpcInstaller.java
+++ b/src/main/java/com/pesterenan/updater/KrpcInstaller.java
@@ -1,7 +1,6 @@
package com.pesterenan.updater;
import com.pesterenan.views.InstallKrpcDialog;
-
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
@@ -15,76 +14,77 @@
import java.util.zip.ZipInputStream;
public class KrpcInstaller {
- static final int BUFFER = 2048;
- private static final String KRPC_GITHUB_LINK = "https://github.com/krpc/krpc/releases/download/v0.5.4/krpc-0.5.4.zip";
- private static String KSP_FOLDER = null;
+ static final int BUFFER = 2048;
+ private static final String KRPC_GITHUB_LINK =
+ "https://github.com/krpc/krpc/releases/download/v0.5.4/krpc-0.5.4.zip";
+ private static String KSP_FOLDER = null;
- public static String getKspFolder() {
- return KSP_FOLDER;
- }
+ public static String getKspFolder() {
+ return KSP_FOLDER;
+ }
- public static void setKspFolder(String folderPath) {
- KSP_FOLDER = folderPath;
- }
+ public static void setKspFolder(String folderPath) {
+ KSP_FOLDER = folderPath;
+ }
- public static void downloadAndInstallKrpc() {
- InstallKrpcDialog.setStatus("Fazendo download do KRPC pelo Github...");
- downloadKrpc();
- InstallKrpcDialog.setStatus("Download completo!");
- InstallKrpcDialog.setStatus("Extraindo arquivos...");
- unzipKrpc();
- InstallKrpcDialog.setStatus("Instalação terminada, reinicie o KSP!");
- }
+ public static void downloadAndInstallKrpc() {
+ InstallKrpcDialog.setStatus("Fazendo download do KRPC pelo Github...");
+ downloadKrpc();
+ InstallKrpcDialog.setStatus("Download completo!");
+ InstallKrpcDialog.setStatus("Extraindo arquivos...");
+ unzipKrpc();
+ InstallKrpcDialog.setStatus("Instalação terminada, reinicie o KSP!");
+ }
- public static void downloadKrpc() {
- URL krpcLink;
- try {
- krpcLink = new URL(KRPC_GITHUB_LINK);
- ReadableByteChannel readableByteChannel = Channels.newChannel(krpcLink.openStream());
- FileOutputStream fos = new FileOutputStream(KSP_FOLDER + "\\krpc-0.5.4.zip");
- fos.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
- fos.close();
- } catch (IOException e) {
- InstallKrpcDialog.setStatus("Não foi possível fazer o download do KRPC");
- }
+ public static void downloadKrpc() {
+ URL krpcLink;
+ try {
+ krpcLink = new URL(KRPC_GITHUB_LINK);
+ ReadableByteChannel readableByteChannel = Channels.newChannel(krpcLink.openStream());
+ FileOutputStream fos = new FileOutputStream(KSP_FOLDER + "\\krpc-0.5.4.zip");
+ fos.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
+ fos.close();
+ } catch (IOException e) {
+ InstallKrpcDialog.setStatus("Não foi possível fazer o download do KRPC");
}
+ }
- public static void unzipKrpc() {
- try {
- File folder = new File(KSP_FOLDER);
- if (!folder.exists()) {
- folder.mkdir();
- }
- BufferedOutputStream dest;
- // zipped input
- FileInputStream fis = new FileInputStream(KSP_FOLDER + "\\krpc-0.5.4.zip");
- ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
- ZipEntry entry;
- while ((entry = zis.getNextEntry()) != null) {
- int count;
- byte[] data = new byte[BUFFER];
- String fileName = entry.getName();
- File newFile = new File(folder + File.separator + fileName);
- // If directory then just create the directory (and parents if required)
- if (entry.isDirectory()) {
- if (!newFile.exists()) {
- newFile.mkdirs();
- }
- } else {
- // write the files to the disk
- FileOutputStream fos = new FileOutputStream(newFile);
- dest = new BufferedOutputStream(fos, BUFFER);
- while ((count = zis.read(data, 0, BUFFER)) != -1) {
- dest.write(data, 0, count);
- }
- dest.flush();
- dest.close();
- }
- zis.closeEntry();
- }
- zis.close();
- } catch (Exception e) {
- InstallKrpcDialog.setStatus("Não foi possível fazer instalar o KRPC");
+ public static void unzipKrpc() {
+ try {
+ File folder = new File(KSP_FOLDER);
+ if (!folder.exists()) {
+ folder.mkdir();
+ }
+ BufferedOutputStream dest;
+ // zipped input
+ FileInputStream fis = new FileInputStream(KSP_FOLDER + "\\krpc-0.5.4.zip");
+ ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
+ ZipEntry entry;
+ while ((entry = zis.getNextEntry()) != null) {
+ int count;
+ byte[] data = new byte[BUFFER];
+ String fileName = entry.getName();
+ File newFile = new File(folder + File.separator + fileName);
+ // If directory then just create the directory (and parents if required)
+ if (entry.isDirectory()) {
+ if (!newFile.exists()) {
+ newFile.mkdirs();
+ }
+ } else {
+ // write the files to the disk
+ FileOutputStream fos = new FileOutputStream(newFile);
+ dest = new BufferedOutputStream(fos, BUFFER);
+ while ((count = zis.read(data, 0, BUFFER)) != -1) {
+ dest.write(data, 0, count);
+ }
+ dest.flush();
+ dest.close();
}
+ zis.closeEntry();
+ }
+ zis.close();
+ } catch (Exception e) {
+ InstallKrpcDialog.setStatus("Não foi possível fazer instalar o KRPC");
}
+ }
}
diff --git a/src/main/java/com/pesterenan/utils/Attributes.java b/src/main/java/com/pesterenan/utils/Attributes.java
index 51174d8..2c75c39 100644
--- a/src/main/java/com/pesterenan/utils/Attributes.java
+++ b/src/main/java/com/pesterenan/utils/Attributes.java
@@ -5,29 +5,30 @@
public class Attributes {
- private static Map safeLowOrbitAltitudes = new HashMap();
+ private static Map safeLowOrbitAltitudes = new HashMap();
- public Attributes() {
- safeLowOrbitAltitudes.put("Bop", 10_000.0);
- safeLowOrbitAltitudes.put("Dres", 20_000.0);
- safeLowOrbitAltitudes.put("Duna", 60_000.0);
- safeLowOrbitAltitudes.put("Eeloo", 20_000.0);
- safeLowOrbitAltitudes.put("Eve", 100_000.0);
- safeLowOrbitAltitudes.put("Gilly", 10_000.0);
- safeLowOrbitAltitudes.put("Ike", 20_000.0);
- safeLowOrbitAltitudes.put("Jool", 220_000.0);
- safeLowOrbitAltitudes.put("Kerbin", 80_000.0);
- safeLowOrbitAltitudes.put("Laythe", 80_000.0);
- safeLowOrbitAltitudes.put("Minmus", 10_000.0);
- safeLowOrbitAltitudes.put("Moho", 35_000.0);
- safeLowOrbitAltitudes.put("Mun", 10_000.0);
- safeLowOrbitAltitudes.put("Pol", 10_000.0);
- safeLowOrbitAltitudes.put("Sun", 350_000.0);
- safeLowOrbitAltitudes.put("Tylo", 40_000.0);
- safeLowOrbitAltitudes.put("Vall", 20_000.0);
- }
+ public Attributes() {
+ safeLowOrbitAltitudes.put("Bop", 10_000.0);
+ safeLowOrbitAltitudes.put("Dres", 20_000.0);
+ safeLowOrbitAltitudes.put("Duna", 60_000.0);
+ safeLowOrbitAltitudes.put("Eeloo", 20_000.0);
+ safeLowOrbitAltitudes.put("Eve", 100_000.0);
+ safeLowOrbitAltitudes.put("Gilly", 10_000.0);
+ safeLowOrbitAltitudes.put("Ike", 20_000.0);
+ safeLowOrbitAltitudes.put("Jool", 220_000.0);
+ safeLowOrbitAltitudes.put("Kerbin", 80_000.0);
+ safeLowOrbitAltitudes.put("Laythe", 80_000.0);
+ safeLowOrbitAltitudes.put("Minmus", 10_000.0);
+ safeLowOrbitAltitudes.put("Moho", 35_000.0);
+ safeLowOrbitAltitudes.put("Mun", 10_000.0);
+ safeLowOrbitAltitudes.put("Pol", 10_000.0);
+ safeLowOrbitAltitudes.put("Sun", 350_000.0);
+ safeLowOrbitAltitudes.put("Tylo", 40_000.0);
+ safeLowOrbitAltitudes.put("Vall", 20_000.0);
+ }
- public double getLowOrbitAltitude(String celestialBody) {
- return safeLowOrbitAltitudes.getOrDefault(celestialBody, 10_000.0);
- };
+ public double getLowOrbitAltitude(String celestialBody) {
+ return safeLowOrbitAltitudes.getOrDefault(celestialBody, 10_000.0);
+ }
+ ;
}
diff --git a/src/main/java/com/pesterenan/utils/ControlePID.java b/src/main/java/com/pesterenan/utils/ControlePID.java
index 1fce344..5534712 100644
--- a/src/main/java/com/pesterenan/utils/ControlePID.java
+++ b/src/main/java/com/pesterenan/utils/ControlePID.java
@@ -4,101 +4,115 @@
import krpc.client.services.SpaceCenter;
public class ControlePID {
- 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 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() {
+ 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 integralTerm = 0.0;
+ private double previousError, lastTime = 0.0;
+ private double timeSample = 0.025; // 25 millisegundos
+ private double proportionalTerm;
+
+ private double derivativeTerm;
+
+ public ControlePID() {}
+
+ public ControlePID(SpaceCenter spaceCenter) {
+ this.spaceCenter = spaceCenter;
+ }
+
+ 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 double getTimeSample() {
+ return timeSample;
+ }
+
+ public void reset() {
+ this.previousError = 0;
+ this.proportionalTerm = 0;
+ this.integralTerm = 0;
+ this.derivativeTerm = 0;
+ }
+
+ public double calculate(double measurement, double setPoint) {
+ double now = this.getCurrentTime();
+ double changeInTime = now - lastTime;
+
+ if (changeInTime >= timeSample) {
+ // Error signal
+ double error = setPoint - measurement;
+ // Proportional
+ proportionalTerm = kp * error;
+
+ // Integral
+ integralTerm += 0.5 * ki * timeSample * (error + previousError);
+ integralTerm = limitOutput(integralTerm);
+
+ derivativeTerm = kd * ((error - previousError) / timeSample);
+ previousError = error;
+ lastTime = now;
}
+ return limitOutput(proportionalTerm + integralTerm + derivativeTerm);
+ }
- public ControlePID(SpaceCenter spaceCenter, double timeSample) {
- this.spaceCenter = spaceCenter;
- setTimeSample(timeSample);
+ public void setOutput(double min, double max) {
+ if (min > max) {
+ return;
}
-
- 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;
+ outputMin = min;
+ outputMax = max;
+ integralTerm = limitOutput(integralTerm);
+ }
+
+ public void setPIDValues(double Kp, double Ki, double Kd) {
+ if (Kp > 0) {
+ this.kp = Kp;
}
-
- public double calculate(double measurement, double setPoint) {
- double now = this.getCurrentTime();
- double changeInTime = now - lastTime;
-
- if (changeInTime >= timeSample) {
- // 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 + integralTerm + derivativeTerm);
+ if (Ki >= 0) {
+ this.ki = Ki;
}
-
- private double limitOutput(double value) {
- return Utilities.clamp(value, outputMin, outputMax);
+ if (Kd >= 0) {
+ this.kd = Kd;
}
-
- public void setOutput(double min, double max) {
- if (min > max) {
- return;
- }
- outputMin = min;
- outputMax = max;
- integralTerm = limitOutput(integralTerm);
+ }
+
+ public void setTimeSample(double milliseconds) {
+ timeSample = milliseconds > 0 ? milliseconds / 1000 : timeSample;
+ }
+
+ /**
+ * Tries to return the milliseconds from the game, if it fails, returns the system time
+ *
+ * @returns the current time in milisseconds
+ */
+ public double getCurrentTime() {
+ try {
+ return spaceCenter.getUT();
+ } catch (RPCException | NullPointerException ignored) {
+ return System.currentTimeMillis();
}
-
- public void setPIDValues(double Kp, double Ki, double Kd) {
- if (Kp > 0) {
- this.kp = Kp;
- }
- if (Ki >= 0) {
- this.ki = Ki;
- }
- if (Kd >= 0) {
- this.kd = Kd;
- }
- }
-
- 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();
- }
+ }
+
+ /** Uses busy waiting to lock the thread until time passes the time sample */
+ public void waitForNextSample() throws InterruptedException {
+ double startTime = getCurrentTime();
+ while (getCurrentTime() - startTime < getTimeSample()) {
+ Thread.sleep(1);
+ if (Thread.interrupted()) {
+ throw new InterruptedException();
+ }
}
+ }
+ private double limitOutput(double value) {
+ return Utilities.clamp(value, outputMin, outputMax);
+ }
}
diff --git a/src/main/java/com/pesterenan/utils/Module.java b/src/main/java/com/pesterenan/utils/Module.java
index 2a6b5cd..566af1e 100644
--- a/src/main/java/com/pesterenan/utils/Module.java
+++ b/src/main/java/com/pesterenan/utils/Module.java
@@ -1,37 +1,51 @@
package com.pesterenan.utils;
public enum Module {
+ ADJUST("Ajustar"),
+ APOAPSIS("Apoastro"),
+ CIRCULAR("Circular"),
+ CREATE_MANEUVER("CRIAR_MANOBRAS"),
+ CUBIC("Cúbica"),
+ DIRECTION("Direção"),
+ DOCKING("DOCKING"),
+ EXECUTE("Executar"),
+ EXPONENCIAL("Exponencial"),
+ FINE_ADJUST("Ajuste Fino"),
+ FUNCTION("Função"),
+ HOVERING("HOVER"),
+ HOVER_AFTER_LANDING("SOBREVOO PÓS POUSO"),
+ HOVER_ALTITUDE("Altitude Sobrevoo"),
+ INCLINATION("Inclinação"),
+ LAND("Pousar nave"),
+ LANDING("LANDING"),
+ LIFTOFF("LIFTOFF"),
+ LOW_ORBIT("ÓRBITA BAIXA"),
+ MANEUVER("MANEUVER"),
+ MAP_MARKER("Marcador no mapa"),
+ MARKER_NAME("Nome do marcador"),
+ MAX_SPEED("Velocidade Máxima"),
+ MAX_TWR("Max_TWR"),
+ MODULO("Módulo"),
+ OPEN_PANELS("Abrir Painéis"),
+ PERIAPSIS("Periastro"),
+ QUADRATIC("Quadrática"),
+ RENDEZVOUS("Rendezvous"),
+ ROLL("Rolagem"),
+ ROVER("ROVER"),
+ ROVER_TARGET_TYPE("Tipo de Alvo do Rover"),
+ SAFE_DISTANCE("Distância Segura"),
+ SINUSOIDAL("Sinusoidal"),
+ STAGE("Usar Estágios"),
+ TARGET_VESSEL("Nave alvo"),
+ TELEMETRY("TELEMETRY");
- ADJUST("Ajustar"), APOAPSIS("Apoastro"), CIRCULAR("Circular"), CREATE_MANEUVER("CRIAR_MANOBRAS"), CUBIC(
- "Cúbica"), DIRECTION("Direção"), DOCKING("DOCKING"), EXECUTE("Executar"), EXPONENCIAL(
- "Exponencial"), FINE_ADJUST("Ajuste Fino"), FUNCTION("Função"), HOVERING(
- "HOVER"), HOVER_AFTER_LANDING("SOBREVOO PÓS POUSO"), HOVER_ALTITUDE(
- "Altitude Sobrevoo"), INCLINATION("Inclinação"), LAND("Pousar nave"), LANDING(
- "LANDING"), LIFTOFF("LIFTOFF"), LOW_ORBIT("ÓRBITA BAIXA"), MANEUVER(
- "MANEUVER"), MAP_MARKER("Marcador no mapa"), MARKER_NAME(
- "Nome do marcador"), MAX_SPEED(
- "Velocidade Máxima"), MAX_TWR("Max_TWR"), MODULO(
- "Módulo"), OPEN_PANELS(
- "Abrir Painéis"), PERIAPSIS(
- "Periastro"), QUADRATIC(
- "Quadrática"), RENDEZVOUS(
- "Rendezvous"), ROLL(
- "Rolagem"), ROVER(
- "ROVER"), ROVER_TARGET_TYPE(
- "Tipo de Alvo do Rover"), SAFE_DISTANCE(
- "Distância Segura"), SINUSOIDAL(
- "Sinusoidal"), STAGE(
- "Usar Estágios"), TARGET_VESSEL(
- "Nave alvo"), TELEMETRY(
- "TELEMETRY");
+ final String t;
- final String t;
+ Module(String t) {
+ this.t = t;
+ }
- Module(String t) {
- this.t = t;
- }
-
- public String get() {
- return this.t;
- }
+ public String get() {
+ return this.t;
+ }
}
diff --git a/src/main/java/com/pesterenan/utils/Navigation.java b/src/main/java/com/pesterenan/utils/Navigation.java
index 9e8792d..5eac8b8 100644
--- a/src/main/java/com/pesterenan/utils/Navigation.java
+++ b/src/main/java/com/pesterenan/utils/Navigation.java
@@ -1,154 +1,155 @@
package com.pesterenan.utils;
+import static krpc.client.services.SpaceCenter.*;
+
+import com.pesterenan.model.ConnectionManager;
import krpc.client.RPCException;
import krpc.client.Stream;
import krpc.client.StreamException;
import org.javatuples.Triplet;
-import static com.pesterenan.MechPeste.getConnection;
-import static com.pesterenan.MechPeste.getSpaceCenter;
-import static krpc.client.services.SpaceCenter.*;
-
public class Navigation {
- public static final Triplet RADIAL = new Triplet<>(1.0, 0.0, 0.0);
- public static final Triplet ANTI_RADIAL = new Triplet<>(-1.0, 0.0, 0.0);
- public static final Triplet PROGRADE = new Triplet<>(0.0, 1.0, 0.0);
- public static final Triplet RETROGRADE = new Triplet<>(0.0, -1.0, 0.0);
- public static final Triplet NORMAL = new Triplet<>(0.0, 0.0, 1.0);
- public static final Triplet ANTI_NORMAL = new Triplet<>(0.0, 0.0, -1.0);
- // private Drawing drawing;
- private Vessel currentVessel;
- private Flight flightParameters;
- private Stream horizontalSpeed;
- private ReferenceFrame orbitalReference;
-
- public Navigation(Vessel currentVessel) {
- this.currentVessel = currentVessel;
- initializeParameters();
- }
+ public static final Triplet RADIAL = new Triplet<>(1.0, 0.0, 0.0);
+ public static final Triplet ANTI_RADIAL = new Triplet<>(-1.0, 0.0, 0.0);
+ public static final Triplet PROGRADE = new Triplet<>(0.0, 1.0, 0.0);
+ public static final Triplet RETROGRADE = new Triplet<>(0.0, -1.0, 0.0);
+ public static final Triplet NORMAL = new Triplet<>(0.0, 0.0, 1.0);
+ public static final Triplet ANTI_NORMAL = new Triplet<>(0.0, 0.0, -1.0);
+ // private Drawing drawing;
+ private Vessel currentVessel;
+ private Flight flightParameters;
+ private Stream horizontalSpeed;
+ private ReferenceFrame orbitalReference;
+ private ConnectionManager connectionManager;
- private void initializeParameters() {
- try {
- // drawing = Drawing.newInstance(getConexao());
- orbitalReference = currentVessel.getOrbit().getBody().getReferenceFrame();
- flightParameters = currentVessel.flight(orbitalReference);
- horizontalSpeed = getConnection().addStream(flightParameters, "getHorizontalSpeed");
- } catch (RPCException | StreamException ignored) {
- }
+ public Navigation(ConnectionManager connectionManager, Vessel currentVessel) {
+ this.connectionManager = connectionManager;
+ this.currentVessel = currentVessel;
+ try {
+ // drawing = Drawing.newInstance(getConexao());
+ orbitalReference = currentVessel.getOrbit().getBody().getReferenceFrame();
+ flightParameters = currentVessel.flight(orbitalReference);
+ horizontalSpeed =
+ connectionManager.getConnection().addStream(flightParameters, "getHorizontalSpeed");
+ } catch (RPCException | StreamException e) {
+ throw new IllegalStateException("ERRO: Inicialização de parâmetros de navegação.", e);
}
+ }
- public void aimAtManeuver(Node maneuver) throws RPCException {
- aimAtDirection(getSpaceCenter().transformDirection(PROGRADE, maneuver.getReferenceFrame(), orbitalReference));
- }
+ public void aimAtManeuverNode(Node maneuver) throws RPCException {
+ currentVessel.getAutoPilot().setReferenceFrame(maneuver.getReferenceFrame());
+ currentVessel.getAutoPilot().setTargetDirection(PROGRADE);
+ }
- public void aimForLanding() throws RPCException, StreamException {
- Vector currentPosition = new Vector(currentVessel.position(orbitalReference));
- Vector retrograde = new Vector(getSpaceCenter().transformPosition(RETROGRADE,
- currentVessel.getSurfaceVelocityReferenceFrame(), orbitalReference)).subtract(currentPosition);
- Vector radial = new Vector(getSpaceCenter().transformDirection(RADIAL, currentVessel.getSurfaceReferenceFrame(),
- orbitalReference));
- double angleLimit = Utilities.remap(0, 10, 0, 0.9, horizontalSpeed.get(), true);
- Vector landingVector = Utilities.linearInterpolation(radial, retrograde, angleLimit);
- aimAtDirection(landingVector.toTriplet());
- }
+ public void aimForLanding() throws RPCException, StreamException {
+ Vector retrograde =
+ new Vector(
+ transformDirection(RETROGRADE, currentVessel.getSurfaceVelocityReferenceFrame()));
+ Vector radial =
+ new Vector(transformDirection(RADIAL, currentVessel.getSurfaceReferenceFrame()));
- // public void aimAtTarget() throws RPCException, StreamException,
- // InterruptedException {
- // Vector currentPosition = new Vector(naveAtual.position(pontoRefSuperficie));
- // Vector targetPosition = new
- // Vector(centroEspacial.getTargetVessel().position(pontoRefSuperficie));
- // targetPosition.x = 0.0;
- // double distanceToTarget = Vector.distance(currentPosition, targetPosition);
- //
- // Vector toTargetDirection = Vector.targetDirection(currentPosition,
- // targetPosition);
- // Vector oppositeDirection = Vector.targetOppositeDirection(currentPosition,
- // targetPosition);
- // Vector progradeDirection = Vector.targetDirection(currentPosition, new
- // Vector(
- // centroEspacial.transformPosition(PROGRADE,
- // naveAtual.getSurfaceVelocityReferenceFrame(),
- // pontoRefSuperficie
- // )));
- // Vector retrogradeDirection = Vector.targetDirection(currentPosition, new
- // Vector(
- // centroEspacial.transformPosition(RETROGRADE,
- // naveAtual.getSurfaceVelocityReferenceFrame(),
- // pontoRefSuperficie
- // )));
- // progradeDirection.x = 0.0;
- // retrogradeDirection.x = 0.0;
- // drawing.addDirection(toTargetDirection.toTriplet(), pontoRefSuperficie, 10,
- // true);
- // drawing.addDirection(oppositeDirection.toTriplet(), pontoRefSuperficie, 5,
- // true);
- // double pointingToTargetThreshold = Utilities.remap(0, 200, 0, 1,
- // distanceToTarget, true);
- // double speedThreshold = Utilities.remap(0, 20, 0, 1, horizontalSpeed.get(),
- // true);
- //
- // Vector currentDirection =
- // Utilities.linearInterpolation(oppositeDirection, toTargetDirection,
- // pointingToTargetThreshold);
- // double angleCurrentDirection =
- // new Vector(currentDirection.z, currentDirection.y,
- // currentDirection.x).heading();
- // double angleProgradeDirection =
- // new Vector(progradeDirection.z, progradeDirection.y,
- // progradeDirection.x).heading();
- // double deltaAngle = angleProgradeDirection - angleCurrentDirection;
- // System.out.println(deltaAngle);
- // if (deltaAngle > 3) {
- // currentDirection.sum(progradeDirection).normalize();
- // } else if (deltaAngle < -3) {
- // currentDirection.subtract(progradeDirection).normalize();
- // }
- // drawing.addDirection(currentDirection.toTriplet(), pontoRefSuperficie, 25,
- // true);
- //
- //
- // Vector currentDirectionOnOrbitalRef = new Vector(
- // centroEspacial.transformDirection(currentDirection.toTriplet(),
- // pontoRefSuperficie,
- // pontoRefOrbital));
- // Vector radial = new Vector(centroEspacial.transformDirection(RADIAL,
- // pontoRefSuperficie,
- // pontoRefOrbital));
- // Vector speedVector = Utilities.linearInterpolation(retrogradeDirection,
- // progradeDirection, speedThreshold);
- // Vector speedVectorOnOrbitalRef = new Vector(
- // centroEspacial.transformDirection(speedVector.toTriplet(),
- // pontoRefSuperficie,
- // pontoRefOrbital));
- // Vector pointingVector =
- // Utilities.linearInterpolation(currentDirectionOnOrbitalRef,
- // radial.sum(speedVectorOnOrbitalRef),
- // speedThreshold
- // );
- // Thread.sleep(50);
- // drawing.clear(false);
- // aimAtDirection(pointingVector.toTriplet());
- // }
-
- public void aimAtPrograde() throws RPCException {
- aimAtDirection(getSpaceCenter().transformDirection(PROGRADE, currentVessel.getSurfaceVelocityReferenceFrame(),
- orbitalReference));
- }
+ double angleLimit = Utilities.remap(0, 10, 0, 0.9, horizontalSpeed.get(), true);
+ Vector landingVector = Utilities.linearInterpolation(radial, retrograde, angleLimit);
+ aimAtDirection(landingVector.toTriplet());
+ }
- public void aimAtRadialOut() throws RPCException {
- aimAtDirection(getSpaceCenter().transformDirection(RADIAL, currentVessel.getSurfaceReferenceFrame(),
- orbitalReference));
- }
+ public void aimForDeorbit() throws RPCException {
+ aimAtDirection(flightParameters.getRetrograde());
+ }
- public void aimAtRetrograde() throws RPCException {
- aimAtDirection(getSpaceCenter().transformDirection(RETROGRADE, currentVessel.getSurfaceVelocityReferenceFrame(),
- orbitalReference));
- }
+ public void aimAtPrograde() throws RPCException {
+ transformAndAim(PROGRADE, currentVessel.getSurfaceVelocityReferenceFrame());
+ }
- public void aimAtDirection(Triplet currentDirection) throws RPCException {
- currentVessel.getAutoPilot().setReferenceFrame(orbitalReference);
- currentVessel.getAutoPilot().setTargetDirection(currentDirection);
- }
+ public void aimAtRadialOut() throws RPCException {
+ transformAndAim(RADIAL, currentVessel.getSurfaceReferenceFrame());
+ }
+
+ public void aimAtRetrograde() throws RPCException {
+ transformAndAim(RETROGRADE, currentVessel.getSurfaceVelocityReferenceFrame());
+ }
+
+ public void aimAtDirection(Triplet currentDirection) throws RPCException {
+ currentVessel.getAutoPilot().setReferenceFrame(orbitalReference);
+ currentVessel.getAutoPilot().setTargetDirection(currentDirection);
+ }
+
+ // Método auxiliar para evitar duplicação
+ private void transformAndAim(
+ Triplet direction, ReferenceFrame referenceFrame)
+ throws RPCException {
+ aimAtDirection(transformDirection(direction, referenceFrame));
+ }
+
+ // Método auxiliar sobrecarregado para clareza
+ private Triplet transformDirection(
+ Triplet direction, ReferenceFrame fromReference) throws RPCException {
+ return connectionManager
+ .getSpaceCenter()
+ .transformDirection(direction, fromReference, orbitalReference);
+ }
+ // public void aimAtTarget() throws RPCException, StreamException, InterruptedException {
+ // Vector currentPosition = new Vector(naveAtual.position(pontoRefSuperficie));
+ // Vector targetPosition =
+ // new Vector(centroEspacial.getTargetVessel().position(pontoRefSuperficie));
+ // targetPosition.x = 0.0;
+ // double distanceToTarget = Vector.distance(currentPosition, targetPosition);
+ //
+ // Vector toTargetDirection = Vector.targetDirection(currentPosition, targetPosition);
+ // Vector oppositeDirection = Vector.targetOppositeDirection(currentPosition, targetPosition);
+ // Vector progradeDirection =
+ // Vector.targetDirection(
+ // currentPosition,
+ // new Vector(
+ // centroEspacial.transformPosition(
+ // PROGRADE, naveAtual.getSurfaceVelocityReferenceFrame(), pontoRefSuperficie)));
+ // Vector retrogradeDirection =
+ // Vector.targetDirection(
+ // currentPosition,
+ // new Vector(
+ // centroEspacial.transformPosition(
+ // RETROGRADE, naveAtual.getSurfaceVelocityReferenceFrame(), pontoRefSuperficie)));
+ // progradeDirection.x = 0.0;
+ // retrogradeDirection.x = 0.0;
+ // drawing.addDirection(toTargetDirection.toTriplet(), pontoRefSuperficie, 10, true);
+ // drawing.addDirection(oppositeDirection.toTriplet(), pontoRefSuperficie, 5, true);
+ // double pointingToTargetThreshold = Utilities.remap(0, 200, 0, 1, distanceToTarget, true);
+ // double speedThreshold = Utilities.remap(0, 20, 0, 1, horizontalSpeed.get(), true);
+ //
+ // Vector currentDirection =
+ // Utilities.linearInterpolation(
+ // oppositeDirection, toTargetDirection, pointingToTargetThreshold);
+ // double angleCurrentDirection =
+ // new Vector(currentDirection.z, currentDirection.y, currentDirection.x).heading();
+ // double angleProgradeDirection =
+ // new Vector(progradeDirection.z, progradeDirection.y, progradeDirection.x).heading();
+ // double deltaAngle = angleProgradeDirection - angleCurrentDirection;
+ // System.out.println(deltaAngle);
+ // if (deltaAngle > 3) {
+ // currentDirection.sum(progradeDirection).normalize();
+ // } else if (deltaAngle < -3) {
+ // currentDirection.subtract(progradeDirection).normalize();
+ // }
+ // drawing.addDirection(currentDirection.toTriplet(), pontoRefSuperficie, 25, true);
+ //
+ // Vector currentDirectionOnOrbitalRef =
+ // new Vector(
+ // transformDirection(currentDirection.toTriplet(), pontoRefSuperficie));
+ // Vector radial =
+ // new Vector(centroEspacial.transformDirection(RADIAL, pontoRefSuperficie, pontoRefOrbital));
+ // Vector speedVector =
+ // Utilities.linearInterpolation(retrogradeDirection, progradeDirection, speedThreshold);
+ // Vector speedVectorOnOrbitalRef =
+ // new Vector(
+ // centroEspacial.transformDirection(
+ // speedVector.toTriplet(), pontoRefSuperficie, pontoRefOrbital));
+ // Vector pointingVector =
+ // Utilities.linearInterpolation(
+ // currentDirectionOnOrbitalRef, radial.sum(speedVectorOnOrbitalRef), speedThreshold);
+ // Thread.sleep(50);
+ // drawing.clear(false);
+ // aimAtDirection(pointingVector.toTriplet());
+ // }
}
diff --git a/src/main/java/com/pesterenan/utils/PathFinding.java b/src/main/java/com/pesterenan/utils/PathFinding.java
index f55510f..700125d 100644
--- a/src/main/java/com/pesterenan/utils/PathFinding.java
+++ b/src/main/java/com/pesterenan/utils/PathFinding.java
@@ -1,216 +1,259 @@
package com.pesterenan.utils;
-import com.pesterenan.controllers.Controller;
-import krpc.client.RPCException;
-import krpc.client.services.Drawing;
-import krpc.client.services.SpaceCenter;
-import krpc.client.services.SpaceCenter.Waypoint;
-import krpc.client.services.SpaceCenter.WaypointManager;
-import org.javatuples.Triplet;
-
+import com.pesterenan.model.ConnectionManager;
+import com.pesterenan.model.VesselManager;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.stream.Collectors;
+import krpc.client.RPCException;
+import krpc.client.services.Drawing;
+import krpc.client.services.SpaceCenter;
+import krpc.client.services.SpaceCenter.Waypoint;
+import krpc.client.services.SpaceCenter.WaypointManager;
+import org.javatuples.Triplet;
-import static com.pesterenan.MechPeste.getConnection;
-import static com.pesterenan.MechPeste.getSpaceCenter;
+public class PathFinding {
-public class PathFinding extends Controller {
+ private WaypointManager waypointManager;
+ private String waypointName;
+ private List waypointsToReach;
+ private List pathToTarget;
+ private Drawing drawing;
+ private Drawing.Polygon polygonPath;
+ private final ConnectionManager connectionManager;
+ private final VesselManager vesselManager;
- private WaypointManager waypointManager;
- private String waypointName;
- private List waypointsToReach;
- private List pathToTarget;
- private Drawing drawing;
- private Drawing.Polygon polygonPath;
+ public PathFinding(ConnectionManager connectionManager, VesselManager vesselManager) {
+ this.connectionManager = connectionManager;
+ this.vesselManager = vesselManager;
+ initializeParameters();
+ }
- public PathFinding() {
- super();
- initializeParameters();
+ private void initializeParameters() {
+ try {
+ waypointManager = connectionManager.getSpaceCenter().getWaypointManager();
+ waypointsToReach = new ArrayList<>();
+ pathToTarget = new ArrayList<>();
+ drawing = Drawing.newInstance(connectionManager.getConnection());
+ } catch (RPCException ignored) {
}
+ }
- private void initializeParameters() {
- try {
- waypointManager = getSpaceCenter().getWaypointManager();
- waypointsToReach = new ArrayList<>();
- pathToTarget = new ArrayList<>();
- drawing = Drawing.newInstance(getConnection());
- } catch (RPCException ignored) {
- }
- }
+ public void addWaypointsOnSameBody(String waypointName) throws RPCException {
+ this.waypointName = waypointName;
+ this.waypointsToReach =
+ waypointManager.getWaypoints().stream()
+ .filter(this::hasSameName)
+ .collect(Collectors.toList());
+ }
- public void addWaypointsOnSameBody(String waypointName) throws RPCException {
- this.waypointName = waypointName;
- this.waypointsToReach = waypointManager.getWaypoints().stream().filter(this::hasSameName)
- .collect(Collectors.toList());
+ private boolean hasSameName(Waypoint waypoint) {
+ try {
+ return waypoint.getName().toLowerCase().contains(waypointName.toLowerCase())
+ && waypoint.getBody().equals(vesselManager.getCurrentVessel().currentBody);
+ } catch (RPCException e) {
+ return false;
}
+ }
- private boolean hasSameName(Waypoint waypoint) {
- try {
- return waypoint.getName().toLowerCase().contains(waypointName.toLowerCase())
- && waypoint.getBody().equals(currentBody);
- } catch (RPCException e) {
- return false;
- }
- }
+ public Vector findNearestWaypoint() throws RPCException, IOException, InterruptedException {
+ waypointsToReach =
+ waypointsToReach.stream()
+ .sorted(
+ (w1, w2) -> {
+ double w1Distance = 0;
+ double w2Distance = 0;
+ try {
+ w1Distance =
+ Vector.distance(
+ new Vector(
+ vesselManager
+ .getCurrentVessel()
+ .getActiveVessel()
+ .position(
+ vesselManager.getCurrentVessel().orbitalReferenceFrame)),
+ waypointPosOnSurface(w1));
+ w2Distance =
+ Vector.distance(
+ new Vector(
+ vesselManager
+ .getCurrentVessel()
+ .getActiveVessel()
+ .position(
+ vesselManager.getCurrentVessel().orbitalReferenceFrame)),
+ waypointPosOnSurface(w2));
+ } catch (RPCException e) {
+ }
+ return w1Distance > w2Distance ? 1 : -1;
+ })
+ .collect(Collectors.toList());
+ waypointsToReach.forEach(System.out::println);
+ Waypoint currentWaypoint = waypointsToReach.get(0);
+ return waypointPosOnSurface(currentWaypoint);
+ }
- public Vector findNearestWaypoint() throws RPCException, IOException, InterruptedException {
- waypointsToReach = waypointsToReach.stream().sorted((w1, w2) -> {
- double w1Distance = 0;
- double w2Distance = 0;
- try {
- w1Distance = Vector.distance(new Vector(getActiveVessel().position(orbitalReferenceFrame)),
- waypointPosOnSurface(w1));
- w2Distance = Vector.distance(new Vector(getActiveVessel().position(orbitalReferenceFrame)),
- waypointPosOnSurface(w2));
- } catch (RPCException e) {
- }
- return w1Distance > w2Distance ? 1 : -1;
- }).collect(Collectors.toList());
- waypointsToReach.forEach(System.out::println);
- Waypoint currentWaypoint = waypointsToReach.get(0);
- // for (Waypoint waypoint : waypointsToReach) {
- // double waypointDistance = Vector.distance(new
- // Vector(getNaveAtual().position(orbitalReferenceFrame)),
- // waypointPosOnSurface(waypoint)
- // );
- // if (currentDistance > waypointDistance) {
- // currentDistance = waypointDistance;
- // currentWaypoint = waypoint;
- // }
- // }
- return waypointPosOnSurface(currentWaypoint);
- }
+ private Vector waypointPosOnSurface(Waypoint waypoint) throws RPCException {
+ return new Vector(
+ vesselManager
+ .getCurrentVessel()
+ .currentBody
+ .surfacePosition(
+ waypoint.getLatitude(),
+ waypoint.getLongitude(),
+ vesselManager.getCurrentVessel().orbitalReferenceFrame));
+ }
- private Vector waypointPosOnSurface(Waypoint waypoint) throws RPCException {
- return new Vector(
- currentBody.surfacePosition(waypoint.getLatitude(), waypoint.getLongitude(), orbitalReferenceFrame));
- }
+ public boolean isPathToTargetEmpty() {
+ return pathToTarget.isEmpty();
+ }
- public boolean isPathToTargetEmpty() {
- return pathToTarget.isEmpty();
- }
+ public boolean isWaypointsToReachEmpty() {
+ boolean allFromContract =
+ waypointsToReach.stream()
+ .allMatch(
+ v -> {
+ try {
+ return v.getHasContract();
+ } catch (RPCException ignored) {
+ }
+ return false;
+ });
+ return waypointsToReach.isEmpty() || allFromContract;
+ }
- public boolean isWaypointsToReachEmpty() {
- boolean allFromContract = waypointsToReach.stream().allMatch(v -> {
- try {
- return v.getHasContract();
- } catch (RPCException ignored) {
- }
- return false;
- });
- return waypointsToReach.isEmpty() || allFromContract;
- }
+ public Vector getPathsFirstPoint() {
+ return pathToTarget.get(0);
+ }
- public Vector getPathsFirstPoint() {
- return pathToTarget.get(0);
+ public void removePathsCurrentPoint() {
+ if (isPathToTargetEmpty()) {
+ return;
}
+ pathToTarget.remove(0);
+ }
- public void removePathsCurrentPoint() {
- if (isPathToTargetEmpty()) {
- return;
- }
- pathToTarget.remove(0);
+ public void removeWaypointFromList() throws RPCException {
+ if (waypointsToReach.isEmpty()) {
+ return;
}
+ waypointsToReach.remove(0);
+ }
- public void removeWaypointFromList() throws RPCException {
- if (waypointsToReach.isEmpty()) {
- return;
- }
- waypointsToReach.remove(0);
+ public void buildPathToTarget(Vector targetPosition)
+ throws IOException, RPCException, InterruptedException {
+ Vector roverHeight = new Vector(0.2, 0.0, 0.0);
+ Vector currentRoverPos =
+ transformSurfToOrb(
+ new Vector(
+ vesselManager
+ .getCurrentVessel()
+ .getActiveVessel()
+ .position(vesselManager.getCurrentVessel().surfaceReferenceFrame))
+ .sum(roverHeight));
+ double distanceToTarget = Vector.distance(currentRoverPos, targetPosition);
+ pathToTarget.add(currentRoverPos);
+ int index = 0;
+ while (distanceToTarget > 50) {
+ if (Thread.interrupted()) {
+ throw new InterruptedException();
+ }
+ Vector currentPoint = pathToTarget.get(index);
+ Vector targetDirection =
+ transformOrbToSurf(targetPosition).subtract(transformOrbToSurf(currentPoint)).normalize();
+ Vector nextPoint =
+ transformSurfToOrb(calculateNextPoint(transformOrbToSurf(currentPoint), targetDirection));
+ pathToTarget.add(nextPoint);
+ index++;
+ double distanceBetweenPoints =
+ Vector.distance(transformOrbToSurf(currentPoint), transformOrbToSurf(nextPoint));
+ distanceToTarget -= distanceBetweenPoints;
}
+ pathToTarget.add(getPosOnSurface(targetPosition));
+ drawPathToTarget(pathToTarget);
+ }
- /**
- * Builds the path to the targetPosition, on the Celestial Body Reference (
- * Orbital Ref )
- *
- * @param targetPosition
- * the target pos to build the path to
- * @throws IOException
- * @throws RPCException
- * @throws InterruptedException
- */
- public void buildPathToTarget(Vector targetPosition) throws IOException, RPCException, InterruptedException {
- // Get current rover Position on Orbital Ref, transform to Surf Ref and add 20
- // centimeters on height:
- Vector roverHeight = new Vector(0.2, 0.0, 0.0);
- Vector currentRoverPos = transformSurfToOrb(
- new Vector(getActiveVessel().position(surfaceReferenceFrame)).sum(roverHeight));
- // Calculate distance from rover to target on Orbital Ref:
- double distanceToTarget = Vector.distance(currentRoverPos, targetPosition);
- // Add rover pos as first point, on Orbital Ref
- pathToTarget.add(currentRoverPos);
- // Calculate the next points positions and add to the list on Orbital Ref
- int index = 0;
- while (distanceToTarget > 50) {
- if (Thread.interrupted()) {
- throw new InterruptedException();
- }
- Vector currentPoint = pathToTarget.get(index);
- Vector targetDirection = transformOrbToSurf(targetPosition).subtract(transformOrbToSurf(currentPoint))
- .normalize();
- Vector nextPoint = transformSurfToOrb(
- calculateNextPoint(transformOrbToSurf(currentPoint), targetDirection));
- pathToTarget.add(nextPoint);
- index++;
- double distanceBetweenPoints = Vector.distance(transformOrbToSurf(currentPoint),
- transformOrbToSurf(nextPoint));
- distanceToTarget -= distanceBetweenPoints;
- }
- pathToTarget.add(getPosOnSurface(targetPosition));
- drawPathToTarget(pathToTarget);
- }
+ private void drawPathToTarget(List path) throws RPCException {
+ Deque> drawablePath =
+ path.stream().map(Vector::toTriplet).collect(Collectors.toCollection(ArrayDeque::new));
+ drawablePath.offerFirst(new Triplet<>(0.0, 0.0, 0.0));
+ drawablePath.offerLast(new Triplet<>(0.0, 0.0, 0.0));
+ polygonPath =
+ drawing.addPolygon(
+ drawablePath.stream().collect(Collectors.toList()),
+ vesselManager.getCurrentVessel().orbitalReferenceFrame,
+ true);
+ polygonPath.setThickness(0.5f);
+ polygonPath.setColor(new Triplet<>(1.0, 0.5, 0.0));
+ }
- private void drawPathToTarget(List path) throws RPCException {
- Deque> drawablePath = path.stream().map(Vector::toTriplet)
- .collect(Collectors.toCollection(ArrayDeque::new));
- drawablePath.offerFirst(new Triplet<>(0.0, 0.0, 0.0));
- drawablePath.offerLast(new Triplet<>(0.0, 0.0, 0.0));
- polygonPath = drawing.addPolygon(drawablePath.stream().collect(Collectors.toList()), orbitalReferenceFrame,
- true);
- polygonPath.setThickness(0.5f);
- polygonPath.setColor(new Triplet<>(1.0, 0.5, 0.0));
+ public void removeDrawnPath() {
+ try {
+ polygonPath.remove();
+ } catch (RPCException ignored) {
}
+ }
- public void removeDrawnPath() {
- try {
- polygonPath.remove();
- } catch (RPCException ignored) {
- }
- }
+ private Vector calculateNextPoint(Vector currentPoint, Vector targetDirection)
+ throws RPCException, IOException {
+ double stepDistance = 100.0;
+ Vector nextPoint =
+ getPosOnSurface(
+ transformSurfToOrb(currentPoint.sum(targetDirection.multiply(stepDistance))));
+ return transformOrbToSurf(nextPoint).sum(new Vector(0.2, 0.0, 0.0));
+ }
- private Vector calculateNextPoint(Vector currentPoint, Vector targetDirection) throws RPCException, IOException {
- // PONTO REF SUPERFICIE: X = CIMA, Y = NORTE, Z = LESTE;
- double stepDistance = 100.0;
- // Calculate the next point position on surface:
- Vector nextPoint = getPosOnSurface(
- transformSurfToOrb(currentPoint.sum(targetDirection.multiply(stepDistance))));
- return transformOrbToSurf(nextPoint).sum(new Vector(0.2, 0.0, 0.0));
- }
-
- public double raycastDistance(Vector currentPoint, Vector targetDirection, SpaceCenter.ReferenceFrame reference,
- double searchDistance) throws RPCException {
- return Math.min(
- getSpaceCenter().raycastDistance(currentPoint.toTriplet(), targetDirection.toTriplet(), reference),
- searchDistance);
- }
+ public double raycastDistance(
+ Vector currentPoint,
+ Vector targetDirection,
+ SpaceCenter.ReferenceFrame reference,
+ double searchDistance)
+ throws RPCException {
+ return Math.min(
+ connectionManager
+ .getSpaceCenter()
+ .raycastDistance(currentPoint.toTriplet(), targetDirection.toTriplet(), reference),
+ searchDistance);
+ }
- private Vector getPosOnSurface(Vector vector) throws RPCException {
- return new Vector(currentBody.surfacePosition(
- currentBody.latitudeAtPosition(vector.toTriplet(), orbitalReferenceFrame),
- currentBody.longitudeAtPosition(vector.toTriplet(), orbitalReferenceFrame), orbitalReferenceFrame));
- }
+ private Vector getPosOnSurface(Vector vector) throws RPCException {
+ return new Vector(
+ vesselManager
+ .getCurrentVessel()
+ .currentBody
+ .surfacePosition(
+ vesselManager
+ .getCurrentVessel()
+ .currentBody
+ .latitudeAtPosition(
+ vector.toTriplet(), vesselManager.getCurrentVessel().orbitalReferenceFrame),
+ vesselManager
+ .getCurrentVessel()
+ .currentBody
+ .longitudeAtPosition(
+ vector.toTriplet(), vesselManager.getCurrentVessel().orbitalReferenceFrame),
+ vesselManager.getCurrentVessel().orbitalReferenceFrame));
+ }
- private Vector transformSurfToOrb(Vector vector) throws IOException, RPCException {
- return new Vector(
- getSpaceCenter().transformPosition(vector.toTriplet(), surfaceReferenceFrame, orbitalReferenceFrame));
- }
+ private Vector transformSurfToOrb(Vector vector) throws IOException, RPCException {
+ return new Vector(
+ connectionManager
+ .getSpaceCenter()
+ .transformPosition(
+ vector.toTriplet(),
+ vesselManager.getCurrentVessel().surfaceReferenceFrame,
+ vesselManager.getCurrentVessel().orbitalReferenceFrame));
+ }
- private Vector transformOrbToSurf(Vector vector) throws IOException, RPCException {
- return new Vector(
- getSpaceCenter().transformPosition(vector.toTriplet(), orbitalReferenceFrame, surfaceReferenceFrame));
- }
+ private Vector transformOrbToSurf(Vector vector) throws IOException, RPCException {
+ return new Vector(
+ connectionManager
+ .getSpaceCenter()
+ .transformPosition(
+ vector.toTriplet(),
+ vesselManager.getCurrentVessel().orbitalReferenceFrame,
+ vesselManager.getCurrentVessel().surfaceReferenceFrame));
+ }
}
diff --git a/src/main/java/com/pesterenan/utils/Telemetry.java b/src/main/java/com/pesterenan/utils/Telemetry.java
index ab46f77..96975ec 100644
--- a/src/main/java/com/pesterenan/utils/Telemetry.java
+++ b/src/main/java/com/pesterenan/utils/Telemetry.java
@@ -1,5 +1,10 @@
package com.pesterenan.utils;
public enum Telemetry {
- ALT_SURF, ALTITUDE, APOAPSIS, PERIAPSIS, HORZ_SPEED, VERT_SPEED,
+ ALT_SURF,
+ ALTITUDE,
+ APOAPSIS,
+ PERIAPSIS,
+ HORZ_SPEED,
+ VERT_SPEED,
}
diff --git a/src/main/java/com/pesterenan/utils/Utilities.java b/src/main/java/com/pesterenan/utils/Utilities.java
index a310da6..1ef0687 100644
--- a/src/main/java/com/pesterenan/utils/Utilities.java
+++ b/src/main/java/com/pesterenan/utils/Utilities.java
@@ -4,79 +4,90 @@
public class Utilities {
- public static double linearInterpolation(double start, double end, double value) {
- return (1.0 - value) * start + value * end;
- }
+ public static double linearInterpolation(double start, double end, double value) {
+ return (1.0 - value) * start + value * end;
+ }
- public static Vector linearInterpolation(Vector start, Vector end, double value) {
- double x = linearInterpolation(start.x, end.x, value);
- double y = linearInterpolation(start.y, end.y, value);
- double z = linearInterpolation(start.z, end.z, value);
- return new Vector(x, y, z);
- }
+ public static Vector linearInterpolation(Vector start, Vector end, double value) {
+ double x = linearInterpolation(start.x, end.x, value);
+ double y = linearInterpolation(start.y, end.y, value);
+ double z = linearInterpolation(start.z, end.z, value);
+ return new Vector(x, y, z);
+ }
- public static double inverseLinearInterpolation(double start, double end, double value) {
- return (value - start) / (end - start);
- }
+ public static double inverseLinearInterpolation(double start, double end, double value) {
+ return (value - start) / (end - start);
+ }
- public static Vector inverseLinearInterpolation(Vector start, Vector end, double value) {
- double x = inverseLinearInterpolation(start.x, end.x, value);
- double y = inverseLinearInterpolation(start.y, end.y, value);
- double z = inverseLinearInterpolation(start.z, end.z, value);
- return new Vector(x, y, z);
- }
+ public static Vector inverseLinearInterpolation(Vector start, Vector end, double value) {
+ double x = inverseLinearInterpolation(start.x, end.x, value);
+ double y = inverseLinearInterpolation(start.y, end.y, value);
+ double z = inverseLinearInterpolation(start.z, end.z, value);
+ return new Vector(x, y, z);
+ }
- public static double remap(double inputMin, double inputMax, double outputMin, double outputMax, double value,
- boolean clampOutput) {
- double between = inverseLinearInterpolation(inputMin, inputMax, value);
- double remappedOutput = linearInterpolation(outputMin, outputMax, between);
- return clampOutput ? clamp(remappedOutput, outputMin, outputMax) : remappedOutput;
- }
+ public static double remap(
+ double inputMin,
+ double inputMax,
+ double outputMin,
+ double outputMax,
+ double value,
+ boolean clampOutput) {
+ double between = inverseLinearInterpolation(inputMin, inputMax, value);
+ double remappedOutput = linearInterpolation(outputMin, outputMax, between);
+ return clampOutput ? clamp(remappedOutput, outputMin, outputMax) : remappedOutput;
+ }
- public static double clamp(double value, double minimum, double maximum) {
- return Math.max(Math.min(value, maximum), minimum);
- }
+ public static double clamp(double value, double minimum, double maximum) {
+ return Math.max(Math.min(value, maximum), minimum);
+ }
- // Easing functions
- public static double easeInCirc(double value) {
- return 1 - Math.sqrt(1 - Math.pow(clamp(value, 0, 1), 2));
- }
+ // Easing functions
+ public static double easeInCirc(double value) {
+ return 1 - Math.sqrt(1 - Math.pow(clamp(value, 0, 1), 2));
+ }
- public static double easeInSine(double value) {
- return 1 - Math.cos((value * Math.PI) / 2);
- }
+ public static double easeInSine(double value) {
+ return 1 - Math.cos((value * Math.PI) / 2);
+ }
- public static double easeInQuad(double value) {
- return Math.pow(value, 2);
- }
+ public static double easeInQuad(double value) {
+ return Math.pow(value, 2);
+ }
- public static double easeInCubic(double value) {
- return Math.pow(value, 3);
- }
+ public static double easeInCubic(double value) {
+ return Math.pow(value, 3);
+ }
- public static double easeInExpo(double value) {
- return value == 0 ? 0 : Math.pow(2, 10 * value - 10);
- }
+ public static double easeInExpo(double value) {
+ return value == 0 ? 0 : Math.pow(2, 10 * value - 10);
+ }
- public static String convertToMetersMagnitudes(double meters) {
- String decimalPlaces = "%.2f"; //$NON-NLS-1$
- if (meters >= 1000000000) {
- return String.format(decimalPlaces + "Gm", meters / 1000000000); //$NON-NLS-1$
- } else if (meters >= 1000000) {
- return String.format(decimalPlaces + "Mm", meters / 1000000); //$NON-NLS-1$
- } else if (meters >= 1000) {
- return String.format(decimalPlaces + "km", meters / 1000); //$NON-NLS-1$
- } else {
- return String.format(decimalPlaces + "m", meters); //$NON-NLS-1$
- }
+ public static String convertToMetersMagnitudes(double meters) {
+ String decimalPlaces = "%.2f"; // $NON-NLS-1$
+ if (meters >= 1000000000) {
+ return String.format(decimalPlaces + "Gm", meters / 1000000000); // $NON-NLS-1$
+ } else if (meters >= 1000000) {
+ return String.format(decimalPlaces + "Mm", meters / 1000000); // $NON-NLS-1$
+ } else if (meters >= 1000) {
+ return String.format(decimalPlaces + "km", meters / 1000); // $NON-NLS-1$
+ } else {
+ return String.format(decimalPlaces + "m", meters); // $NON-NLS-1$
}
+ }
- public String formatElapsedTime(Double totalSeconds) {
- int years = (totalSeconds.intValue() / 9201600);
- int days = (totalSeconds.intValue() / 21600) % 426;
- int hours = (totalSeconds.intValue() / 3600) % 6;
- int minutes = (totalSeconds.intValue() % 3600) / 60;
- int seconds = totalSeconds.intValue() % 60;
- return String.format(Bundle.getString("pnl_tel_lbl_date_template"), years, days, hours, minutes, seconds); // $NON-NLS-1$
- }
+ public String formatElapsedTime(Double totalSeconds) {
+ int years = (totalSeconds.intValue() / 9201600);
+ int days = (totalSeconds.intValue() / 21600) % 426;
+ int hours = (totalSeconds.intValue() / 3600) % 6;
+ int minutes = (totalSeconds.intValue() % 3600) / 60;
+ int seconds = totalSeconds.intValue() % 60;
+ return String.format(
+ Bundle.getString("pnl_tel_lbl_date_template"),
+ years,
+ days,
+ hours,
+ minutes,
+ seconds); // $NON-NLS-1$
+ }
}
diff --git a/src/main/java/com/pesterenan/utils/Vector.java b/src/main/java/com/pesterenan/utils/Vector.java
index 2919433..975b8c6 100644
--- a/src/main/java/com/pesterenan/utils/Vector.java
+++ b/src/main/java/com/pesterenan/utils/Vector.java
@@ -4,234 +4,212 @@
public class Vector {
- public double x = 0;
- public double y = 0;
- public double z = 0;
-
- public Vector() {
-
- }
-
- /**
- * Cria um vetor informando valores X,Y,Z manualmente
- *
- * @param X
- * - Valor eixo X
- * @param Y
- * - Valor eixo Y
- * @param Z
- * - Valor eixo Z
- */
- public Vector(double X, double Y, double Z) {
- this.x = X;
- this.y = Y;
- this.z = Z;
- }
-
- /**
- * Cria um vetor a partir de outro Vetor
- *
- * @param newVector
- * - Outro Vetor
- */
- public Vector(Vector newVector) {
- this.x = newVector.x;
- this.y = newVector.y;
- this.z = newVector.z;
- }
-
- /**
- * Cria um vetor com valores de uma tupla (Triplet)
- *
- * @param triplet
- * - Triplet com valores X,Y,Z em conjunto
- */
- public Vector(Triplet triplet) {
- this.x = triplet.getValue0();
- this.y = triplet.getValue1();
- this.z = triplet.getValue2();
- }
-
- /**
- * Calcula o ângulo do vetor de direção informado
- *
- * @return - O ângulo da direção desse vetor, entre -180 a 180 graus.
- */
- public double heading() {
- return Math.toDegrees(Math.atan2(this.y, this.x));
- }
-
- public static double distance(Vector start, Vector end) {
- return end.subtract(start).magnitude();
- }
-
- /**
- * Calcula o Vetor da direção do ponto de origem até o alvo.
- *
- * @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.
- */
- public static Vector targetDirection(Vector start, Vector end) {
- return end.subtract(start).normalize();
- }
-
- /**
- * Calcula o Vetor da direção CONTRÁRIA do ponto de origem até o alvo.
- *
- * @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.
- */
- public static Vector targetOppositeDirection(Vector start, Vector end) {
- return end.subtract(start).multiply(-1).normalize();
- }
-
- /**
- * Retorna um String com os valores do Vetor
- *
- * @return ex: "(X: 3.0, Y: 4.0, Z: 5.0)"
- */
- @Override
- public String toString() {
- return String.format("( X: %.2f Y: %.2f Z: %.2f)", this.x, this.y, this.z);
- }
-
- /**
- * Modifica um vetor informando novos valores X,Y,Z
- *
- * @param X
- * - Valor eixo X
- * @param Y
- * - Valor eixo Y
- * @param Z
- * - Valor eixo Z
- */
- public void setVector(double X, double Y, double Z) {
- this.x = X;
- this.y = Y;
- this.z = Z;
- }
-
- /**
- * @return Retorna um novo Vetor com os valores X e Y invertidos
- */
- public Vector invertXY() {
- return new Vector(y, x, z);
- }
-
- /**
- * Magnitude do Vetor
- *
- * @return Retorna a magnitude (comprimento) do Vetor no eixo X e Y.
- */
- public double magnitudeXY() {
- return Math.sqrt(x * x + y * y);
- }
-
- /**
- * Magnitude do Vetor
- *
- * @return Retorna a magnitude (comprimento) do Vetor em todos os eixos.
- */
- public double magnitude() {
- return Math.sqrt(x * x + y * y + z * z);
- }
-
- /**
- * Normalizar Vetor
- *
- * @return Retorna um novo Vetor normalizado (magnitude de 1).
- */
- public Vector normalize() {
- double m = magnitude();
- if (m != 0) {
- return new Vector(x / m, y / m, z / m);
- }
- return new Vector(x, y, z);
- }
-
- /**
- * Soma os componentes de outro vetor com o vetor informado
- *
- * @param otherVector
- * - Vetor para somar os componentes
- * @return Novo vetor com a soma dos componentes dos dois
- */
-
- public double dotProduct(Vector otherVector) {
- return (x * otherVector.x + y * otherVector.y + z * otherVector.z);
- }
-
- public double determinant(Vector otherVector) {
- return (x * otherVector.z - y * otherVector.y - z * otherVector.x);
- }
-
- /**
- * Soma os componentes de outro vetor com o vetor informado
- *
- * @param otherVector
- * - Vetor para somar os componentes
- * @return Novo vetor com a soma dos componentes dos dois
- */
- public Vector sum(Vector otherVector) {
- return new Vector(x + otherVector.x, y + otherVector.y, z + otherVector.z);
- }
-
- /**
- * Subtrai os componentes de outro vetor com o vetor informado
- *
- * @param otherVector
- * - Vetor para subtrair os componentes
- * @return Novo vetor com a subtração dos componentes dos dois
- */
- public Vector subtract(Vector otherVector) {
- return new Vector(x - otherVector.x, y - otherVector.y, z - otherVector.z);
- }
-
- /**
- * Multiplica os componentes desse vetor por uma escalar
- *
- * @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.
- */
- public Vector multiply(double scalar) {
- if (scalar != 0) {
- return new Vector(x * scalar, y * scalar, z * scalar);
- }
- return new Vector(0, 0, 0);
- }
-
- /**
- * Divide os componentes desse vetor por uma escalar
- *
- * @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.
- */
- public Vector divide(double scalar) {
- if (scalar != 0) {
- return new Vector(x / scalar, y / scalar, z / scalar);
- }
- return new Vector(0, 0, 0);
- }
-
- /**
- * Transforma um Vetor em uma tupla com os valores.
- *
- * @return - Nova tupla contendo os valores do vetor em seus componentes.
- */
- public Triplet toTriplet() {
- return new Triplet<>(this.x, this.y, this.z);
- }
+ public double x = 0;
+ public double y = 0;
+ public double z = 0;
+
+ public Vector() {}
+
+ /**
+ * Cria um vetor informando valores X,Y,Z manualmente
+ *
+ * @param X - Valor eixo X
+ * @param Y - Valor eixo Y
+ * @param Z - Valor eixo Z
+ */
+ public Vector(double X, double Y, double Z) {
+ this.x = X;
+ this.y = Y;
+ this.z = Z;
+ }
+
+ /**
+ * Cria um vetor a partir de outro Vetor
+ *
+ * @param newVector - Outro Vetor
+ */
+ public Vector(Vector newVector) {
+ this.x = newVector.x;
+ this.y = newVector.y;
+ this.z = newVector.z;
+ }
+
+ /**
+ * Cria um vetor com valores de uma tupla (Triplet)
+ *
+ * @param triplet - Triplet com valores X,Y,Z em conjunto
+ */
+ public Vector(Triplet triplet) {
+ this.x = triplet.getValue0();
+ this.y = triplet.getValue1();
+ this.z = triplet.getValue2();
+ }
+
+ /**
+ * Calcula o ângulo do vetor de direção informado
+ *
+ * @return - O ângulo da direção desse vetor, entre -180 a 180 graus.
+ */
+ public double heading() {
+ return Math.toDegrees(Math.atan2(this.y, this.x));
+ }
+
+ public static double distance(Vector start, Vector end) {
+ return end.subtract(start).magnitude();
+ }
+
+ /**
+ * Calcula o Vetor da direção do ponto de origem até o alvo.
+ *
+ * @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.
+ */
+ public static Vector targetDirection(Vector start, Vector end) {
+ return end.subtract(start).normalize();
+ }
+
+ /**
+ * Calcula o Vetor da direção CONTRÁRIA do ponto de origem até o alvo.
+ *
+ * @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.
+ */
+ public static Vector targetOppositeDirection(Vector start, Vector end) {
+ return end.subtract(start).multiply(-1).normalize();
+ }
+
+ /**
+ * Retorna um String com os valores do Vetor
+ *
+ * @return ex: "(X: 3.0, Y: 4.0, Z: 5.0)"
+ */
+ @Override
+ public String toString() {
+ return String.format("( X: %.2f Y: %.2f Z: %.2f)", this.x, this.y, this.z);
+ }
+
+ /**
+ * Modifica um vetor informando novos valores X,Y,Z
+ *
+ * @param X - Valor eixo X
+ * @param Y - Valor eixo Y
+ * @param Z - Valor eixo Z
+ */
+ public void setVector(double X, double Y, double Z) {
+ this.x = X;
+ this.y = Y;
+ this.z = Z;
+ }
+
+ /**
+ * @return Retorna um novo Vetor com os valores X e Y invertidos
+ */
+ public Vector invertXY() {
+ return new Vector(y, x, z);
+ }
+
+ /**
+ * Magnitude do Vetor
+ *
+ * @return Retorna a magnitude (comprimento) do Vetor no eixo X e Y.
+ */
+ public double magnitudeXY() {
+ return Math.sqrt(x * x + y * y);
+ }
+
+ /**
+ * Magnitude do Vetor
+ *
+ * @return Retorna a magnitude (comprimento) do Vetor em todos os eixos.
+ */
+ public double magnitude() {
+ return Math.sqrt(x * x + y * y + z * z);
+ }
+
+ /**
+ * Normalizar Vetor
+ *
+ * @return Retorna um novo Vetor normalizado (magnitude de 1).
+ */
+ public Vector normalize() {
+ double m = magnitude();
+ if (m != 0) {
+ return new Vector(x / m, y / m, z / m);
+ }
+ return new Vector(x, y, z);
+ }
+
+ /**
+ * Soma os componentes de outro vetor com o vetor informado
+ *
+ * @param otherVector - Vetor para somar os componentes
+ * @return Novo vetor com a soma dos componentes dos dois
+ */
+ public double dotProduct(Vector otherVector) {
+ return (x * otherVector.x + y * otherVector.y + z * otherVector.z);
+ }
+
+ public double determinant(Vector otherVector) {
+ return (x * otherVector.z - y * otherVector.y - z * otherVector.x);
+ }
+
+ /**
+ * Soma os componentes de outro vetor com o vetor informado
+ *
+ * @param otherVector - Vetor para somar os componentes
+ * @return Novo vetor com a soma dos componentes dos dois
+ */
+ public Vector sum(Vector otherVector) {
+ return new Vector(x + otherVector.x, y + otherVector.y, z + otherVector.z);
+ }
+
+ /**
+ * Subtrai os componentes de outro vetor com o vetor informado
+ *
+ * @param otherVector - Vetor para subtrair os componentes
+ * @return Novo vetor com a subtração dos componentes dos dois
+ */
+ public Vector subtract(Vector otherVector) {
+ return new Vector(x - otherVector.x, y - otherVector.y, z - otherVector.z);
+ }
+
+ /**
+ * Multiplica os componentes desse vetor por uma escalar
+ *
+ * @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.
+ */
+ public Vector multiply(double scalar) {
+ if (scalar != 0) {
+ return new Vector(x * scalar, y * scalar, z * scalar);
+ }
+ return new Vector(0, 0, 0);
+ }
+
+ /**
+ * Divide os componentes desse vetor por uma escalar
+ *
+ * @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.
+ */
+ public Vector divide(double scalar) {
+ if (scalar != 0) {
+ return new Vector(x / scalar, y / scalar, z / scalar);
+ }
+ return new Vector(0, 0, 0);
+ }
+
+ /**
+ * Transforma um Vetor em uma tupla com os valores.
+ *
+ * @return - Nova tupla contendo os valores do vetor em seus componentes.
+ */
+ public Triplet toTriplet() {
+ return new Triplet<>(this.x, this.y, this.z);
+ }
}
diff --git a/src/main/java/com/pesterenan/utils/VersionUtil.java b/src/main/java/com/pesterenan/utils/VersionUtil.java
index 728153b..053d9a9 100644
--- a/src/main/java/com/pesterenan/utils/VersionUtil.java
+++ b/src/main/java/com/pesterenan/utils/VersionUtil.java
@@ -3,28 +3,29 @@
import java.io.File;
import java.io.FileReader;
import java.io.InputStreamReader;
-
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
public class VersionUtil {
- public static String getVersion() {
- String version = "N/A";
- MavenXpp3Reader reader = new MavenXpp3Reader();
- Model model;
- try {
- if ((new File("pom.xml")).exists()) {
- model = reader.read(new FileReader("pom.xml"));
- } else {
- model = reader.read(new InputStreamReader(
- VersionUtil.class.getResourceAsStream("/META-INF/maven/com.pesterenan/MechPeste/pom.xml")));
- }
- version = model.getVersion();
- return version;
- } catch (Exception e) {
- e.printStackTrace();
-
- }
- return version;
+ public static String getVersion() {
+ String version = "N/A";
+ MavenXpp3Reader reader = new MavenXpp3Reader();
+ Model model;
+ try {
+ if ((new File("pom.xml")).exists()) {
+ model = reader.read(new FileReader("pom.xml"));
+ } else {
+ model =
+ reader.read(
+ new InputStreamReader(
+ VersionUtil.class.getResourceAsStream(
+ "/META-INF/maven/com.pesterenan/MechPeste/pom.xml")));
+ }
+ version = model.getVersion();
+ return version;
+ } catch (Exception e) {
+ e.printStackTrace();
}
+ return version;
+ }
}
diff --git a/src/main/java/com/pesterenan/views/AboutJFrame.java b/src/main/java/com/pesterenan/views/AboutJFrame.java
index e3a5919..8c55628 100644
--- a/src/main/java/com/pesterenan/views/AboutJFrame.java
+++ b/src/main/java/com/pesterenan/views/AboutJFrame.java
@@ -1,83 +1,113 @@
package com.pesterenan.views;
-import java.awt.Font;
+import static com.pesterenan.views.MainGui.BTN_DIMENSION;
+import static com.pesterenan.views.MainGui.centerDialogOnScreen;
+import static com.pesterenan.views.MainGui.createMarginComponent;
+import com.pesterenan.utils.VersionUtil;
+import java.awt.Desktop;
+import java.awt.Font;
+import java.io.IOException;
+import java.net.URISyntaxException;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
+import javax.swing.JEditorPane;
import javax.swing.JLabel;
import javax.swing.JPanel;
-
-import com.pesterenan.utils.VersionUtil;
-
-import static com.pesterenan.views.MainGui.BTN_DIMENSION;
-import static com.pesterenan.views.MainGui.centerDialogOnScreen;
-import static com.pesterenan.views.MainGui.createMarginComponent;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
public class AboutJFrame extends JDialog implements UIMethods {
- private static final long serialVersionUID = 0L;
- private JLabel lblMechpeste, lblAboutInfo;
- private JButton btnOk;
+ private static final long serialVersionUID = 0L;
+ private JLabel lblMechpeste;
+ private JEditorPane editorPane;
+ private JButton btnOk;
+
+ public AboutJFrame() {
+ initComponents();
+ setupComponents();
+ layoutComponents();
+ }
- public AboutJFrame() {
- initComponents();
- setupComponents();
- layoutComponents();
- }
+ @Override
+ public void initComponents() {
+ // Labels:
+ lblMechpeste = new JLabel("MechPeste - v." + VersionUtil.getVersion());
+ editorPane = new JEditorPane();
- @Override
- public void initComponents() {
- // Labels:
- lblMechpeste = new JLabel("MechPeste - v." + VersionUtil.getVersion());
- lblAboutInfo = new JLabel(
- "Esse app foi desenvolvido com o intuito de auxiliar o controle de naves
no game Kerbal Space Program.
"
- + "Não há garantias sobre o controle exato do app, portanto fique atento
"
- + "para retomar o controle quando necessário.
" + "Feito por: Renan Torres
"
- + "Visite meu canal no Youtube! - https://www.youtube.com/@Pesterenan");
+ // Buttons:
+ btnOk = new JButton("OK");
+ }
- // Buttons:
- btnOk = new JButton("OK");
- }
+ @Override
+ public void setupComponents() {
+ // Main Panel setup:
+ setTitle("Sobre");
+ setBounds(centerDialogOnScreen());
+ setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ setResizable(false);
+ setAlwaysOnTop(true);
+ setModalityType(ModalityType.APPLICATION_MODAL);
- @Override
- public void setupComponents() {
- // Main Panel setup:
- setTitle("MechPeste - por Pesterenan");
- setBounds(centerDialogOnScreen());
- setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
- setResizable(false);
- setAlwaysOnTop(true);
- setModalityType(ModalityType.APPLICATION_MODAL);
+ // Setting-up components:
+ lblMechpeste.setFont(new Font("Trajan Pro", Font.BOLD, 18));
+ lblMechpeste.setAlignmentX(CENTER_ALIGNMENT);
- // Setting-up components:
- lblMechpeste.setFont(new Font("Trajan Pro", Font.BOLD, 18));
- lblMechpeste.setAlignmentX(CENTER_ALIGNMENT);
- lblAboutInfo.setAlignmentX(CENTER_ALIGNMENT);
+ editorPane.setContentType("text/html");
+ editorPane.setText(
+ ""
+ + "Esse app foi desenvolvido com o intuito de auxiliar o controle de naves
no game Kerbal Space Program.
"
+ + "Não há garantias sobre o controle exato do app, portanto fique atento
"
+ + "para retomar o controle quando necessário.
"
+ + "Feito por: Renan Torres
"
+ + "Visite meu canal no Youtube! - https://www.youtube.com/@Pesterenan
"
+ + "Gostou do app? Considere fazer uma doação!
"
+ + "LivePix: https://livepix.gg/pesterenan
"
+ + "Código fonte: https://github.com/Pesterenan/MechPeste-Java"
+ + "");
+ editorPane.setEditable(false);
+ editorPane.setOpaque(false);
+ editorPane.addHyperlinkListener(
+ new HyperlinkListener() {
+ @Override
+ public void hyperlinkUpdate(HyperlinkEvent e) {
+ if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+ try {
+ Desktop.getDesktop().browse(e.getURL().toURI());
+ } catch (IOException | URISyntaxException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+ });
- btnOk.addActionListener(e -> {
- this.dispose();
+ btnOk.addActionListener(
+ e -> {
+ this.dispose();
});
- btnOk.setPreferredSize(BTN_DIMENSION);
- btnOk.setMaximumSize(BTN_DIMENSION);
- btnOk.setAlignmentX(CENTER_ALIGNMENT);
- }
+ btnOk.setPreferredSize(BTN_DIMENSION);
+ btnOk.setMaximumSize(BTN_DIMENSION);
+ btnOk.setAlignmentX(CENTER_ALIGNMENT);
+ }
- @Override
- public void layoutComponents() {
- JPanel pnlMain = new JPanel();
- pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.Y_AXIS));
- pnlMain.setBorder(MainGui.MARGIN_BORDER_10_PX_LR);
- pnlMain.add(createMarginComponent(10, 10));
- pnlMain.add(lblMechpeste);
- pnlMain.add(createMarginComponent(10, 10));
- pnlMain.add(lblAboutInfo);
- pnlMain.add(Box.createVerticalGlue());
- pnlMain.add(btnOk);
- pnlMain.add(createMarginComponent(10, 10));
+ @Override
+ public void layoutComponents() {
+ JPanel pnlMain = new JPanel();
+ pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.Y_AXIS));
+ pnlMain.setBorder(MainGui.MARGIN_BORDER_10_PX_LR);
+ pnlMain.add(createMarginComponent(10, 10));
+ pnlMain.add(lblMechpeste);
+ pnlMain.add(createMarginComponent(10, 10));
+ pnlMain.add(editorPane);
+ pnlMain.add(Box.createVerticalGlue());
+ pnlMain.add(btnOk);
+ pnlMain.add(createMarginComponent(10, 10));
- getContentPane().add(pnlMain);
- setVisible(true);
- }
+ getContentPane().add(pnlMain);
+ pack();
+ setVisible(true);
+ }
}
diff --git a/src/main/java/com/pesterenan/views/ChangeVesselDialog.java b/src/main/java/com/pesterenan/views/ChangeVesselDialog.java
index 188801c..507986e 100644
--- a/src/main/java/com/pesterenan/views/ChangeVesselDialog.java
+++ b/src/main/java/com/pesterenan/views/ChangeVesselDialog.java
@@ -1,153 +1,165 @@
package com.pesterenan.views;
-import com.pesterenan.MechPeste;
+import static com.pesterenan.views.MainGui.BTN_DIMENSION;
-import javax.swing.*;
+import com.pesterenan.model.VesselManager;
+import java.awt.event.ActionEvent;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
-import java.awt.event.ActionEvent;
-
-import static com.pesterenan.views.MainGui.BTN_DIMENSION;
public class ChangeVesselDialog extends JDialog implements UIMethods {
- private static final long serialVersionUID = 1L;
- private JLabel lblPanelInfo, lblVesselStatus;
- private JList listActiveVessels;
- private JButton btnChangeToVessel;
- private JRadioButton rbClosestVessels, rbOnSameBody, rbAllVessels;
-
- public ChangeVesselDialog() {
- initComponents();
- setupComponents();
- layoutComponents();
- }
-
- @Override
- public void initComponents() {
- // Labels:
- lblPanelInfo = new JLabel("Use esse painel para verificar e trocar para as naves próximas.");
- lblVesselStatus = new JLabel("Selecione uma nave na lista.");
-
- // Buttons:
- btnChangeToVessel = new JButton("Mudar para");
- rbClosestVessels = new JRadioButton("Naves próximas (10km)");
- rbOnSameBody = new JRadioButton("No mesmo corpo celeste");
- rbAllVessels = new JRadioButton("Todas as naves");
-
- // Misc:
- listActiveVessels = new JList<>(MechPeste.getActiveVessels("closest"));
- listActiveVessels.setToolTipText("Aqui são mostradas as naves próximas de acordo com o filtro da esquerda.");
+ private static final long serialVersionUID = 1L;
+ private JLabel lblPanelInfo, lblVesselStatus;
+ private JList listActiveVessels;
+ private JButton btnChangeToVessel;
+ private JRadioButton rbClosestVessels, rbOnSameBody, rbAllVessels;
+ private VesselManager vesselManager;
+
+ public ChangeVesselDialog(VesselManager vesselManager) {
+ this.vesselManager = vesselManager;
+ initComponents();
+ setupComponents();
+ layoutComponents();
+ }
+
+ @Override
+ public void initComponents() {
+ // Labels:
+ lblPanelInfo = new JLabel("Use esse painel para verificar e trocar para as naves próximas.");
+ lblVesselStatus = new JLabel("Selecione uma nave na lista.");
+
+ // Buttons:
+ btnChangeToVessel = new JButton("Mudar para");
+ rbClosestVessels = new JRadioButton("Naves próximas (10km)");
+ rbOnSameBody = new JRadioButton("No mesmo corpo celeste");
+ rbAllVessels = new JRadioButton("Todas as naves");
+
+ // Misc:
+ listActiveVessels = new JList<>(vesselManager.getActiveVessels("closest"));
+ listActiveVessels.setToolTipText(
+ "Aqui são mostradas as naves próximas de acordo com o filtro da esquerda.");
+ }
+
+ @Override
+ public void setupComponents() {
+ // Main Panel setup:
+ setTitle("Troca de naves");
+ setBounds(MainGui.centerDialogOnScreen());
+ setModal(true);
+ setModalityType(ModalityType.MODELESS);
+ setResizable(false);
+ setAlwaysOnTop(true);
+
+ // Setting-up components:
+ btnChangeToVessel.addActionListener(this::handleChangeToVessel);
+ btnChangeToVessel.setPreferredSize(BTN_DIMENSION);
+ btnChangeToVessel.setMaximumSize(BTN_DIMENSION);
+
+ rbClosestVessels.setSelected(true);
+ rbClosestVessels.addActionListener(this::handleBuildVesselList);
+ rbOnSameBody.addActionListener(this::handleBuildVesselList);
+ rbAllVessels.addActionListener(this::handleBuildVesselList);
+ rbClosestVessels.setActionCommand("closest");
+ rbOnSameBody.setActionCommand("samebody");
+ rbAllVessels.setActionCommand("all");
+
+ ButtonGroup rbBtnGroup = new ButtonGroup();
+ rbBtnGroup.add(rbClosestVessels);
+ rbBtnGroup.add(rbOnSameBody);
+ rbBtnGroup.add(rbAllVessels);
+
+ listActiveVessels.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ listActiveVessels.addListSelectionListener(e -> handleListActiveVesselsValueChanged(e));
+ }
+
+ @Override
+ public void layoutComponents() {
+
+ JPanel pnlSearchArea = new JPanel();
+ pnlSearchArea.setBorder(new TitledBorder(null, "\u00C1rea de procura:"));
+ pnlSearchArea.setLayout(new BoxLayout(pnlSearchArea, BoxLayout.Y_AXIS));
+ pnlSearchArea.add(rbClosestVessels);
+ pnlSearchArea.add(rbOnSameBody);
+ pnlSearchArea.add(rbAllVessels);
+
+ JPanel pnlOptions = new JPanel();
+ pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS));
+ pnlOptions.add(pnlSearchArea);
+ pnlOptions.add(Box.createVerticalStrut(10));
+ pnlOptions.add(btnChangeToVessel);
+ btnChangeToVessel.setAlignmentX(LEFT_ALIGNMENT);
+ pnlSearchArea.setAlignmentX(LEFT_ALIGNMENT);
+
+ JPanel pnlScroll = new JPanel();
+ pnlScroll.setLayout(new BoxLayout(pnlScroll, BoxLayout.Y_AXIS));
+ JScrollPane scrollPane = new JScrollPane();
+ scrollPane.setViewportView(listActiveVessels);
+ pnlScroll.add(Box.createVerticalStrut(6));
+ pnlScroll.add(scrollPane);
+ pnlScroll.add(Box.createHorizontalStrut(190));
+
+ JPanel pnlOptionsAndList = new JPanel();
+ pnlOptionsAndList.setLayout(new BoxLayout(pnlOptionsAndList, BoxLayout.X_AXIS));
+ pnlOptions.setAlignmentY(TOP_ALIGNMENT);
+ pnlScroll.setAlignmentY(TOP_ALIGNMENT);
+ pnlOptionsAndList.add(pnlOptions);
+ pnlOptionsAndList.add(Box.createHorizontalStrut(5));
+ pnlOptionsAndList.add(pnlScroll);
+
+ JPanel pnlStatus = new JPanel();
+ pnlStatus.setLayout(new BoxLayout(pnlStatus, BoxLayout.X_AXIS));
+ pnlStatus.add(lblVesselStatus);
+ pnlStatus.add(Box.createHorizontalGlue());
+ pnlStatus.add(Box.createVerticalStrut(10));
+
+ JPanel pnlMain = new JPanel();
+ pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.Y_AXIS));
+ pnlMain.setBorder(MainGui.MARGIN_BORDER_10_PX_LR);
+ lblPanelInfo.setAlignmentX(CENTER_ALIGNMENT);
+ pnlMain.add(lblPanelInfo);
+ pnlOptionsAndList.setAlignmentY(TOP_ALIGNMENT);
+ pnlMain.add(pnlOptionsAndList);
+ pnlMain.add(Box.createVerticalStrut(5));
+ pnlMain.add(pnlStatus);
+ pnlMain.add(Box.createVerticalStrut(10));
+
+ getContentPane().add(pnlMain);
+ setVisible(true);
+ }
+
+ protected void handleChangeToVessel(ActionEvent e) {
+ if (listActiveVessels.getSelectedIndex() == -1) {
+ return;
}
-
- @Override
- public void setupComponents() {
- // Main Panel setup:
- setTitle("Troca de naves");
- setBounds(MainGui.centerDialogOnScreen());
- setModal(true);
- setModalityType(ModalityType.MODELESS);
- setResizable(false);
- setAlwaysOnTop(true);
-
- // Setting-up components:
- btnChangeToVessel.addActionListener(this::handleChangeToVessel);
- btnChangeToVessel.setPreferredSize(BTN_DIMENSION);
- btnChangeToVessel.setMaximumSize(BTN_DIMENSION);
-
- rbClosestVessels.setSelected(true);
- rbClosestVessels.addActionListener(this::handleBuildVesselList);
- rbOnSameBody.addActionListener(this::handleBuildVesselList);
- rbAllVessels.addActionListener(this::handleBuildVesselList);
- rbClosestVessels.setActionCommand("closest");
- rbOnSameBody.setActionCommand("samebody");
- rbAllVessels.setActionCommand("all");
-
- ButtonGroup rbBtnGroup = new ButtonGroup();
- rbBtnGroup.add(rbClosestVessels);
- rbBtnGroup.add(rbOnSameBody);
- rbBtnGroup.add(rbAllVessels);
-
- listActiveVessels.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- listActiveVessels.addListSelectionListener(e -> handleListActiveVesselsValueChanged(e));
- }
-
- @Override
- public void layoutComponents() {
-
- JPanel pnlSearchArea = new JPanel();
- pnlSearchArea.setBorder(new TitledBorder(null, "\u00C1rea de procura:"));
- pnlSearchArea.setLayout(new BoxLayout(pnlSearchArea, BoxLayout.Y_AXIS));
- pnlSearchArea.add(rbClosestVessels);
- pnlSearchArea.add(rbOnSameBody);
- pnlSearchArea.add(rbAllVessels);
-
- JPanel pnlOptions = new JPanel();
- pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS));
- pnlOptions.add(pnlSearchArea);
- pnlOptions.add(Box.createVerticalStrut(10));
- pnlOptions.add(btnChangeToVessel);
- btnChangeToVessel.setAlignmentX(LEFT_ALIGNMENT);
- pnlSearchArea.setAlignmentX(LEFT_ALIGNMENT);
-
- JPanel pnlScroll = new JPanel();
- pnlScroll.setLayout(new BoxLayout(pnlScroll, BoxLayout.Y_AXIS));
- JScrollPane scrollPane = new JScrollPane();
- scrollPane.setViewportView(listActiveVessels);
- pnlScroll.add(Box.createVerticalStrut(6));
- pnlScroll.add(scrollPane);
- pnlScroll.add(Box.createHorizontalStrut(190));
-
- JPanel pnlOptionsAndList = new JPanel();
- pnlOptionsAndList.setLayout(new BoxLayout(pnlOptionsAndList, BoxLayout.X_AXIS));
- pnlOptions.setAlignmentY(TOP_ALIGNMENT);
- pnlScroll.setAlignmentY(TOP_ALIGNMENT);
- pnlOptionsAndList.add(pnlOptions);
- pnlOptionsAndList.add(Box.createHorizontalStrut(5));
- pnlOptionsAndList.add(pnlScroll);
-
- JPanel pnlStatus = new JPanel();
- pnlStatus.setLayout(new BoxLayout(pnlStatus, BoxLayout.X_AXIS));
- pnlStatus.add(lblVesselStatus);
- pnlStatus.add(Box.createHorizontalGlue());
- pnlStatus.add(Box.createVerticalStrut(10));
-
- JPanel pnlMain = new JPanel();
- pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.Y_AXIS));
- pnlMain.setBorder(MainGui.MARGIN_BORDER_10_PX_LR);
- lblPanelInfo.setAlignmentX(CENTER_ALIGNMENT);
- pnlMain.add(lblPanelInfo);
- pnlOptionsAndList.setAlignmentY(TOP_ALIGNMENT);
- pnlMain.add(pnlOptionsAndList);
- pnlMain.add(Box.createVerticalStrut(5));
- pnlMain.add(pnlStatus);
- pnlMain.add(Box.createVerticalStrut(10));
-
- getContentPane().add(pnlMain);
- setVisible(true);
- }
-
- protected void handleChangeToVessel(ActionEvent e) {
- if (listActiveVessels.getSelectedIndex() == -1) {
- return;
- }
- int vesselHashCode = Integer.parseInt(listActiveVessels.getSelectedValue().split(" - ")[0]);
- MechPeste.changeToVessel(vesselHashCode);
- }
-
- protected void handleBuildVesselList(ActionEvent e) {
- listActiveVessels.setModel(MechPeste.getActiveVessels(e.getActionCommand()));
- }
-
- protected void handleListActiveVesselsValueChanged(ListSelectionEvent e) {
- String selectedValue = listActiveVessels.getSelectedValue();
- if (selectedValue == null) {
- lblVesselStatus.setText("Selecione uma nave da lista.");
- btnChangeToVessel.setEnabled(false);
- return;
- }
- int vesselId = Integer.parseInt(selectedValue.split(" - ")[0]);
- lblVesselStatus.setText(MechPeste.getVesselInfo(vesselId));
- btnChangeToVessel.setEnabled(true);
+ int vesselHashCode = Integer.parseInt(listActiveVessels.getSelectedValue().split(" - ")[0]);
+ vesselManager.changeToVessel(vesselHashCode);
+ }
+
+ protected void handleBuildVesselList(ActionEvent e) {
+ listActiveVessels.setModel(vesselManager.getActiveVessels(e.getActionCommand()));
+ }
+
+ protected void handleListActiveVesselsValueChanged(ListSelectionEvent e) {
+ String selectedValue = listActiveVessels.getSelectedValue();
+ if (selectedValue == null) {
+ lblVesselStatus.setText("Selecione uma nave da lista.");
+ btnChangeToVessel.setEnabled(false);
+ return;
}
+ int vesselId = Integer.parseInt(selectedValue.split(" - ")[0]);
+ lblVesselStatus.setText(vesselManager.getVesselInfo(vesselId));
+ btnChangeToVessel.setEnabled(true);
+ }
}
diff --git a/src/main/java/com/pesterenan/views/CreateManeuverJPanel.java b/src/main/java/com/pesterenan/views/CreateManeuverJPanel.java
index a47af7e..28a1bf8 100644
--- a/src/main/java/com/pesterenan/views/CreateManeuverJPanel.java
+++ b/src/main/java/com/pesterenan/views/CreateManeuverJPanel.java
@@ -1,442 +1,463 @@
package com.pesterenan.views;
+import static com.pesterenan.views.MainGui.BTN_DIMENSION;
+import static com.pesterenan.views.MainGui.PNL_DIMENSION;
+
import com.pesterenan.MechPeste;
+import com.pesterenan.model.VesselManager;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.ControlePID;
-
-import krpc.client.RPCException;
-import krpc.client.services.SpaceCenter.Node;
-import krpc.client.services.SpaceCenter.Orbit;
-import krpc.client.services.SpaceCenter.Vessel;
-import krpc.client.services.SpaceCenter.VesselSituation;
-
-import javax.swing.*;
-import javax.swing.border.TitledBorder;
-
-import org.javatuples.Pair;
-
-import java.awt.*;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridLayout;
+import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
-import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;
-
-import static com.pesterenan.views.MainGui.PNL_DIMENSION;
-import static com.pesterenan.views.MainGui.BTN_DIMENSION;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.JSlider;
+import javax.swing.ListModel;
+import javax.swing.ListSelectionModel;
+import javax.swing.border.TitledBorder;
+import krpc.client.RPCException;
+import krpc.client.services.SpaceCenter.Node;
+import krpc.client.services.SpaceCenter.Orbit;
+import krpc.client.services.SpaceCenter.Vessel;
+import krpc.client.services.SpaceCenter.VesselSituation;
public class CreateManeuverJPanel extends JPanel implements ActionListener, UIMethods {
- private static JLabel lblManeuverInfo;
- private static JButton btnCreateManeuver, btnDeleteManeuver, btnBack, btnAp, btnPe, btnAN, btnDN;
- private static JButton btnIncrease, btnDecrease, btnNextOrbit, btnPrevOrbit;
- private static JSlider sldScale;
- private static JList listCurrentManeuvers;
- private static int selectedManeuverIndex = 0;
- private static JRadioButton rbPrograde, rbNormal, rbRadial, rbTime;
- private static ButtonGroup bgManeuverType;
- private static Map sliderValues = new HashMap<>();
- private final ControlePID ctrlManeuver = new ControlePID();
-
- public CreateManeuverJPanel() {
- initComponents();
- setupComponents();
- layoutComponents();
- }
-
- @Override
- public void initComponents() {
- // Labels:
- lblManeuverInfo = new JLabel("");
-
- // Buttons:
- btnCreateManeuver = new JButton("Criar");
- btnDeleteManeuver = new JButton("Apagar");
- btnAp = new JButton("AP");
- btnPe = new JButton("PE");
- btnAN = new JButton("NA");
- btnDN = new JButton("ND");
- btnBack = new JButton(Bundle.getString("pnl_mnv_btn_back"));
- btnIncrease = new JButton("+");
- btnDecrease = new JButton("-");
- btnNextOrbit = new JButton(">");
- btnPrevOrbit = new JButton("<");
-
- // Radio buttons:
- rbPrograde = new JRadioButton("Pro");
- rbNormal = new JRadioButton("Nor");
- rbRadial = new JRadioButton("Rad");
- rbTime = new JRadioButton("Tmp");
-
- // Misc:
- listCurrentManeuvers = new JList<>();
- sldScale = new JSlider(JSlider.VERTICAL, 0, 5, 2);
- bgManeuverType = new ButtonGroup();
- sliderValues.put(0, 0.01f);
- sliderValues.put(1, 0.1f);
- sliderValues.put(2, 1f);
- sliderValues.put(3, 10f);
- sliderValues.put(4, 100f);
- sliderValues.put(5, 1000f);
-
- ctrlManeuver.setOutput(-100, 100);
- }
-
- @Override
- public void setupComponents() {
- // Setting-up components:
- btnCreateManeuver.addActionListener(this);
- btnCreateManeuver.setMaximumSize(BTN_DIMENSION);
- btnCreateManeuver.setPreferredSize(BTN_DIMENSION);
- btnDeleteManeuver.addActionListener(this);
- btnDeleteManeuver.setMaximumSize(BTN_DIMENSION);
- btnDeleteManeuver.setPreferredSize(BTN_DIMENSION);
- btnAp.addActionListener(this);
- btnAp.setActionCommand("apoapsis");
- btnPe.addActionListener(this);
- btnPe.setActionCommand("periapsis");
- btnAN.addActionListener(this);
- btnAN.setActionCommand("ascending");
- btnDN.addActionListener(this);
- btnDN.setActionCommand("descending");
- btnBack.addActionListener(this);
- btnBack.setMaximumSize(BTN_DIMENSION);
- btnBack.setPreferredSize(BTN_DIMENSION);
- btnIncrease.setActionCommand("increase");
- btnIncrease.addActionListener(this);
- btnIncrease.addMouseWheelListener(e -> {
- int rotation = e.getWheelRotation();
- if (rotation > 0) {
- changeManeuverDeltaV(btnDecrease.getActionCommand());
- } else {
- changeManeuverDeltaV(btnIncrease.getActionCommand());
- }
+ private static JLabel lblManeuverInfo;
+ private static JButton btnCreateManeuver, btnDeleteManeuver, btnBack, btnAp, btnPe, btnAN, btnDN;
+ private static JButton btnIncrease, btnDecrease, btnNextOrbit, btnPrevOrbit;
+ private static JSlider sldScale;
+ private static JList listCurrentManeuvers;
+ private static int selectedManeuverIndex = 0;
+ private static JRadioButton rbPrograde, rbNormal, rbRadial, rbTime;
+ private static ButtonGroup bgManeuverType;
+ private static Map sliderValues = new HashMap<>();
+ private final ControlePID ctrlManeuver = new ControlePID();
+ private VesselManager vesselManager;
+ private StatusDisplay statusDisplay;
+
+ public CreateManeuverJPanel(StatusDisplay statusDisplay) {
+ this.statusDisplay = statusDisplay;
+ initComponents();
+ setupComponents();
+ layoutComponents();
+ }
+
+ public void setVesselManager(VesselManager vesselManager) {
+ this.vesselManager = vesselManager;
+ }
+
+ @Override
+ public void initComponents() {
+ // Labels:
+ lblManeuverInfo = new JLabel("");
+
+ // Buttons:
+ btnCreateManeuver = new JButton("Criar");
+ btnDeleteManeuver = new JButton("Apagar");
+ btnAp = new JButton("AP");
+ btnPe = new JButton("PE");
+ btnAN = new JButton("NA");
+ btnDN = new JButton("ND");
+ btnBack = new JButton(Bundle.getString("pnl_mnv_btn_back"));
+ btnIncrease = new JButton("+");
+ btnDecrease = new JButton("-");
+ btnNextOrbit = new JButton(">");
+ btnPrevOrbit = new JButton("<");
+
+ // Radio buttons:
+ rbPrograde = new JRadioButton("Pro");
+ rbNormal = new JRadioButton("Nor");
+ rbRadial = new JRadioButton("Rad");
+ rbTime = new JRadioButton("Tmp");
+
+ // Misc:
+ listCurrentManeuvers = new JList<>();
+ sldScale = new JSlider(JSlider.VERTICAL, 0, 5, 2);
+ bgManeuverType = new ButtonGroup();
+ sliderValues.put(0, 0.01f);
+ sliderValues.put(1, 0.1f);
+ sliderValues.put(2, 1f);
+ sliderValues.put(3, 10f);
+ sliderValues.put(4, 100f);
+ sliderValues.put(5, 1000f);
+
+ ctrlManeuver.setOutput(-100, 100);
+ }
+
+ @Override
+ public void setupComponents() {
+ // Setting-up components:
+ btnCreateManeuver.addActionListener(this);
+ btnCreateManeuver.setMaximumSize(BTN_DIMENSION);
+ btnCreateManeuver.setPreferredSize(BTN_DIMENSION);
+ btnDeleteManeuver.addActionListener(this);
+ btnDeleteManeuver.setMaximumSize(BTN_DIMENSION);
+ btnDeleteManeuver.setPreferredSize(BTN_DIMENSION);
+ btnAp.addActionListener(this);
+ btnAp.setActionCommand("apoapsis");
+ btnPe.addActionListener(this);
+ btnPe.setActionCommand("periapsis");
+ btnAN.addActionListener(this);
+ btnAN.setActionCommand("ascending");
+ btnDN.addActionListener(this);
+ btnDN.setActionCommand("descending");
+ btnBack.addActionListener(this);
+ btnBack.setMaximumSize(BTN_DIMENSION);
+ btnBack.setPreferredSize(BTN_DIMENSION);
+ btnIncrease.setActionCommand("increase");
+ btnIncrease.addActionListener(this);
+ btnIncrease.addMouseWheelListener(
+ e -> {
+ int rotation = e.getWheelRotation();
+ if (rotation > 0) {
+ changeManeuverDeltaV(btnDecrease.getActionCommand());
+ } else {
+ changeManeuverDeltaV(btnIncrease.getActionCommand());
+ }
});
- btnIncrease.setMaximumSize(new Dimension(70, 26));
- btnIncrease.setPreferredSize(new Dimension(70, 26));
- btnIncrease.setMargin(new Insets(0, 0, 0, 0));
- btnDecrease.setActionCommand("decrease");
- btnDecrease.addActionListener(this);
- btnDecrease.addMouseWheelListener(e -> {
- int rotation = e.getWheelRotation();
- if (rotation > 0) {
- changeManeuverDeltaV(btnIncrease.getActionCommand());
- } else {
- changeManeuverDeltaV(btnDecrease.getActionCommand());
- }
+ btnIncrease.setMaximumSize(new Dimension(70, 26));
+ btnIncrease.setPreferredSize(new Dimension(70, 26));
+ btnIncrease.setMargin(new Insets(0, 0, 0, 0));
+ btnDecrease.setActionCommand("decrease");
+ btnDecrease.addActionListener(this);
+ btnDecrease.addMouseWheelListener(
+ e -> {
+ int rotation = e.getWheelRotation();
+ if (rotation > 0) {
+ changeManeuverDeltaV(btnIncrease.getActionCommand());
+ } else {
+ changeManeuverDeltaV(btnDecrease.getActionCommand());
+ }
});
- btnDecrease.setMaximumSize(new Dimension(70, 26));
- btnDecrease.setPreferredSize(new Dimension(70, 26));
- btnDecrease.setMargin(new Insets(0, 0, 0, 0));
- btnNextOrbit.setActionCommand("next_orbit");
- btnNextOrbit.addActionListener(this);
- btnNextOrbit.setMaximumSize(new Dimension(35, 26));
- btnNextOrbit.setPreferredSize(new Dimension(35, 26));
- btnNextOrbit.setMargin(new Insets(0, 0, 0, 0));
- btnPrevOrbit.setActionCommand("prev_orbit");
- btnPrevOrbit.addActionListener(this);
- btnPrevOrbit.setMaximumSize(new Dimension(35, 26));
- btnPrevOrbit.setPreferredSize(new Dimension(35, 26));
- btnPrevOrbit.setMargin(new Insets(0, 0, 0, 0));
-
- rbPrograde.setActionCommand("prograde");
- rbPrograde.addChangeListener(e -> handleChangeButtonText(sldScale.getValue()));
- rbNormal.setActionCommand("normal");
- rbNormal.addChangeListener(e -> handleChangeButtonText(sldScale.getValue()));
- rbRadial.setActionCommand("radial");
- rbRadial.addChangeListener(e -> handleChangeButtonText(sldScale.getValue()));
- rbTime.setActionCommand("time");
- rbTime.addChangeListener(e -> handleChangeButtonText(sldScale.getValue()));
- bgManeuverType.add(rbPrograde);
- bgManeuverType.add(rbNormal);
- bgManeuverType.add(rbRadial);
- bgManeuverType.add(rbTime);
- bgManeuverType.setSelected(rbPrograde.getModel(), true);
-
- listCurrentManeuvers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- listCurrentManeuvers.addListSelectionListener(e -> selectedManeuverIndex = e.getFirstIndex());
-
- sldScale.setSnapToTicks(true);
- sldScale.setPaintTicks(true);
- sldScale.setMajorTickSpacing(1);
- sldScale.setMinorTickSpacing(1);
- sldScale.setPaintLabels(false);
- sldScale.addChangeListener(e -> handleChangeButtonText(sldScale.getValue()));
- sldScale.addMouseWheelListener(e -> {
- int rotation = e.getWheelRotation();
- if (rotation < 0) {
- sldScale.setValue(sldScale.getValue() + sldScale.getMinorTickSpacing());
- } else {
- sldScale.setValue(sldScale.getValue() - sldScale.getMinorTickSpacing());
- }
+ btnDecrease.setMaximumSize(new Dimension(70, 26));
+ btnDecrease.setPreferredSize(new Dimension(70, 26));
+ btnDecrease.setMargin(new Insets(0, 0, 0, 0));
+ btnNextOrbit.setActionCommand("next_orbit");
+ btnNextOrbit.addActionListener(this);
+ btnNextOrbit.setMaximumSize(new Dimension(35, 26));
+ btnNextOrbit.setPreferredSize(new Dimension(35, 26));
+ btnNextOrbit.setMargin(new Insets(0, 0, 0, 0));
+ btnPrevOrbit.setActionCommand("prev_orbit");
+ btnPrevOrbit.addActionListener(this);
+ btnPrevOrbit.setMaximumSize(new Dimension(35, 26));
+ btnPrevOrbit.setPreferredSize(new Dimension(35, 26));
+ btnPrevOrbit.setMargin(new Insets(0, 0, 0, 0));
+
+ rbPrograde.setActionCommand("prograde");
+ rbPrograde.addChangeListener(e -> handleChangeButtonText(sldScale.getValue()));
+ rbNormal.setActionCommand("normal");
+ rbNormal.addChangeListener(e -> handleChangeButtonText(sldScale.getValue()));
+ rbRadial.setActionCommand("radial");
+ rbRadial.addChangeListener(e -> handleChangeButtonText(sldScale.getValue()));
+ rbTime.setActionCommand("time");
+ rbTime.addChangeListener(e -> handleChangeButtonText(sldScale.getValue()));
+ bgManeuverType.add(rbPrograde);
+ bgManeuverType.add(rbNormal);
+ bgManeuverType.add(rbRadial);
+ bgManeuverType.add(rbTime);
+ bgManeuverType.setSelected(rbPrograde.getModel(), true);
+
+ listCurrentManeuvers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ listCurrentManeuvers.addListSelectionListener(e -> selectedManeuverIndex = e.getFirstIndex());
+
+ sldScale.setSnapToTicks(true);
+ sldScale.setPaintTicks(true);
+ sldScale.setMajorTickSpacing(1);
+ sldScale.setMinorTickSpacing(1);
+ sldScale.setPaintLabels(false);
+ sldScale.addChangeListener(e -> handleChangeButtonText(sldScale.getValue()));
+ sldScale.addMouseWheelListener(
+ e -> {
+ int rotation = e.getWheelRotation();
+ if (rotation < 0) {
+ sldScale.setValue(sldScale.getValue() + sldScale.getMinorTickSpacing());
+ } else {
+ sldScale.setValue(sldScale.getValue() - sldScale.getMinorTickSpacing());
+ }
});
+ }
+
+ @Override
+ public void layoutComponents() {
+ // Main Panel layout:
+ setPreferredSize(PNL_DIMENSION);
+ setSize(PNL_DIMENSION);
+ setLayout(new BorderLayout());
+
+ JPanel pnlPositionManeuver = new JPanel();
+ pnlPositionManeuver.setLayout(new BoxLayout(pnlPositionManeuver, BoxLayout.X_AXIS));
+ pnlPositionManeuver.setBorder(new TitledBorder("Posicionar manobra no:"));
+ pnlPositionManeuver.add(Box.createHorizontalGlue());
+ pnlPositionManeuver.add(btnAp);
+ pnlPositionManeuver.add(btnPe);
+ pnlPositionManeuver.add(btnAN);
+ pnlPositionManeuver.add(btnDN);
+ pnlPositionManeuver.add(Box.createHorizontalGlue());
+
+ JPanel pnlRadioButtons = new JPanel(new GridLayout(4, 1));
+ pnlRadioButtons.setMaximumSize(new Dimension(50, 100));
+ pnlRadioButtons.add(rbPrograde);
+ pnlRadioButtons.add(rbNormal);
+ pnlRadioButtons.add(rbRadial);
+ pnlRadioButtons.add(rbTime);
+
+ JPanel pnlSlider = new JPanel();
+ pnlSlider.setLayout(new BoxLayout(pnlSlider, BoxLayout.Y_AXIS));
+ pnlSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
+ pnlSlider.setBorder(new TitledBorder("Escala:"));
+ pnlSlider.add(sldScale);
+ pnlSlider.add(Box.createHorizontalStrut(40));
+
+ JPanel pnlOrbitControl = new JPanel();
+ pnlOrbitControl.setLayout(new BoxLayout(pnlOrbitControl, BoxLayout.X_AXIS));
+ pnlOrbitControl.setAlignmentX(Component.LEFT_ALIGNMENT);
+ pnlOrbitControl.add(btnPrevOrbit);
+ pnlOrbitControl.add(btnNextOrbit);
+
+ JPanel pnlManeuverButtons = new JPanel();
+ pnlManeuverButtons.setLayout(new BoxLayout(pnlManeuverButtons, BoxLayout.Y_AXIS));
+ pnlManeuverButtons.setAlignmentX(Component.LEFT_ALIGNMENT);
+ pnlManeuverButtons.add(btnIncrease);
+ pnlManeuverButtons.add(pnlOrbitControl);
+ pnlManeuverButtons.add(btnDecrease);
+
+ JPanel pnlManeuverController = new JPanel();
+ pnlManeuverController.setLayout(new BoxLayout(pnlManeuverController, BoxLayout.X_AXIS));
+ pnlManeuverController.setBorder(new TitledBorder("Controlador de Manobra:"));
+ pnlManeuverController.setMaximumSize(new Dimension(180, 300));
+ pnlManeuverController.add(pnlRadioButtons);
+ pnlManeuverController.add(pnlSlider);
+ pnlManeuverController.add(pnlManeuverButtons);
+
+ JPanel pnlManeuverInfo = new JPanel();
+ pnlManeuverInfo.setLayout(new BoxLayout(pnlManeuverInfo, BoxLayout.Y_AXIS));
+ pnlManeuverInfo.setBorder(new TitledBorder("Info. Manobra:"));
+ pnlManeuverInfo.setMaximumSize(new Dimension(300, 300));
+
+ JPanel pnlMCpnlAP = new JPanel();
+ pnlMCpnlAP.setLayout(new BoxLayout(pnlMCpnlAP, BoxLayout.X_AXIS));
+ pnlMCpnlAP.add(pnlManeuverController);
+ pnlMCpnlAP.add(pnlManeuverInfo);
+
+ JPanel pnlControls = new JPanel();
+ pnlControls.setLayout(new BoxLayout(pnlControls, BoxLayout.Y_AXIS));
+ pnlControls.add(pnlPositionManeuver);
+ pnlControls.add(pnlMCpnlAP);
+
+ JPanel pnlManeuverList = new JPanel();
+ pnlManeuverList.setLayout(new BoxLayout(pnlManeuverList, BoxLayout.Y_AXIS));
+ JScrollPane scrollPane = new JScrollPane();
+ scrollPane.setViewportView(listCurrentManeuvers);
+ pnlManeuverList.add(scrollPane);
+ pnlManeuverList.add(btnCreateManeuver);
+ pnlManeuverList.add(btnDeleteManeuver);
+
+ JPanel pnlOptions = new JPanel();
+ pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS));
+ pnlOptions.setBorder(new TitledBorder("Lista de Manobras:"));
+ pnlOptions.add(pnlManeuverList);
+ pnlOptions.setPreferredSize(new Dimension(110, 300));
+ pnlOptions.setMaximumSize(new Dimension(110, 300));
+
+ JPanel pnlOptionsAndList = new JPanel();
+ pnlOptionsAndList.setLayout(new BoxLayout(pnlOptionsAndList, BoxLayout.X_AXIS));
+ pnlControls.setAlignmentY(TOP_ALIGNMENT);
+ pnlOptions.setAlignmentY(TOP_ALIGNMENT);
+ pnlOptionsAndList.add(pnlOptions);
+ pnlOptionsAndList.add(Box.createHorizontalStrut(5));
+ pnlOptionsAndList.add(pnlControls);
+
+ JPanel pnlBackButton = new JPanel();
+ pnlBackButton.setLayout(new BoxLayout(pnlBackButton, BoxLayout.X_AXIS));
+ pnlBackButton.add(lblManeuverInfo);
+ pnlBackButton.add(Box.createHorizontalGlue());
+ pnlBackButton.add(btnBack);
+
+ JPanel pnlMain = new JPanel();
+ pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
+ pnlMain.add(pnlOptionsAndList);
+
+ add(pnlMain, BorderLayout.CENTER);
+ add(pnlBackButton, BorderLayout.SOUTH);
+ }
+
+ public void updatePanel(ListModel list) {
+ try {
+ boolean hasManeuverNodes = list.getSize() > 0;
+ boolean hasTargetVessel = vesselManager.getSpaceCenter().getTargetVessel() != null;
+ listCurrentManeuvers.setModel(list);
+ listCurrentManeuvers.setSelectedIndex(selectedManeuverIndex);
+ btnDeleteManeuver.setEnabled(hasManeuverNodes);
+ btnAp.setEnabled(hasManeuverNodes);
+ btnPe.setEnabled(hasManeuverNodes);
+ btnAN.setEnabled(hasManeuverNodes && hasTargetVessel);
+ btnDN.setEnabled(hasManeuverNodes && hasTargetVessel);
+ btnIncrease.setEnabled(hasManeuverNodes);
+ btnDecrease.setEnabled(hasManeuverNodes);
+ btnNextOrbit.setEnabled(hasManeuverNodes);
+ btnPrevOrbit.setEnabled(hasManeuverNodes);
+ lblManeuverInfo.setText(listCurrentManeuvers.getSelectedValue());
+ } catch (RPCException ignored) {
}
-
- @Override
- public void layoutComponents() {
- // Main Panel layout:
- setPreferredSize(PNL_DIMENSION);
- setSize(PNL_DIMENSION);
- setLayout(new BorderLayout());
-
- JPanel pnlPositionManeuver = new JPanel();
- pnlPositionManeuver.setLayout(new BoxLayout(pnlPositionManeuver, BoxLayout.X_AXIS));
- pnlPositionManeuver.setBorder(new TitledBorder("Posicionar manobra no:"));
- pnlPositionManeuver.add(Box.createHorizontalGlue());
- pnlPositionManeuver.add(btnAp);
- pnlPositionManeuver.add(btnPe);
- pnlPositionManeuver.add(btnAN);
- pnlPositionManeuver.add(btnDN);
- pnlPositionManeuver.add(Box.createHorizontalGlue());
-
- JPanel pnlRadioButtons = new JPanel(new GridLayout(4, 1));
- pnlRadioButtons.setMaximumSize(new Dimension(50, 100));
- pnlRadioButtons.add(rbPrograde);
- pnlRadioButtons.add(rbNormal);
- pnlRadioButtons.add(rbRadial);
- pnlRadioButtons.add(rbTime);
-
- JPanel pnlSlider = new JPanel();
- pnlSlider.setLayout(new BoxLayout(pnlSlider, BoxLayout.Y_AXIS));
- pnlSlider.setAlignmentX(Component.LEFT_ALIGNMENT);
- pnlSlider.setBorder(new TitledBorder("Escala:"));
- pnlSlider.add(sldScale);
- pnlSlider.add(Box.createHorizontalStrut(40));
-
- JPanel pnlOrbitControl = new JPanel();
- pnlOrbitControl.setLayout(new BoxLayout(pnlOrbitControl, BoxLayout.X_AXIS));
- pnlOrbitControl.setAlignmentX(Component.LEFT_ALIGNMENT);
- pnlOrbitControl.add(btnPrevOrbit);
- pnlOrbitControl.add(btnNextOrbit);
-
- JPanel pnlManeuverButtons = new JPanel();
- pnlManeuverButtons.setLayout(new BoxLayout(pnlManeuverButtons, BoxLayout.Y_AXIS));
- pnlManeuverButtons.setAlignmentX(Component.LEFT_ALIGNMENT);
- pnlManeuverButtons.add(btnIncrease);
- pnlManeuverButtons.add(pnlOrbitControl);
- pnlManeuverButtons.add(btnDecrease);
-
- JPanel pnlManeuverController = new JPanel();
- pnlManeuverController.setLayout(new BoxLayout(pnlManeuverController, BoxLayout.X_AXIS));
- pnlManeuverController.setBorder(new TitledBorder("Controlador de Manobra:"));
- pnlManeuverController.setMaximumSize(new Dimension(180, 300));
- pnlManeuverController.add(pnlRadioButtons);
- pnlManeuverController.add(pnlSlider);
- pnlManeuverController.add(pnlManeuverButtons);
-
- JPanel pnlManeuverInfo = new JPanel();
- pnlManeuverInfo.setLayout(new BoxLayout(pnlManeuverInfo, BoxLayout.Y_AXIS));
- pnlManeuverInfo.setBorder(new TitledBorder("Info. Manobra:"));
- pnlManeuverInfo.setMaximumSize(new Dimension(300, 300));
-
- JPanel pnlMCpnlAP = new JPanel();
- pnlMCpnlAP.setLayout(new BoxLayout(pnlMCpnlAP, BoxLayout.X_AXIS));
- pnlMCpnlAP.add(pnlManeuverController);
- pnlMCpnlAP.add(pnlManeuverInfo);
-
- JPanel pnlControls = new JPanel();
- pnlControls.setLayout(new BoxLayout(pnlControls, BoxLayout.Y_AXIS));
- pnlControls.add(pnlPositionManeuver);
- pnlControls.add(pnlMCpnlAP);
-
- JPanel pnlManeuverList = new JPanel();
- pnlManeuverList.setLayout(new BoxLayout(pnlManeuverList, BoxLayout.Y_AXIS));
- JScrollPane scrollPane = new JScrollPane();
- scrollPane.setViewportView(listCurrentManeuvers);
- pnlManeuverList.add(scrollPane);
- pnlManeuverList.add(btnCreateManeuver);
- pnlManeuverList.add(btnDeleteManeuver);
-
- JPanel pnlOptions = new JPanel();
- pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS));
- pnlOptions.setBorder(new TitledBorder("Lista de Manobras:"));
- pnlOptions.add(pnlManeuverList);
- pnlOptions.setPreferredSize(new Dimension(110, 300));
- pnlOptions.setMaximumSize(new Dimension(110, 300));
-
- JPanel pnlOptionsAndList = new JPanel();
- pnlOptionsAndList.setLayout(new BoxLayout(pnlOptionsAndList, BoxLayout.X_AXIS));
- pnlControls.setAlignmentY(TOP_ALIGNMENT);
- pnlOptions.setAlignmentY(TOP_ALIGNMENT);
- pnlOptionsAndList.add(pnlOptions);
- pnlOptionsAndList.add(Box.createHorizontalStrut(5));
- pnlOptionsAndList.add(pnlControls);
-
- JPanel pnlBackButton = new JPanel();
- pnlBackButton.setLayout(new BoxLayout(pnlBackButton, BoxLayout.X_AXIS));
- pnlBackButton.add(lblManeuverInfo);
- pnlBackButton.add(Box.createHorizontalGlue());
- pnlBackButton.add(btnBack);
-
- JPanel pnlMain = new JPanel();
- pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
- pnlMain.add(pnlOptionsAndList);
-
- add(pnlMain, BorderLayout.CENTER);
- add(pnlBackButton, BorderLayout.SOUTH);
+ }
+
+ private static void handleChangeButtonText(int value) {
+ String decimalPlaces = value > 1 ? "%.0f" : "%.2f";
+ String formattedValue = String.format(Locale.ENGLISH, decimalPlaces, sliderValues.get(value));
+ String suffix = bgManeuverType.getSelection() == rbTime.getModel() ? " s" : "m/s";
+ btnIncrease.setText("+ " + formattedValue + suffix);
+ btnDecrease.setText("- " + formattedValue + suffix);
+ }
+
+ public void createManeuver() {
+ try {
+ createManeuver(vesselManager.getSpaceCenter().getUT() + 60);
+ } catch (RPCException e) {
}
-
- public static void updatePanel(ListModel list) {
- try {
- boolean hasManeuverNodes = list.getSize() > 0;
- boolean hasTargetVessel = MechPeste.getSpaceCenter().getTargetVessel() != null;
- listCurrentManeuvers.setModel(list);
- listCurrentManeuvers.setSelectedIndex(selectedManeuverIndex);
- btnDeleteManeuver.setEnabled(hasManeuverNodes);
- btnAp.setEnabled(hasManeuverNodes);
- btnPe.setEnabled(hasManeuverNodes);
- btnAN.setEnabled(hasManeuverNodes && hasTargetVessel);
- btnDN.setEnabled(hasManeuverNodes && hasTargetVessel);
- btnIncrease.setEnabled(hasManeuverNodes);
- btnDecrease.setEnabled(hasManeuverNodes);
- btnNextOrbit.setEnabled(hasManeuverNodes);
- btnPrevOrbit.setEnabled(hasManeuverNodes);
- lblManeuverInfo.setText(listCurrentManeuvers.getSelectedValue());
- } catch (RPCException ignored) {
- }
+ }
+
+ public void createManeuver(double atFutureTime) {
+ try {
+ Vessel vessel = vesselManager.getSpaceCenter().getActiveVessel();
+
+ if (vessel.getSituation() != VesselSituation.ORBITING) {
+ statusDisplay.setStatusMessage("Não é possível criar a manobra fora de órbita.");
+ return;
+ }
+ vessel.getControl().addNode(atFutureTime, 0, 0, 0);
+ } catch (Exception e) {
}
-
- private static void handleChangeButtonText(int value) {
- String decimalPlaces = value > 1 ? "%.0f" : "%.2f";
- String formattedValue = String.format(Locale.ENGLISH, decimalPlaces, sliderValues.get(value));
- String suffix = bgManeuverType.getSelection() == rbTime.getModel() ? " s" : "m/s";
- btnIncrease.setText("+ " + formattedValue + suffix);
- btnDecrease.setText("- " + formattedValue + suffix);
+ }
+
+ private void deleteManeuver() {
+ try {
+ MechPeste.newInstance();
+ Vessel vessel = vesselManager.getSpaceCenter().getActiveVessel();
+ Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex);
+ currentManeuver.remove();
+ } catch (Exception e) {
}
-
- private void createManeuver() {
- try {
- createManeuver(MechPeste.getSpaceCenter().getUT() + 60);
- } catch (RPCException e) {
- }
+ }
+
+ public void positionManeuverAt(String node) {
+ try {
+ Vessel vessel = vesselManager.getSpaceCenter().getActiveVessel();
+ Orbit orbit = vessel.getOrbit();
+ Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex);
+ double timeToNode = 0;
+ switch (node) {
+ case "apoapsis":
+ timeToNode = vesselManager.getSpaceCenter().getUT() + orbit.getTimeToApoapsis();
+ break;
+ case "periapsis":
+ timeToNode = vesselManager.getSpaceCenter().getUT() + orbit.getTimeToPeriapsis();
+ break;
+ case "ascending":
+ double ascendingAnomaly =
+ orbit.trueAnomalyAtAN(vesselManager.getSpaceCenter().getTargetVessel().getOrbit());
+ timeToNode = orbit.uTAtTrueAnomaly(ascendingAnomaly);
+ break;
+ case "descending":
+ double descendingAnomaly =
+ orbit.trueAnomalyAtDN(vesselManager.getSpaceCenter().getTargetVessel().getOrbit());
+ timeToNode = orbit.uTAtTrueAnomaly(descendingAnomaly);
+ break;
+ }
+ currentManeuver.setUT(timeToNode);
+ // Print the maneuver node information
+ System.out.println("Maneuver Node updated:");
+ System.out.println(" Time to node: " + currentManeuver.getTimeTo() + " s");
+ } catch (Exception e) {
}
-
- private void createManeuver(double atFutureTime) {
- try {
- MechPeste.newInstance();
- Vessel vessel = MechPeste.getSpaceCenter().getActiveVessel();
-
- if (vessel.getSituation() != VesselSituation.ORBITING) {
- StatusJPanel.setStatusMessage("Não é possível criar a manobra fora de órbita.");
- return;
- }
- vessel.getControl().addNode(atFutureTime, 0, 0, 0);
- } catch (Exception e) {
- }
+ }
+
+ private void changeManeuverDeltaV(String command) {
+ try {
+ Vessel vessel = vesselManager.getSpaceCenter().getActiveVessel();
+ Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex);
+ String maneuverType = bgManeuverType.getSelection().getActionCommand();
+ float currentSliderValue = sliderValues.get(sldScale.getValue());
+ currentSliderValue = command == "decrease" ? -currentSliderValue : currentSliderValue;
+
+ switch (maneuverType) {
+ case "prograde":
+ currentManeuver.setPrograde(currentManeuver.getPrograde() + currentSliderValue);
+ break;
+ case "normal":
+ currentManeuver.setNormal(currentManeuver.getNormal() + currentSliderValue);
+ break;
+ case "radial":
+ currentManeuver.setRadial(currentManeuver.getRadial() + currentSliderValue);
+ break;
+ case "time":
+ currentManeuver.setUT(currentManeuver.getUT() + currentSliderValue);
+ break;
+ }
+ } catch (RPCException e) {
+ System.err.println("Erro RPC ao mudar o delta-V da manobra: " + e.getMessage());
+ } catch (Exception e) {
+ System.err.println("Erro ao mudar o delta-V da manobra: " + e.getMessage());
}
-
- private void deleteManeuver() {
- try {
- MechPeste.newInstance();
- Vessel vessel = MechPeste.getSpaceCenter().getActiveVessel();
- Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex);
- currentManeuver.remove();
- } catch (Exception e) {
- }
+ }
+
+ private void changeOrbit(String command) {
+ try {
+ Vessel vessel;
+ vessel = vesselManager.getSpaceCenter().getActiveVessel();
+ Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex);
+ double currentOrbitPeriod = vessel.getOrbit().getPeriod();
+ if (command == "next_orbit") {
+ currentManeuver.setUT(currentManeuver.getUT() + currentOrbitPeriod);
+ } else {
+ double newUT = currentManeuver.getUT() - currentOrbitPeriod;
+ newUT =
+ newUT < vesselManager.getSpaceCenter().getUT()
+ ? vesselManager.getSpaceCenter().getUT() + 60
+ : newUT;
+ currentManeuver.setUT(newUT);
+ }
+ } catch (RPCException ignored) {
}
+ }
- private void positionManeuverAt(String node) {
- try {
- MechPeste.newInstance();
- Vessel vessel = MechPeste.getSpaceCenter().getActiveVessel();
- Orbit orbit = vessel.getOrbit();
- Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex);
- double timeToNode = 0;
- switch (node) {
- case "apoapsis" :
- timeToNode = MechPeste.getSpaceCenter().getUT() + orbit.getTimeToApoapsis();
- break;
- case "periapsis" :
- timeToNode = MechPeste.getSpaceCenter().getUT() + orbit.getTimeToPeriapsis();
- break;
- case "ascending" :
- double ascendingAnomaly = orbit
- .trueAnomalyAtAN(MechPeste.getSpaceCenter().getTargetVessel().getOrbit());
- timeToNode = orbit.uTAtTrueAnomaly(ascendingAnomaly);
- break;
- case "descending" :
- double descendingAnomaly = orbit
- .trueAnomalyAtDN(MechPeste.getSpaceCenter().getTargetVessel().getOrbit());
- timeToNode = orbit.uTAtTrueAnomaly(descendingAnomaly);
- break;
- }
- currentManeuver.setUT(timeToNode);
- // Print the maneuver node information
- System.out.println("Maneuver Node updated:");
- System.out.println(" Time to node: " + currentManeuver.getTimeTo() + " s");
- } catch (Exception e) {
- }
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == btnCreateManeuver) {
+ createManeuver();
}
-
- private void changeManeuverDeltaV(String command) {
- try {
- MechPeste.newInstance();
- Vessel vessel = MechPeste.getSpaceCenter().getActiveVessel();
- Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex);
- String maneuverType = bgManeuverType.getSelection().getActionCommand();
- float currentSliderValue = sliderValues.get(sldScale.getValue());
- currentSliderValue = command == "decrease" ? -currentSliderValue : currentSliderValue;
-
- switch (maneuverType) {
- case "prograde" :
- currentManeuver.setPrograde(currentManeuver.getPrograde() + currentSliderValue);
- break;
- case "normal" :
- currentManeuver.setNormal(currentManeuver.getNormal() + currentSliderValue);
- break;
- case "radial" :
- currentManeuver.setRadial(currentManeuver.getRadial() + currentSliderValue);
- break;
- case "time" :
- currentManeuver.setUT(currentManeuver.getUT() + currentSliderValue);
- break;
- }
- } catch (RPCException e) {
- System.err.println("Erro RPC ao mudar o delta-V da manobra: " + e.getMessage());
- } catch (Exception e) {
- System.err.println("Erro ao mudar o delta-V da manobra: " + e.getMessage());
- }
-
+ if (e.getSource() == btnDeleteManeuver) {
+ deleteManeuver();
}
-
- private void changeOrbit(String command) {
- try {
- MechPeste.newInstance();
- Vessel vessel;
- vessel = MechPeste.getSpaceCenter().getActiveVessel();
- Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex);
- double currentOrbitPeriod = vessel.getOrbit().getPeriod();
- if (command == "next_orbit") {
- currentManeuver.setUT(currentManeuver.getUT() + currentOrbitPeriod);
- } else {
- double newUT = currentManeuver.getUT() - currentOrbitPeriod;
- newUT = newUT < MechPeste.getSpaceCenter().getUT() ? MechPeste.getSpaceCenter().getUT() + 60 : newUT;
- currentManeuver.setUT(newUT);
- }
- } catch (RPCException ignored) {
- }
+ if (e.getSource() == btnIncrease || e.getSource() == btnDecrease) {
+ changeManeuverDeltaV(e.getActionCommand());
}
-
- @Override
- public void actionPerformed(ActionEvent e) {
- if (e.getSource() == btnCreateManeuver) {
- createManeuver();
- }
- if (e.getSource() == btnDeleteManeuver) {
- deleteManeuver();
- }
- if (e.getSource() == btnIncrease || e.getSource() == btnDecrease) {
- changeManeuverDeltaV(e.getActionCommand());
- }
- if (e.getSource() == btnNextOrbit || e.getSource() == btnPrevOrbit) {
- changeOrbit(e.getActionCommand());
- }
- if (e.getSource() == btnAp || e.getSource() == btnPe || e.getSource() == btnAN || e.getSource() == btnDN) {
- positionManeuverAt(e.getActionCommand());
- }
- if (e.getSource() == btnBack) {
- MainGui.backToTelemetry(e);
- }
+ if (e.getSource() == btnNextOrbit || e.getSource() == btnPrevOrbit) {
+ changeOrbit(e.getActionCommand());
+ }
+ if (e.getSource() == btnAp
+ || e.getSource() == btnPe
+ || e.getSource() == btnAN
+ || e.getSource() == btnDN) {
+ positionManeuverAt(e.getActionCommand());
+ }
+ if (e.getSource() == btnBack) {
+ MainGui.backToTelemetry(e);
}
+ }
}
diff --git a/src/main/java/com/pesterenan/views/DockingJPanel.java b/src/main/java/com/pesterenan/views/DockingJPanel.java
index 151c929..683a2b8 100644
--- a/src/main/java/com/pesterenan/views/DockingJPanel.java
+++ b/src/main/java/com/pesterenan/views/DockingJPanel.java
@@ -1,156 +1,171 @@
package com.pesterenan.views;
-import com.pesterenan.MechPeste;
+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;
+
+import com.pesterenan.model.VesselManager;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.Module;
-
-import javax.swing.*;
-import javax.swing.border.TitledBorder;
-import java.awt.*;
+import java.awt.BorderLayout;
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;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+import javax.swing.border.TitledBorder;
public class DockingJPanel extends JPanel implements UIMethods {
- private static final long serialVersionUID = 0L;
-
- private JLabel lblMaxSpeed, lblSafeDistance, lblCurrentDockingStepText;
- private static JLabel lblDockingStep;
-
- private JTextField txfMaxSpeed, txfSafeDistance;
- private JButton btnBack, btnStartDocking;
-
- public DockingJPanel() {
- initComponents();
- setupComponents();
- layoutComponents();
- }
-
- @Override
- public void initComponents() {
- // Labels:
- lblMaxSpeed = new JLabel(Bundle.getString("pnl_docking_max_speed"));
- lblSafeDistance = new JLabel(Bundle.getString("pnl_docking_safe_distance"));
- lblDockingStep = new JLabel(Bundle.getString("pnl_docking_step_ready"));
- lblCurrentDockingStepText = new JLabel(Bundle.getString("pnl_docking_current_step"));
- // Textfields:
- txfMaxSpeed = new JTextField("3");
- txfSafeDistance = new JTextField("50");
-
- // 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);
- txfSafeDistance.setHorizontalAlignment(SwingConstants.RIGHT);
- txfSafeDistance.setMaximumSize(BTN_DIMENSION);
- txfSafeDistance.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 pnlSafeDistance = new JPanel();
- pnlSafeDistance.setLayout(new BoxLayout(pnlSafeDistance, BoxLayout.X_AXIS));
- pnlSafeDistance.add(lblSafeDistance);
- pnlSafeDistance.add(Box.createHorizontalGlue());
- pnlSafeDistance.add(txfSafeDistance);
-
- JPanel pnlDockingStep = new JPanel();
- pnlDockingStep.setLayout(new BoxLayout(pnlDockingStep, BoxLayout.X_AXIS));
- pnlDockingStep.add(lblCurrentDockingStepText);
- pnlDockingStep.add(Box.createHorizontalGlue());
- pnlDockingStep.add(lblDockingStep);
-
- JPanel pnlDockingControls = new JPanel();
- pnlDockingControls.setLayout(new BoxLayout(pnlDockingControls, BoxLayout.Y_AXIS));
- pnlDockingControls.setBorder(MARGIN_BORDER_10_PX_LR);
- pnlDockingControls.add(MainGui.createMarginComponent(0, 6));
- pnlDockingControls.add(pnlMaxSpeed);
- pnlDockingControls.add(pnlSafeDistance);
- pnlDockingControls.add(Box.createVerticalGlue());
- pnlDockingControls.add(pnlDockingStep);
- pnlDockingControls.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));
- pnlDockingControls.setAlignmentY(TOP_ALIGNMENT);
- pnlMain.add(pnlDockingControls);
-
- setLayout(new BorderLayout());
- add(pnlMain, BorderLayout.CENTER);
- add(pnlButtons, BorderLayout.SOUTH);
- }
-
- public static void setDockingStep(String step) {
- lblDockingStep.setText(step);
+ private static final long serialVersionUID = 0L;
+
+ private JLabel lblMaxSpeed, lblSafeDistance, lblCurrentDockingStepText;
+ private static JLabel lblDockingStep;
+
+ private JTextField txfMaxSpeed, txfSafeDistance;
+ private JButton btnBack, btnStartDocking;
+
+ private VesselManager vesselManager;
+
+ private StatusDisplay statusDisplay;
+
+ public DockingJPanel(StatusDisplay statusDisplay) {
+ this.statusDisplay = statusDisplay;
+ initComponents();
+ setupComponents();
+ layoutComponents();
+ }
+
+ public void setVesselManager(VesselManager vesselManager) {
+ this.vesselManager = vesselManager;
+ }
+
+ @Override
+ public void initComponents() {
+ // Labels:
+ lblMaxSpeed = new JLabel(Bundle.getString("pnl_docking_max_speed"));
+ lblSafeDistance = new JLabel(Bundle.getString("pnl_docking_safe_distance"));
+ lblDockingStep = new JLabel(Bundle.getString("pnl_docking_step_ready"));
+ lblCurrentDockingStepText = new JLabel(Bundle.getString("pnl_docking_current_step"));
+ // Textfields:
+ txfMaxSpeed = new JTextField("3");
+ txfSafeDistance = new JTextField("50");
+
+ // 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);
+ txfSafeDistance.setHorizontalAlignment(SwingConstants.RIGHT);
+ txfSafeDistance.setMaximumSize(BTN_DIMENSION);
+ txfSafeDistance.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 pnlSafeDistance = new JPanel();
+ pnlSafeDistance.setLayout(new BoxLayout(pnlSafeDistance, BoxLayout.X_AXIS));
+ pnlSafeDistance.add(lblSafeDistance);
+ pnlSafeDistance.add(Box.createHorizontalGlue());
+ pnlSafeDistance.add(txfSafeDistance);
+
+ JPanel pnlDockingStep = new JPanel();
+ pnlDockingStep.setLayout(new BoxLayout(pnlDockingStep, BoxLayout.X_AXIS));
+ pnlDockingStep.add(lblCurrentDockingStepText);
+ pnlDockingStep.add(Box.createHorizontalGlue());
+ pnlDockingStep.add(lblDockingStep);
+
+ JPanel pnlDockingControls = new JPanel();
+ pnlDockingControls.setLayout(new BoxLayout(pnlDockingControls, BoxLayout.Y_AXIS));
+ pnlDockingControls.setBorder(MARGIN_BORDER_10_PX_LR);
+ pnlDockingControls.add(MainGui.createMarginComponent(0, 6));
+ pnlDockingControls.add(pnlMaxSpeed);
+ pnlDockingControls.add(pnlSafeDistance);
+ pnlDockingControls.add(Box.createVerticalGlue());
+ pnlDockingControls.add(pnlDockingStep);
+ pnlDockingControls.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));
+ pnlDockingControls.setAlignmentY(TOP_ALIGNMENT);
+ pnlMain.add(pnlDockingControls);
+
+ setLayout(new BorderLayout());
+ add(pnlMain, BorderLayout.CENTER);
+ add(pnlButtons, BorderLayout.SOUTH);
+ }
+
+ public static void setDockingStep(String step) {
+ lblDockingStep.setText(step);
+ }
+
+ private void handleStartDocking(ActionEvent e) {
+ if (validateTextFields()) {
+ Map commands = new HashMap<>();
+ commands.put(Module.MODULO.get(), Module.DOCKING.get());
+ commands.put(Module.SAFE_DISTANCE.get(), txfSafeDistance.getText());
+ commands.put(Module.MAX_SPEED.get(), txfMaxSpeed.getText());
+ vesselManager.startModule(commands);
}
-
- private void handleStartDocking(ActionEvent e) {
- if (validateTextFields()) {
- Map commands = new HashMap<>();
- commands.put(Module.MODULO.get(), Module.DOCKING.get());
- commands.put(Module.SAFE_DISTANCE.get(), txfSafeDistance.getText());
- commands.put(Module.MAX_SPEED.get(), txfMaxSpeed.getText());
- MechPeste.newInstance().startModule(commands);
- }
- }
-
- private boolean validateTextFields() {
- try {
- if (Float.parseFloat(txfMaxSpeed.getText()) > 10) {
- StatusJPanel.setStatusMessage("Velocidade de acoplagem muito alta. Tem que ser menor que 10m/s.");
- return false;
- }
- if (Float.parseFloat(txfSafeDistance.getText()) > 200) {
- StatusJPanel.setStatusMessage("Distância segura muito alta. Tem que ser menor que 200m.");
- return false;
- }
- } catch (NumberFormatException e) {
- StatusJPanel.setStatusMessage(Bundle.getString("pnl_lift_stat_only_numbers"));
- return false;
- } catch (IllegalArgumentException e) {
- StatusJPanel.setStatusMessage(Bundle.getString("pnl_rover_waypoint_name_not_empty"));
- return false;
- }
- return true;
+ }
+
+ private boolean validateTextFields() {
+ try {
+ if (Float.parseFloat(txfMaxSpeed.getText()) > 10) {
+ statusDisplay.setStatusMessage(
+ "Velocidade de acoplagem muito alta. Tem que ser menor que 10m/s.");
+ return false;
+ }
+ if (Float.parseFloat(txfSafeDistance.getText()) > 200) {
+ statusDisplay.setStatusMessage("Distância segura muito alta. Tem que ser menor que 200m.");
+ return false;
+ }
+ } catch (NumberFormatException e) {
+ statusDisplay.setStatusMessage(Bundle.getString("pnl_lift_stat_only_numbers"));
+ return false;
+ } catch (IllegalArgumentException e) {
+ statusDisplay.setStatusMessage(Bundle.getString("pnl_rover_waypoint_name_not_empty"));
+ return false;
}
+ return true;
+ }
}
diff --git a/src/main/java/com/pesterenan/views/FunctionsAndTelemetryJPanel.java b/src/main/java/com/pesterenan/views/FunctionsAndTelemetryJPanel.java
index 816b06a..b603bfc 100644
--- a/src/main/java/com/pesterenan/views/FunctionsAndTelemetryJPanel.java
+++ b/src/main/java/com/pesterenan/views/FunctionsAndTelemetryJPanel.java
@@ -1,197 +1,235 @@
package com.pesterenan.views;
-import com.pesterenan.MechPeste;
+import static com.pesterenan.views.MainGui.PNL_DIMENSION;
+
+import com.pesterenan.model.VesselManager;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.Module;
import com.pesterenan.utils.Telemetry;
import com.pesterenan.utils.Utilities;
-
-import javax.swing.*;
-import javax.swing.border.TitledBorder;
-
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.Map;
-
-import static com.pesterenan.views.MainGui.PNL_DIMENSION;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.TitledBorder;
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, btnDocking, btnRover, btnCancel;
- private static JLabel lblAltitude, lblSurfaceAlt, lblApoapsis, lblPeriapsis, lblVertSpeed, lblHorzSpeed;
- private static JLabel lblAltitudeValue, lblSurfaceAltValue, lblApoapsisValue;
- private static JLabel lblPeriapsisValue, lblVertSpeedValue, lblHorzSpeedValue;
-
- public FunctionsAndTelemetryJPanel() {
- initComponents();
- setupComponents();
- layoutComponents();
- }
-
- @Override
- public void initComponents() {
- // Labels:
- lblAltitude = new JLabel(Bundle.getString("pnl_tel_lbl_alt"));
- lblSurfaceAlt = new JLabel(Bundle.getString("pnl_tel_lbl_alt_sur"));
- lblApoapsis = new JLabel(Bundle.getString("pnl_tel_lbl_apoapsis"));
- lblPeriapsis = new JLabel(Bundle.getString("pnl_tel_lbl_periapsis"));
- lblVertSpeed = new JLabel(Bundle.getString("pnl_tel_lbl_vert_spd"));
- lblHorzSpeed = new JLabel(Bundle.getString("pnl_tel_lbl_horz_spd"));
- lblAltitudeValue = new JLabel("---");
- lblSurfaceAltValue = new JLabel("---");
- lblApoapsisValue = new JLabel("---");
- lblPeriapsisValue = new JLabel("---");
- lblVertSpeedValue = new JLabel("---");
- lblHorzSpeedValue = new JLabel("---");
-
- // Buttons:
- btnLiftoff = new JButton(Bundle.getString("btn_func_liftoff"));
- 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"));
- }
-
- @Override
- public void setupComponents() {
- setPreferredSize(PNL_DIMENSION);
- setBorder(new TitledBorder(null, Bundle.getString("pnl_func_title"), TitledBorder.LEADING, TitledBorder.TOP,
- null, null));
- setLayout(new BorderLayout());
-
- // Setting up components:
- btnCancel.addActionListener(MechPeste::cancelControl);
- btnCancel.setMaximumSize(btnFuncDimension);
- btnCancel.setPreferredSize(btnFuncDimension);
- btnLanding.addActionListener(this::changeFunctionPanel);
- btnLanding.setActionCommand(Module.LANDING.get());
- btnLanding.setMaximumSize(btnFuncDimension);
- btnLanding.setPreferredSize(btnFuncDimension);
- btnLiftoff.addActionListener(this::changeFunctionPanel);
- btnLiftoff.setActionCommand(Module.LIFTOFF.get());
- btnLiftoff.setMaximumSize(btnFuncDimension);
- btnLiftoff.setPreferredSize(btnFuncDimension);
- btnManeuvers.addActionListener(this::changeFunctionPanel);
- btnManeuvers.setActionCommand(Module.MANEUVER.get());
- btnManeuvers.setMaximumSize(btnFuncDimension);
- btnManeuvers.setPreferredSize(btnFuncDimension);
- btnRover.addActionListener(this::changeFunctionPanel);
- btnRover.setActionCommand(Module.ROVER.get());
- btnRover.setMaximumSize(btnFuncDimension);
- btnRover.setPreferredSize(btnFuncDimension);
- btnDocking.addActionListener(this::changeFunctionPanel);
- btnDocking.setActionCommand(Module.DOCKING.get());
- btnDocking.setMaximumSize(btnFuncDimension);
- btnDocking.setPreferredSize(btnFuncDimension);
- }
-
- @Override
- public void layoutComponents() {
-
- JPanel pnlFunctionControls = new JPanel();
- pnlFunctionControls.setLayout(new BoxLayout(pnlFunctionControls, BoxLayout.Y_AXIS));
- pnlFunctionControls.add(MainGui.createMarginComponent(0, 4));
- pnlFunctionControls.add(btnLiftoff);
- pnlFunctionControls.add(btnLanding);
- pnlFunctionControls.add(btnRover);
- pnlFunctionControls.add(btnDocking);
- pnlFunctionControls.add(btnManeuvers);
- pnlFunctionControls.add(Box.createVerticalGlue());
-
- JPanel pnlLeftPanel = new JPanel();
- pnlLeftPanel.setBorder(MainGui.MARGIN_BORDER_10_PX_LR);
- pnlLeftPanel.setLayout(new BoxLayout(pnlLeftPanel, BoxLayout.Y_AXIS));
- pnlLeftPanel.add(lblAltitude);
- pnlLeftPanel.add(Box.createVerticalStrut(5));
- pnlLeftPanel.add(lblSurfaceAlt);
- pnlLeftPanel.add(Box.createVerticalStrut(5));
- pnlLeftPanel.add(lblApoapsis);
- pnlLeftPanel.add(Box.createVerticalStrut(5));
- pnlLeftPanel.add(lblPeriapsis);
- pnlLeftPanel.add(Box.createVerticalStrut(5));
- pnlLeftPanel.add(lblHorzSpeed);
- pnlLeftPanel.add(Box.createVerticalStrut(5));
- pnlLeftPanel.add(lblVertSpeed);
- pnlLeftPanel.add(Box.createGlue());
-
- JPanel pnlRightPanel = new JPanel();
- pnlRightPanel.setBorder(MainGui.MARGIN_BORDER_10_PX_LR);
- pnlRightPanel.setLayout(new BoxLayout(pnlRightPanel, BoxLayout.Y_AXIS));
- lblAltitudeValue.setAlignmentX(RIGHT_ALIGNMENT);
- lblSurfaceAltValue.setAlignmentX(RIGHT_ALIGNMENT);
- lblApoapsisValue.setAlignmentX(RIGHT_ALIGNMENT);
- lblPeriapsisValue.setAlignmentX(RIGHT_ALIGNMENT);
- lblHorzSpeedValue.setAlignmentX(RIGHT_ALIGNMENT);
- lblVertSpeedValue.setAlignmentX(RIGHT_ALIGNMENT);
- pnlRightPanel.add(lblAltitudeValue);
- pnlRightPanel.add(Box.createVerticalStrut(5));
- pnlRightPanel.add(lblSurfaceAltValue);
- pnlRightPanel.add(Box.createVerticalStrut(5));
- pnlRightPanel.add(lblApoapsisValue);
- pnlRightPanel.add(Box.createVerticalStrut(5));
- pnlRightPanel.add(lblPeriapsisValue);
- pnlRightPanel.add(Box.createVerticalStrut(5));
- pnlRightPanel.add(lblHorzSpeedValue);
- pnlRightPanel.add(Box.createVerticalStrut(5));
- pnlRightPanel.add(lblVertSpeedValue);
- pnlRightPanel.add(Box.createGlue());
-
- JPanel pnlLeftRightContainer = new JPanel();
- pnlLeftRightContainer.setLayout(new BoxLayout(pnlLeftRightContainer, BoxLayout.X_AXIS));
- pnlLeftRightContainer.add(pnlLeftPanel);
- pnlLeftRightContainer.add(pnlRightPanel);
-
- JPanel pnlTelemetry = new JPanel();
- pnlTelemetry.setLayout(new BoxLayout(pnlTelemetry, BoxLayout.Y_AXIS));
- pnlTelemetry.setBorder(new TitledBorder(null, Bundle.getString("pnl_tel_border")));
- pnlTelemetry.add(pnlLeftRightContainer);
- pnlTelemetry.add(Box.createGlue());
- btnCancel.setAlignmentX(CENTER_ALIGNMENT);
- pnlTelemetry.add(btnCancel);
-
- JPanel pnlMain = new JPanel();
- pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
- pnlFunctionControls.setAlignmentY(TOP_ALIGNMENT);
- pnlTelemetry.setAlignmentY(TOP_ALIGNMENT);
- pnlMain.add(pnlFunctionControls);
- pnlMain.add(pnlTelemetry);
-
- add(pnlMain, BorderLayout.CENTER);
- }
-
- private void changeFunctionPanel(ActionEvent e) {
- MainGui.changeToPage(e);
- }
-
- public static void updateTelemetry(Map telemetryData) {
- synchronized (telemetryData) {
- for (Telemetry key : telemetryData.keySet()) {
- switch (key) {
- case ALTITUDE :
- lblAltitudeValue.setText(Utilities.convertToMetersMagnitudes(telemetryData.get(key)));
- break;
- case ALT_SURF :
- lblSurfaceAltValue.setText(Utilities.convertToMetersMagnitudes(telemetryData.get(key)));
- break;
- case APOAPSIS :
- lblApoapsisValue.setText(Utilities.convertToMetersMagnitudes(telemetryData.get(key)));
- break;
- case PERIAPSIS :
- lblPeriapsisValue.setText(Utilities.convertToMetersMagnitudes(telemetryData.get(key)));
- break;
- case VERT_SPEED :
- lblVertSpeedValue.setText(Utilities.convertToMetersMagnitudes(telemetryData.get(key)) + "/s");
- break;
- case HORZ_SPEED :
- lblHorzSpeedValue.setText(Utilities.convertToMetersMagnitudes(telemetryData.get(key)) + "/s");
- break;
- }
- }
+ private static final long serialVersionUID = 0L;
+
+ private final Dimension btnFuncDimension = new Dimension(140, 25);
+ private JButton btnLiftoff, btnLanding, btnManeuvers, btnDocking, btnRover, btnCancel;
+ private JLabel lblAltitude, lblSurfaceAlt, lblApoapsis, lblPeriapsis, lblVertSpeed, lblHorzSpeed;
+ private JLabel lblAltitudeValue, lblSurfaceAltValue, lblApoapsisValue;
+ private JLabel lblPeriapsisValue, lblVertSpeedValue, lblHorzSpeedValue;
+
+ private VesselManager vesselManager;
+
+ private StatusDisplay statusDisplay;
+
+ public FunctionsAndTelemetryJPanel(StatusDisplay statusDisplay) {
+ this.statusDisplay = statusDisplay;
+ initComponents();
+ setupComponents();
+ layoutComponents();
+ }
+
+ public void setVesselManager(VesselManager vesselManager) {
+ this.vesselManager = vesselManager;
+ btnCancel.setEnabled(true);
+ }
+
+ @Override
+ public void initComponents() {
+ // Labels:
+ lblAltitude = new JLabel(Bundle.getString("pnl_tel_lbl_alt"));
+ lblSurfaceAlt = new JLabel(Bundle.getString("pnl_tel_lbl_alt_sur"));
+ lblApoapsis = new JLabel(Bundle.getString("pnl_tel_lbl_apoapsis"));
+ lblPeriapsis = new JLabel(Bundle.getString("pnl_tel_lbl_periapsis"));
+ lblVertSpeed = new JLabel(Bundle.getString("pnl_tel_lbl_vert_spd"));
+ lblHorzSpeed = new JLabel(Bundle.getString("pnl_tel_lbl_horz_spd"));
+ lblAltitudeValue = new JLabel("---");
+ lblSurfaceAltValue = new JLabel("---");
+ lblApoapsisValue = new JLabel("---");
+ lblPeriapsisValue = new JLabel("---");
+ lblVertSpeedValue = new JLabel("---");
+ lblHorzSpeedValue = new JLabel("---");
+
+ // Buttons:
+ btnLiftoff = new JButton(Bundle.getString("btn_func_liftoff"));
+ 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"));
+ }
+
+ @Override
+ public void setupComponents() {
+ setPreferredSize(PNL_DIMENSION);
+ setBorder(
+ new TitledBorder(
+ null,
+ Bundle.getString("pnl_func_title"),
+ TitledBorder.LEADING,
+ TitledBorder.TOP,
+ null,
+ null));
+ setLayout(new BorderLayout());
+
+ // Setting up components:
+ btnCancel.addActionListener(e -> cancelCurrentAction(e));
+ btnCancel.setMaximumSize(btnFuncDimension);
+ btnCancel.setPreferredSize(btnFuncDimension);
+ btnCancel.setEnabled(false);
+ btnLanding.addActionListener(this::changeFunctionPanel);
+ btnLanding.setActionCommand(Module.LANDING.get());
+ btnLanding.setMaximumSize(btnFuncDimension);
+ btnLanding.setPreferredSize(btnFuncDimension);
+ btnLiftoff.addActionListener(this::changeFunctionPanel);
+ btnLiftoff.setActionCommand(Module.LIFTOFF.get());
+ btnLiftoff.setMaximumSize(btnFuncDimension);
+ btnLiftoff.setPreferredSize(btnFuncDimension);
+ btnManeuvers.addActionListener(this::changeFunctionPanel);
+ btnManeuvers.setActionCommand(Module.MANEUVER.get());
+ btnManeuvers.setMaximumSize(btnFuncDimension);
+ btnManeuvers.setPreferredSize(btnFuncDimension);
+ btnRover.addActionListener(this::changeFunctionPanel);
+ btnRover.setActionCommand(Module.ROVER.get());
+ btnRover.setMaximumSize(btnFuncDimension);
+ btnRover.setPreferredSize(btnFuncDimension);
+ btnDocking.addActionListener(this::changeFunctionPanel);
+ btnDocking.setActionCommand(Module.DOCKING.get());
+ btnDocking.setMaximumSize(btnFuncDimension);
+ btnDocking.setPreferredSize(btnFuncDimension);
+ btnDocking.setEnabled(false); // FIX: Not yet ready
+ }
+
+ private void cancelCurrentAction(ActionEvent e) {
+ statusDisplay.setStatusMessage("Canceling current action...");
+ vesselManager.cancelControl(e);
+ ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
+ executor.schedule(
+ () -> {
+ statusDisplay.setStatusMessage(Bundle.getString("lbl_stat_ready"));
+ },
+ 2,
+ TimeUnit.SECONDS);
+ executor.shutdown();
+ }
+
+ @Override
+ public void layoutComponents() {
+
+ JPanel pnlFunctionControls = new JPanel();
+ pnlFunctionControls.setLayout(new BoxLayout(pnlFunctionControls, BoxLayout.Y_AXIS));
+ pnlFunctionControls.add(MainGui.createMarginComponent(0, 4));
+ pnlFunctionControls.add(btnLiftoff);
+ pnlFunctionControls.add(btnLanding);
+ pnlFunctionControls.add(btnRover);
+ pnlFunctionControls.add(btnDocking);
+ pnlFunctionControls.add(btnManeuvers);
+ pnlFunctionControls.add(Box.createVerticalGlue());
+
+ JPanel pnlLeftPanel = new JPanel();
+ pnlLeftPanel.setBorder(MainGui.MARGIN_BORDER_10_PX_LR);
+ pnlLeftPanel.setLayout(new BoxLayout(pnlLeftPanel, BoxLayout.Y_AXIS));
+ pnlLeftPanel.add(lblAltitude);
+ pnlLeftPanel.add(Box.createVerticalStrut(5));
+ pnlLeftPanel.add(lblSurfaceAlt);
+ pnlLeftPanel.add(Box.createVerticalStrut(5));
+ pnlLeftPanel.add(lblApoapsis);
+ pnlLeftPanel.add(Box.createVerticalStrut(5));
+ pnlLeftPanel.add(lblPeriapsis);
+ pnlLeftPanel.add(Box.createVerticalStrut(5));
+ pnlLeftPanel.add(lblHorzSpeed);
+ pnlLeftPanel.add(Box.createVerticalStrut(5));
+ pnlLeftPanel.add(lblVertSpeed);
+ pnlLeftPanel.add(Box.createGlue());
+
+ JPanel pnlRightPanel = new JPanel();
+ pnlRightPanel.setBorder(MainGui.MARGIN_BORDER_10_PX_LR);
+ pnlRightPanel.setLayout(new BoxLayout(pnlRightPanel, BoxLayout.Y_AXIS));
+ lblAltitudeValue.setAlignmentX(RIGHT_ALIGNMENT);
+ lblSurfaceAltValue.setAlignmentX(RIGHT_ALIGNMENT);
+ lblApoapsisValue.setAlignmentX(RIGHT_ALIGNMENT);
+ lblPeriapsisValue.setAlignmentX(RIGHT_ALIGNMENT);
+ lblHorzSpeedValue.setAlignmentX(RIGHT_ALIGNMENT);
+ lblVertSpeedValue.setAlignmentX(RIGHT_ALIGNMENT);
+ pnlRightPanel.add(lblAltitudeValue);
+ pnlRightPanel.add(Box.createVerticalStrut(5));
+ pnlRightPanel.add(lblSurfaceAltValue);
+ pnlRightPanel.add(Box.createVerticalStrut(5));
+ pnlRightPanel.add(lblApoapsisValue);
+ pnlRightPanel.add(Box.createVerticalStrut(5));
+ pnlRightPanel.add(lblPeriapsisValue);
+ pnlRightPanel.add(Box.createVerticalStrut(5));
+ pnlRightPanel.add(lblHorzSpeedValue);
+ pnlRightPanel.add(Box.createVerticalStrut(5));
+ pnlRightPanel.add(lblVertSpeedValue);
+ pnlRightPanel.add(Box.createGlue());
+
+ JPanel pnlLeftRightContainer = new JPanel();
+ pnlLeftRightContainer.setLayout(new BoxLayout(pnlLeftRightContainer, BoxLayout.X_AXIS));
+ pnlLeftRightContainer.add(pnlLeftPanel);
+ pnlLeftRightContainer.add(pnlRightPanel);
+
+ JPanel pnlTelemetry = new JPanel();
+ pnlTelemetry.setLayout(new BoxLayout(pnlTelemetry, BoxLayout.Y_AXIS));
+ pnlTelemetry.setBorder(new TitledBorder(null, Bundle.getString("pnl_tel_border")));
+ pnlTelemetry.add(pnlLeftRightContainer);
+ pnlTelemetry.add(Box.createGlue());
+ btnCancel.setAlignmentX(CENTER_ALIGNMENT);
+ pnlTelemetry.add(btnCancel);
+
+ JPanel pnlMain = new JPanel();
+ pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
+ pnlFunctionControls.setAlignmentY(TOP_ALIGNMENT);
+ pnlTelemetry.setAlignmentY(TOP_ALIGNMENT);
+ pnlMain.add(pnlFunctionControls);
+ pnlMain.add(pnlTelemetry);
+
+ add(pnlMain, BorderLayout.CENTER);
+ }
+
+ private void changeFunctionPanel(ActionEvent e) {
+ MainGui.changeToPage(e);
+ }
+
+ public void updateTelemetry(Map telemetryData) {
+ synchronized (telemetryData) {
+ for (Telemetry key : telemetryData.keySet()) {
+ switch (key) {
+ case ALTITUDE:
+ lblAltitudeValue.setText(Utilities.convertToMetersMagnitudes(telemetryData.get(key)));
+ break;
+ case ALT_SURF:
+ lblSurfaceAltValue.setText(Utilities.convertToMetersMagnitudes(telemetryData.get(key)));
+ break;
+ case APOAPSIS:
+ lblApoapsisValue.setText(Utilities.convertToMetersMagnitudes(telemetryData.get(key)));
+ break;
+ case PERIAPSIS:
+ lblPeriapsisValue.setText(Utilities.convertToMetersMagnitudes(telemetryData.get(key)));
+ break;
+ case VERT_SPEED:
+ lblVertSpeedValue.setText(
+ Utilities.convertToMetersMagnitudes(telemetryData.get(key)) + "/s");
+ break;
+ case HORZ_SPEED:
+ lblHorzSpeedValue.setText(
+ Utilities.convertToMetersMagnitudes(telemetryData.get(key)) + "/s");
+ break;
}
+ }
}
+ }
}
diff --git a/src/main/java/com/pesterenan/views/InstallKrpcDialog.java b/src/main/java/com/pesterenan/views/InstallKrpcDialog.java
index 370cdfc..051bb75 100644
--- a/src/main/java/com/pesterenan/views/InstallKrpcDialog.java
+++ b/src/main/java/com/pesterenan/views/InstallKrpcDialog.java
@@ -2,7 +2,6 @@
import com.pesterenan.resources.Bundle;
import com.pesterenan.updater.KrpcInstaller;
-
import javax.swing.*;
import javax.swing.GroupLayout.Alignment;
import javax.swing.LayoutStyle.ComponentPlacement;
@@ -10,136 +9,209 @@
import javax.swing.border.TitledBorder;
public class InstallKrpcDialog extends JDialog {
- private static final long serialVersionUID = 1L;
- private JLabel lblInstallerInfo;
- private final JSeparator separator = new JSeparator();
- private final JPanel pnlKspFolderPath = new JPanel();
- private final JTextField txfPath = new JTextField();
- private JButton btnBrowsePath;
- private JButton btnDownloadInstall;
- private JButton btnCancel;
- private JPanel pnlStatus;
- private static JLabel lblStatus;
-
- public InstallKrpcDialog() {
- try {
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- initComponents();
- } catch (Throwable e) {
- e.printStackTrace();
- }
+ private static final long serialVersionUID = 1L;
+ private JLabel lblInstallerInfo;
+ private final JSeparator separator = new JSeparator();
+ private final JPanel pnlKspFolderPath = new JPanel();
+ private final JTextField txfPath = new JTextField();
+ private JButton btnBrowsePath;
+ private JButton btnDownloadInstall;
+ private JButton btnCancel;
+ private JPanel pnlStatus;
+ private static JLabel lblStatus;
+
+ public InstallKrpcDialog() {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ initComponents();
+ } catch (Throwable e) {
+ e.printStackTrace();
}
-
- private void initComponents() {
- setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
- setResizable(false);
- setBounds(MainGui.centerDialogOnScreen());
- setAlwaysOnTop(true);
- setModalityType(ModalityType.APPLICATION_MODAL);
- setTitle(Bundle.getString("installer_dialog_title")); //$NON-NLS-1$
-
- lblInstallerInfo = new JLabel(Bundle.getString("installer_dialog_txt_info")); //$NON-NLS-1$
-
- pnlKspFolderPath
- .setBorder(new TitledBorder(null, Bundle.getString("installer_dialog_pnl_path"), TitledBorder.LEADING, // $NON
- // -NLS-1$
- TitledBorder.TOP, null, null));
-
- btnDownloadInstall = new JButton(Bundle.getString("installer_dialog_btn_download")); // $NON
- // -NLS-1$
- btnDownloadInstall.addActionListener((e) -> KrpcInstaller.downloadAndInstallKrpc());
- btnDownloadInstall.setEnabled(false);
-
- btnCancel = new JButton(Bundle.getString("installer_dialog_btn_cancel")); //$NON-NLS-1$
- btnCancel.addActionListener((e) -> this.dispose());
-
- pnlStatus = new JPanel();
- pnlStatus.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
-
- GroupLayout groupLayout = new GroupLayout(getContentPane());
- groupLayout.setHorizontalGroup(groupLayout.createParallelGroup(Alignment.TRAILING).addGroup(groupLayout
- .createSequentialGroup().addContainerGap()
- .addGroup(groupLayout.createParallelGroup(Alignment.LEADING)
- .addComponent(pnlKspFolderPath, GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE)
- .addComponent(lblInstallerInfo, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 414,
+ }
+
+ private void initComponents() {
+ setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
+ setResizable(false);
+ setBounds(MainGui.centerDialogOnScreen());
+ setAlwaysOnTop(true);
+ setModalityType(ModalityType.APPLICATION_MODAL);
+ setTitle(Bundle.getString("installer_dialog_title")); // $NON-NLS-1$
+
+ lblInstallerInfo = new JLabel(Bundle.getString("installer_dialog_txt_info")); // $NON-NLS-1$
+
+ pnlKspFolderPath.setBorder(
+ new TitledBorder(
+ null,
+ Bundle.getString("installer_dialog_pnl_path"),
+ TitledBorder.LEADING, // $NON
+ // -NLS-1$
+ TitledBorder.TOP,
+ null,
+ null));
+
+ btnDownloadInstall = new JButton(Bundle.getString("installer_dialog_btn_download")); // $NON
+ // -NLS-1$
+ btnDownloadInstall.addActionListener((e) -> KrpcInstaller.downloadAndInstallKrpc());
+ btnDownloadInstall.setEnabled(false);
+
+ btnCancel = new JButton(Bundle.getString("installer_dialog_btn_cancel")); // $NON-NLS-1$
+ btnCancel.addActionListener((e) -> this.dispose());
+
+ pnlStatus = new JPanel();
+ pnlStatus.setBorder(new BevelBorder(BevelBorder.LOWERED, null, null, null, null));
+
+ GroupLayout groupLayout = new GroupLayout(getContentPane());
+ groupLayout.setHorizontalGroup(
+ groupLayout
+ .createParallelGroup(Alignment.TRAILING)
+ .addGroup(
+ groupLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addGroup(
+ groupLayout
+ .createParallelGroup(Alignment.LEADING)
+ .addComponent(
+ pnlKspFolderPath, GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE)
+ .addComponent(
+ lblInstallerInfo,
+ Alignment.TRAILING,
+ GroupLayout.DEFAULT_SIZE,
+ 414,
Short.MAX_VALUE)
- .addComponent(separator, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 414, Short.MAX_VALUE)
- .addGroup(groupLayout.createSequentialGroup().addComponent(btnDownloadInstall)
- .addPreferredGap(ComponentPlacement.RELATED, 184, Short.MAX_VALUE)
- .addComponent(btnCancel)))
- .addGap(10))
- .addComponent(pnlStatus, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 434, Short.MAX_VALUE));
- groupLayout.setVerticalGroup(groupLayout.createParallelGroup(Alignment.LEADING)
- .addGroup(groupLayout.createSequentialGroup().addContainerGap()
- .addComponent(lblInstallerInfo, GroupLayout.PREFERRED_SIZE, 60, GroupLayout.PREFERRED_SIZE)
- .addGap(2).addComponent(separator, GroupLayout.PREFERRED_SIZE, 2, GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(ComponentPlacement.UNRELATED)
- .addComponent(pnlKspFolderPath, GroupLayout.PREFERRED_SIZE, 51, GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(ComponentPlacement.UNRELATED)
- .addGroup(groupLayout.createParallelGroup(Alignment.BASELINE).addComponent(btnDownloadInstall)
- .addComponent(btnCancel))
- .addPreferredGap(ComponentPlacement.RELATED, 60, Short.MAX_VALUE)
- .addComponent(pnlStatus, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)));
-
- lblStatus = new JLabel();
- GroupLayout glPnlStatus = new GroupLayout(pnlStatus);
- glPnlStatus.setHorizontalGroup(
- glPnlStatus.createParallelGroup(Alignment.LEADING).addGroup(glPnlStatus.createSequentialGroup()
- .addContainerGap().addComponent(lblStatus).addContainerGap(389, Short.MAX_VALUE)));
- glPnlStatus.setVerticalGroup(glPnlStatus.createParallelGroup(Alignment.TRAILING)
- .addGroup(glPnlStatus.createSequentialGroup().addGap(2)
- .addComponent(lblStatus, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addGap(0)));
- pnlStatus.setLayout(glPnlStatus);
-
- txfPath.setEditable(false);
- txfPath.setColumns(10);
-
- btnBrowsePath = new JButton(Bundle.getString("installer_dialog_btn_browse")); //$NON-NLS-1$
- btnBrowsePath.addActionListener(e -> {
- chooseKSPFolder();
- txfPath.setText(KrpcInstaller.getKspFolder());
+ .addComponent(
+ separator,
+ Alignment.TRAILING,
+ GroupLayout.DEFAULT_SIZE,
+ 414,
+ Short.MAX_VALUE)
+ .addGroup(
+ groupLayout
+ .createSequentialGroup()
+ .addComponent(btnDownloadInstall)
+ .addPreferredGap(
+ ComponentPlacement.RELATED, 184, Short.MAX_VALUE)
+ .addComponent(btnCancel)))
+ .addGap(10))
+ .addComponent(
+ pnlStatus, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 434, Short.MAX_VALUE));
+ groupLayout.setVerticalGroup(
+ groupLayout
+ .createParallelGroup(Alignment.LEADING)
+ .addGroup(
+ groupLayout
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(
+ lblInstallerInfo,
+ GroupLayout.PREFERRED_SIZE,
+ 60,
+ GroupLayout.PREFERRED_SIZE)
+ .addGap(2)
+ .addComponent(
+ separator, GroupLayout.PREFERRED_SIZE, 2, GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(ComponentPlacement.UNRELATED)
+ .addComponent(
+ pnlKspFolderPath,
+ GroupLayout.PREFERRED_SIZE,
+ 51,
+ GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(ComponentPlacement.UNRELATED)
+ .addGroup(
+ groupLayout
+ .createParallelGroup(Alignment.BASELINE)
+ .addComponent(btnDownloadInstall)
+ .addComponent(btnCancel))
+ .addPreferredGap(ComponentPlacement.RELATED, 60, Short.MAX_VALUE)
+ .addComponent(
+ pnlStatus, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)));
+
+ lblStatus = new JLabel();
+ GroupLayout glPnlStatus = new GroupLayout(pnlStatus);
+ glPnlStatus.setHorizontalGroup(
+ glPnlStatus
+ .createParallelGroup(Alignment.LEADING)
+ .addGroup(
+ glPnlStatus
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(lblStatus)
+ .addContainerGap(389, Short.MAX_VALUE)));
+ glPnlStatus.setVerticalGroup(
+ glPnlStatus
+ .createParallelGroup(Alignment.TRAILING)
+ .addGroup(
+ glPnlStatus
+ .createSequentialGroup()
+ .addGap(2)
+ .addComponent(
+ lblStatus,
+ GroupLayout.DEFAULT_SIZE,
+ GroupLayout.DEFAULT_SIZE,
+ Short.MAX_VALUE)
+ .addGap(0)));
+ pnlStatus.setLayout(glPnlStatus);
+
+ txfPath.setEditable(false);
+ txfPath.setColumns(10);
+
+ btnBrowsePath = new JButton(Bundle.getString("installer_dialog_btn_browse")); // $NON-NLS-1$
+ btnBrowsePath.addActionListener(
+ e -> {
+ chooseKSPFolder();
+ txfPath.setText(KrpcInstaller.getKspFolder());
});
- GroupLayout glPnlKspFolderPath = new GroupLayout(pnlKspFolderPath);
- glPnlKspFolderPath.setHorizontalGroup(
- glPnlKspFolderPath.createParallelGroup(Alignment.LEADING).addGroup(Alignment.TRAILING,
- glPnlKspFolderPath.createSequentialGroup().addContainerGap()
- .addComponent(txfPath, GroupLayout.DEFAULT_SIZE, 273, Short.MAX_VALUE)
- .addPreferredGap(ComponentPlacement.RELATED).addComponent(btnBrowsePath,
- GroupLayout.PREFERRED_SIZE, 103, GroupLayout.PREFERRED_SIZE)
- .addContainerGap()));
+ GroupLayout glPnlKspFolderPath = new GroupLayout(pnlKspFolderPath);
+ glPnlKspFolderPath.setHorizontalGroup(
glPnlKspFolderPath
- .setVerticalGroup(glPnlKspFolderPath.createParallelGroup(Alignment.LEADING)
- .addGroup(glPnlKspFolderPath.createSequentialGroup()
- .addGroup(glPnlKspFolderPath.createParallelGroup(Alignment.BASELINE)
- .addComponent(txfPath, GroupLayout.PREFERRED_SIZE, 23,
- GroupLayout.PREFERRED_SIZE)
- .addComponent(btnBrowsePath))
- .addContainerGap(24, Short.MAX_VALUE)));
- pnlKspFolderPath.setLayout(glPnlKspFolderPath);
- getContentPane().setLayout(groupLayout);
-
- setVisible(true);
- }
-
- public void chooseKSPFolder() {
- JFileChooser kspDir = new JFileChooser();
- kspDir.setDialogTitle("Escolha a pasta do KSP na Steam");
- kspDir.setMultiSelectionEnabled(false);
- kspDir.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
- int response = kspDir.showOpenDialog(this);
- if (response == JFileChooser.APPROVE_OPTION) {
- KrpcInstaller.setKspFolder(kspDir.getSelectedFile().getPath());
- btnDownloadInstall.setEnabled(true);
- setStatus("Pasta escolhida, pronto para instalar.");
- } else {
- KrpcInstaller.setKspFolder(null);
- btnDownloadInstall.setEnabled(false);
- setStatus("");
- }
+ .createParallelGroup(Alignment.LEADING)
+ .addGroup(
+ Alignment.TRAILING,
+ glPnlKspFolderPath
+ .createSequentialGroup()
+ .addContainerGap()
+ .addComponent(txfPath, GroupLayout.DEFAULT_SIZE, 273, Short.MAX_VALUE)
+ .addPreferredGap(ComponentPlacement.RELATED)
+ .addComponent(
+ btnBrowsePath, GroupLayout.PREFERRED_SIZE, 103, GroupLayout.PREFERRED_SIZE)
+ .addContainerGap()));
+ glPnlKspFolderPath.setVerticalGroup(
+ glPnlKspFolderPath
+ .createParallelGroup(Alignment.LEADING)
+ .addGroup(
+ glPnlKspFolderPath
+ .createSequentialGroup()
+ .addGroup(
+ glPnlKspFolderPath
+ .createParallelGroup(Alignment.BASELINE)
+ .addComponent(
+ txfPath, GroupLayout.PREFERRED_SIZE, 23, GroupLayout.PREFERRED_SIZE)
+ .addComponent(btnBrowsePath))
+ .addContainerGap(24, Short.MAX_VALUE)));
+ pnlKspFolderPath.setLayout(glPnlKspFolderPath);
+ getContentPane().setLayout(groupLayout);
+
+ setVisible(true);
+ }
+
+ public void chooseKSPFolder() {
+ JFileChooser kspDir = new JFileChooser();
+ kspDir.setDialogTitle("Escolha a pasta do KSP na Steam");
+ kspDir.setMultiSelectionEnabled(false);
+ kspDir.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ int response = kspDir.showOpenDialog(this);
+ if (response == JFileChooser.APPROVE_OPTION) {
+ KrpcInstaller.setKspFolder(kspDir.getSelectedFile().getPath());
+ btnDownloadInstall.setEnabled(true);
+ setStatus("Pasta escolhida, pronto para instalar.");
+ } else {
+ KrpcInstaller.setKspFolder(null);
+ btnDownloadInstall.setEnabled(false);
+ setStatus("");
}
+ }
- public static void setStatus(String status) {
- lblStatus.setText(status);
- }
+ public static void setStatus(String status) {
+ lblStatus.setText(status);
+ }
}
diff --git a/src/main/java/com/pesterenan/views/LandingJPanel.java b/src/main/java/com/pesterenan/views/LandingJPanel.java
index a547286..554e831 100644
--- a/src/main/java/com/pesterenan/views/LandingJPanel.java
+++ b/src/main/java/com/pesterenan/views/LandingJPanel.java
@@ -1,168 +1,201 @@
package com.pesterenan.views;
-import com.pesterenan.MechPeste;
+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;
+
+import com.pesterenan.model.VesselManager;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.Module;
-
-import javax.swing.*;
-import javax.swing.border.Border;
-import javax.swing.border.EtchedBorder;
-import javax.swing.border.TitledBorder;
-import java.awt.*;
+import java.awt.BorderLayout;
+import java.awt.Color;
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;
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.Border;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
public class LandingJPanel extends JPanel implements UIMethods {
- private static final long serialVersionUID = 1L;
- private JLabel lblHoverAltitude, lblTWRLimit;
- private JTextField txfHover, txfMaxTWR;
- private JButton btnHover, btnAutoLanding, btnBack;
- private JCheckBox chkHoverAfterLanding;
-
- public LandingJPanel() {
- initComponents();
- setupComponents();
- layoutComponents();
+ private static final long serialVersionUID = 1L;
+ private JLabel lblHoverAltitude, lblTWRLimit;
+ private JTextField txfHover, txfMaxTWR;
+ private JButton btnHover, btnAutoLanding, btnBack;
+ private JCheckBox chkHoverAfterLanding;
+ private VesselManager vesselManager;
+
+ private StatusDisplay statusDisplay;
+
+ public LandingJPanel(StatusDisplay statusDisplay) {
+ this.statusDisplay = statusDisplay;
+ initComponents();
+ setupComponents();
+ layoutComponents();
+ }
+
+ public void setVesselManager(VesselManager vesselManager) {
+ this.vesselManager = vesselManager;
+ }
+
+ @Override
+ public void initComponents() {
+ // Labels:
+ lblHoverAltitude = new JLabel(Bundle.getString("pnl_land_lbl_alt"));
+ lblTWRLimit = new JLabel(Bundle.getString("pnl_common_lbl_limit_twr"));
+
+ // Textfields:
+ txfHover = new JTextField("50");
+ txfMaxTWR = new JTextField("5");
+
+ // Buttons:
+ btnHover = new JButton(Bundle.getString("pnl_land_btn_hover"));
+ btnAutoLanding = new JButton(Bundle.getString("pnl_land_btn_land"));
+ btnBack = new JButton(Bundle.getString("pnl_land_btn_back"));
+
+ // Checkboxes:
+ chkHoverAfterLanding = new JCheckBox(Bundle.getString("pnl_land_hover_checkbox"));
+ }
+
+ @Override
+ public void setupComponents() {
+ // Main Panel setup:
+ setBorder(
+ new TitledBorder(
+ null,
+ Bundle.getString("pnl_land_border"),
+ TitledBorder.LEADING,
+ TitledBorder.TOP,
+ null,
+ null));
+
+ // Setting-up components:
+ txfHover.setPreferredSize(BTN_DIMENSION);
+ txfHover.setMaximumSize(BTN_DIMENSION);
+ txfHover.setHorizontalAlignment(JTextField.RIGHT);
+ txfMaxTWR.setPreferredSize(BTN_DIMENSION);
+ txfMaxTWR.setMaximumSize(BTN_DIMENSION);
+ txfMaxTWR.setHorizontalAlignment(JTextField.RIGHT);
+
+ btnAutoLanding.addActionListener(this::handleLandingAction);
+ btnAutoLanding.setActionCommand(Module.LANDING.get());
+ btnAutoLanding.setPreferredSize(BTN_DIMENSION);
+ btnAutoLanding.setMaximumSize(BTN_DIMENSION);
+ btnHover.addActionListener(this::handleLandingAction);
+ btnHover.setActionCommand(Module.HOVERING.get());
+ btnHover.setPreferredSize(BTN_DIMENSION);
+ btnHover.setMaximumSize(BTN_DIMENSION);
+ btnBack.addActionListener(MainGui::backToTelemetry);
+ btnBack.setPreferredSize(BTN_DIMENSION);
+ btnBack.setMaximumSize(BTN_DIMENSION);
+ }
+
+ @Override
+ public void layoutComponents() {
+ // Main Panel layout:
+ setPreferredSize(PNL_DIMENSION);
+ setSize(PNL_DIMENSION);
+ setLayout(new BorderLayout());
+
+ // Laying out components:
+ JPanel pnlHoverControls = new JPanel();
+ pnlHoverControls.setBorder(MARGIN_BORDER_10_PX_LR);
+ pnlHoverControls.setLayout(new BoxLayout(pnlHoverControls, BoxLayout.X_AXIS));
+ pnlHoverControls.add(lblHoverAltitude);
+ pnlHoverControls.add(Box.createHorizontalGlue());
+ pnlHoverControls.add(txfHover);
+
+ JPanel pnlTWRLimitControls = new JPanel();
+ pnlTWRLimitControls.setBorder(MARGIN_BORDER_10_PX_LR);
+ pnlTWRLimitControls.setLayout(new BoxLayout(pnlTWRLimitControls, BoxLayout.X_AXIS));
+ pnlTWRLimitControls.add(lblTWRLimit);
+ pnlTWRLimitControls.add(Box.createHorizontalGlue());
+ pnlTWRLimitControls.add(txfMaxTWR);
+
+ JPanel pnlLandingControls = new JPanel();
+ pnlLandingControls.setLayout(new BoxLayout(pnlLandingControls, BoxLayout.X_AXIS));
+ Border titledEtched =
+ new TitledBorder(
+ new EtchedBorder(
+ EtchedBorder.LOWERED, new Color(255, 255, 255), new Color(160, 160, 160)),
+ Bundle.getString("pnl_land_lbl_land"),
+ TitledBorder.LEADING,
+ TitledBorder.TOP,
+ null,
+ new Color(0, 0, 0));
+ Border combined = BorderFactory.createCompoundBorder(titledEtched, MARGIN_BORDER_10_PX_LR);
+ pnlLandingControls.setBorder(combined);
+ pnlLandingControls.add(btnAutoLanding);
+ pnlLandingControls.add(Box.createHorizontalGlue());
+ pnlLandingControls.add(btnHover);
+
+ JPanel pnlControls = new JPanel();
+ pnlControls.setLayout(new BoxLayout(pnlControls, BoxLayout.Y_AXIS));
+ pnlControls.add(MainGui.createMarginComponent(0, 6));
+ pnlControls.add(pnlHoverControls);
+ pnlControls.add(pnlTWRLimitControls);
+ pnlControls.add(pnlLandingControls);
+
+ JPanel pnlOptions = new JPanel();
+ pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS));
+ pnlOptions.setBorder(new TitledBorder(Bundle.getString("pnl_lift_chk_options")));
+ pnlOptions.add(chkHoverAfterLanding);
+ pnlOptions.add(Box.createHorizontalGlue());
+
+ JPanel pnlMain = new JPanel();
+ pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
+ pnlControls.setAlignmentY(TOP_ALIGNMENT);
+ pnlOptions.setAlignmentY(TOP_ALIGNMENT);
+ pnlMain.add(pnlControls);
+ pnlMain.add(pnlOptions);
+
+ JPanel pnlBackbtn = new JPanel();
+ pnlBackbtn.setLayout(new BoxLayout(pnlBackbtn, BoxLayout.X_AXIS));
+ pnlBackbtn.add(Box.createHorizontalGlue());
+ pnlBackbtn.add(btnBack);
+
+ add(pnlMain, BorderLayout.CENTER);
+ add(pnlBackbtn, BorderLayout.SOUTH);
+ }
+
+ private void handleLandingAction(ActionEvent e) {
+ if (vesselManager == null) {
+ statusDisplay.setStatusMessage("Conexão não estabelecida ao pousar.");
+ return;
}
-
- @Override
- public void initComponents() {
- // Labels:
- lblHoverAltitude = new JLabel(Bundle.getString("pnl_land_lbl_alt"));
- lblTWRLimit = new JLabel(Bundle.getString("pnl_common_lbl_limit_twr"));
-
- // Textfields:
- txfHover = new JTextField("50");
- txfMaxTWR = new JTextField("5");
-
- // Buttons:
- btnHover = new JButton(Bundle.getString("pnl_land_btn_hover"));
- btnAutoLanding = new JButton(Bundle.getString("pnl_land_btn_land"));
- btnBack = new JButton(Bundle.getString("pnl_land_btn_back"));
-
- // Checkboxes:
- chkHoverAfterLanding = new JCheckBox(Bundle.getString("pnl_land_hover_checkbox"));
+ try {
+ Map commands = new HashMap<>();
+ commands.put(Module.MODULO.get(), e.getActionCommand());
+ validateTextFields();
+ commands.put(Module.HOVER_ALTITUDE.get(), txfHover.getText());
+ commands.put(Module.MAX_TWR.get(), txfMaxTWR.getText());
+ commands.put(
+ Module.HOVER_AFTER_LANDING.get(), String.valueOf(chkHoverAfterLanding.isSelected()));
+ vesselManager.startModule(commands);
+ MainGui.backToTelemetry(e);
+ chkHoverAfterLanding.setSelected(false);
+ } catch (NumberFormatException nfe) {
+ statusDisplay.setStatusMessage(Bundle.getString("pnl_land_hover_alt_err"));
+ } catch (NullPointerException npe) {
+ statusDisplay.setStatusMessage(Bundle.getString("pnl_land_hover_alt"));
}
-
- @Override
- public void setupComponents() {
- // Main Panel setup:
- setBorder(new TitledBorder(null, Bundle.getString("pnl_land_border"), TitledBorder.LEADING, TitledBorder.TOP,
- null, null));
-
- // Setting-up components:
- txfHover.setPreferredSize(BTN_DIMENSION);
- txfHover.setMaximumSize(BTN_DIMENSION);
- txfHover.setHorizontalAlignment(JTextField.RIGHT);
- txfMaxTWR.setPreferredSize(BTN_DIMENSION);
- txfMaxTWR.setMaximumSize(BTN_DIMENSION);
- txfMaxTWR.setHorizontalAlignment(JTextField.RIGHT);
-
- btnAutoLanding.addActionListener(this::handleLandingAction);
- btnAutoLanding.setActionCommand(Module.LANDING.get());
- btnAutoLanding.setPreferredSize(BTN_DIMENSION);
- btnAutoLanding.setMaximumSize(BTN_DIMENSION);
- btnHover.addActionListener(this::handleLandingAction);
- btnHover.setActionCommand(Module.HOVERING.get());
- btnHover.setPreferredSize(BTN_DIMENSION);
- btnHover.setMaximumSize(BTN_DIMENSION);
- btnBack.addActionListener(MainGui::backToTelemetry);
- btnBack.setPreferredSize(BTN_DIMENSION);
- btnBack.setMaximumSize(BTN_DIMENSION);
- }
-
- @Override
- public void layoutComponents() {
- // Main Panel layout:
- setPreferredSize(PNL_DIMENSION);
- setSize(PNL_DIMENSION);
- setLayout(new BorderLayout());
-
- // Laying out components:
- JPanel pnlHoverControls = new JPanel();
- pnlHoverControls.setBorder(MARGIN_BORDER_10_PX_LR);
- pnlHoverControls.setLayout(new BoxLayout(pnlHoverControls, BoxLayout.X_AXIS));
- pnlHoverControls.add(lblHoverAltitude);
- pnlHoverControls.add(Box.createHorizontalGlue());
- pnlHoverControls.add(txfHover);
-
- JPanel pnlTWRLimitControls = new JPanel();
- pnlTWRLimitControls.setBorder(MARGIN_BORDER_10_PX_LR);
- pnlTWRLimitControls.setLayout(new BoxLayout(pnlTWRLimitControls, BoxLayout.X_AXIS));
- pnlTWRLimitControls.add(lblTWRLimit);
- pnlTWRLimitControls.add(Box.createHorizontalGlue());
- pnlTWRLimitControls.add(txfMaxTWR);
-
- JPanel pnlLandingControls = new JPanel();
- pnlLandingControls.setLayout(new BoxLayout(pnlLandingControls, BoxLayout.X_AXIS));
- Border titledEtched = new TitledBorder(
- new EtchedBorder(EtchedBorder.LOWERED, new Color(255, 255, 255), new Color(160, 160, 160)),
- Bundle.getString("pnl_land_lbl_land"), TitledBorder.LEADING, TitledBorder.TOP, null,
- new Color(0, 0, 0));
- Border combined = BorderFactory.createCompoundBorder(titledEtched, MARGIN_BORDER_10_PX_LR);
- pnlLandingControls.setBorder(combined);
- pnlLandingControls.add(btnAutoLanding);
- pnlLandingControls.add(Box.createHorizontalGlue());
- pnlLandingControls.add(btnHover);
-
- JPanel pnlControls = new JPanel();
- pnlControls.setLayout(new BoxLayout(pnlControls, BoxLayout.Y_AXIS));
- pnlControls.add(MainGui.createMarginComponent(0, 6));
- pnlControls.add(pnlHoverControls);
- pnlControls.add(pnlTWRLimitControls);
- pnlControls.add(pnlLandingControls);
-
- JPanel pnlOptions = new JPanel();
- pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS));
- pnlOptions.setBorder(new TitledBorder(Bundle.getString("pnl_lift_chk_options")));
- pnlOptions.add(chkHoverAfterLanding);
- pnlOptions.add(Box.createHorizontalGlue());
-
- JPanel pnlMain = new JPanel();
- pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
- pnlControls.setAlignmentY(TOP_ALIGNMENT);
- pnlOptions.setAlignmentY(TOP_ALIGNMENT);
- pnlMain.add(pnlControls);
- pnlMain.add(pnlOptions);
-
- JPanel pnlBackbtn = new JPanel();
- pnlBackbtn.setLayout(new BoxLayout(pnlBackbtn, BoxLayout.X_AXIS));
- pnlBackbtn.add(Box.createHorizontalGlue());
- pnlBackbtn.add(btnBack);
-
- add(pnlMain, BorderLayout.CENTER);
- add(pnlBackbtn, BorderLayout.SOUTH);
- }
-
- private void handleLandingAction(ActionEvent e) {
- try {
- Map commands = new HashMap<>();
- commands.put(Module.MODULO.get(), e.getActionCommand());
- validateTextFields();
- commands.put(Module.HOVER_ALTITUDE.get(), txfHover.getText());
- commands.put(Module.MAX_TWR.get(), txfMaxTWR.getText());
- commands.put(Module.HOVER_AFTER_LANDING.get(), String.valueOf(chkHoverAfterLanding.isSelected()));
- MechPeste.newInstance().startModule(commands);
- MainGui.backToTelemetry(e);
- chkHoverAfterLanding.setSelected(false);
- } catch (NumberFormatException nfe) {
- StatusJPanel.setStatusMessage(Bundle.getString("pnl_land_hover_alt_err"));
- } catch (NullPointerException npe) {
- StatusJPanel.setStatusMessage(Bundle.getString("pnl_land_hover_alt"));
- }
- }
-
- private void validateTextFields() throws NumberFormatException, NullPointerException {
- if (txfHover.getText().equals("") || txfHover.getText().equals("0") || txfMaxTWR.getText().equals("")
- || txfMaxTWR.getText().equals("0")) {
- throw new NullPointerException();
- }
- Float.parseFloat(txfHover.getText());
- Float.parseFloat(txfMaxTWR.getText());
+ }
+
+ private void validateTextFields() throws NumberFormatException, NullPointerException {
+ if (txfHover.getText().equals("")
+ || txfHover.getText().equals("0")
+ || txfMaxTWR.getText().equals("")
+ || txfMaxTWR.getText().equals("0")) {
+ throw new NullPointerException();
}
+ Float.parseFloat(txfHover.getText());
+ Float.parseFloat(txfMaxTWR.getText());
+ }
}
diff --git a/src/main/java/com/pesterenan/views/LiftoffJPanel.java b/src/main/java/com/pesterenan/views/LiftoffJPanel.java
index b7b0e10..220fdb9 100644
--- a/src/main/java/com/pesterenan/views/LiftoffJPanel.java
+++ b/src/main/java/com/pesterenan/views/LiftoffJPanel.java
@@ -1,214 +1,251 @@
package com.pesterenan.views;
-import com.pesterenan.MechPeste;
+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;
+
+import com.pesterenan.model.VesselManager;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.Module;
-
-import javax.swing.*;
-import javax.swing.border.TitledBorder;
-import java.awt.*;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
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;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.JTextField;
+import javax.swing.border.TitledBorder;
public class LiftoffJPanel extends JPanel implements UIMethods {
- private static final long serialVersionUID = 1L;
-
- private JLabel lblFinalApoapsis, lblHeading, lblRoll, lblCurveModel, lblLimitTWR;
- private JTextField txfFinalApoapsis, txfHeading, txfLimitTWR;
- private JButton btnLiftoff, btnBack;
- private JComboBox cbGravityCurveModel;
- private JSlider sldRoll;
- private JCheckBox chkOpenPanels, chkDecoupleStages;
-
- public LiftoffJPanel() {
- initComponents();
- setupComponents();
- layoutComponents();
- }
-
- @Override
- public void initComponents() {
- // Labels:
- lblFinalApoapsis = new JLabel(Bundle.getString("pnl_lift_lbl_final_apoapsis"));
- lblHeading = new JLabel(Bundle.getString("pnl_lift_lbl_direction"));
- lblRoll = new JLabel(Bundle.getString("pnl_lift_lbl_roll"));
- lblRoll.setToolTipText(Bundle.getString("pnl_lift_lbl_roll_tooltip"));
- lblCurveModel = new JLabel(Bundle.getString("pnl_lift_lbl_gravity_curve"));
- lblLimitTWR = new JLabel(Bundle.getString("pnl_common_lbl_limit_twr"));
-
- // Textfields:
- txfFinalApoapsis = new JTextField("80000");
- txfFinalApoapsis.setToolTipText(Bundle.getString("pnl_lift_txf_final_apo_tooltip"));
- txfHeading = new JTextField("90");
- txfLimitTWR = new JTextField("2.2");
-
- // Buttons:
- btnLiftoff = new JButton(Bundle.getString("pnl_lift_btn_liftoff"));
- btnBack = new JButton(Bundle.getString("pnl_lift_btn_back"));
-
- // Checkboxes:
- chkOpenPanels = new JCheckBox(Bundle.getString("pnl_lift_chk_open_panels"));
- chkOpenPanels.setToolTipText(Bundle.getString("pnl_lift_chk_open_panels_tooltip"));
- chkDecoupleStages = new JCheckBox(Bundle.getString("pnl_lift_chk_staging"));
- chkDecoupleStages.setToolTipText(Bundle.getString("pnl_lift_chk_staging_tooltip"));
-
- // Misc:
- cbGravityCurveModel = new JComboBox<>();
- cbGravityCurveModel.setToolTipText(Bundle.getString("pnl_lift_cb_gravity_curve_tooltip"));
-
- sldRoll = new JSlider();
+ private static final long serialVersionUID = 1L;
+
+ private JLabel lblFinalApoapsis, lblHeading, lblRoll, lblCurveModel, lblLimitTWR;
+ private JTextField txfFinalApoapsis, txfHeading, txfLimitTWR;
+ private JButton btnLiftoff, btnBack;
+ private JComboBox cbGravityCurveModel;
+ private JSlider sldRoll;
+ private JCheckBox chkOpenPanels, chkDecoupleStages;
+ private VesselManager vesselManager;
+
+ private StatusDisplay statusDisplay;
+
+ public LiftoffJPanel(StatusDisplay statusDisplay) {
+ this.statusDisplay = statusDisplay;
+ initComponents();
+ setupComponents();
+ layoutComponents();
+ }
+
+ public void setVesselManager(VesselManager vesselManager) {
+ this.vesselManager = vesselManager;
+ btnLiftoff.setEnabled(true);
+ }
+
+ @Override
+ public void initComponents() {
+ // Labels:
+ lblFinalApoapsis = new JLabel(Bundle.getString("pnl_lift_lbl_final_apoapsis"));
+ lblHeading = new JLabel(Bundle.getString("pnl_lift_lbl_direction"));
+ lblRoll = new JLabel(Bundle.getString("pnl_lift_lbl_roll"));
+ lblRoll.setToolTipText(Bundle.getString("pnl_lift_lbl_roll_tooltip"));
+ lblCurveModel = new JLabel(Bundle.getString("pnl_lift_lbl_gravity_curve"));
+ lblLimitTWR = new JLabel(Bundle.getString("pnl_common_lbl_limit_twr"));
+
+ // Textfields:
+ txfFinalApoapsis = new JTextField("80000");
+ txfFinalApoapsis.setToolTipText(Bundle.getString("pnl_lift_txf_final_apo_tooltip"));
+ txfHeading = new JTextField("90");
+ txfLimitTWR = new JTextField("2.2");
+
+ // Buttons:
+ btnLiftoff = new JButton(Bundle.getString("pnl_lift_btn_liftoff"));
+ btnLiftoff.setEnabled(false);
+ btnBack = new JButton(Bundle.getString("pnl_lift_btn_back"));
+
+ // Checkboxes:
+ chkOpenPanels = new JCheckBox(Bundle.getString("pnl_lift_chk_open_panels"));
+ chkOpenPanels.setToolTipText(Bundle.getString("pnl_lift_chk_open_panels_tooltip"));
+ chkDecoupleStages = new JCheckBox(Bundle.getString("pnl_lift_chk_staging"));
+ chkDecoupleStages.setToolTipText(Bundle.getString("pnl_lift_chk_staging_tooltip"));
+
+ // Misc:
+ cbGravityCurveModel = new JComboBox<>();
+ cbGravityCurveModel.setToolTipText(Bundle.getString("pnl_lift_cb_gravity_curve_tooltip"));
+
+ sldRoll = new JSlider();
+ }
+
+ @Override
+ public void setupComponents() {
+ // Main Panel setup:
+ setBorder(
+ new TitledBorder(
+ null,
+ Bundle.getString("pnl_lift_pnl_title"),
+ TitledBorder.LEADING,
+ TitledBorder.TOP,
+ null,
+ null));
+
+ // Setting-up components:
+ lblFinalApoapsis.setLabelFor(txfFinalApoapsis);
+ txfFinalApoapsis.setMaximumSize(BTN_DIMENSION);
+ txfFinalApoapsis.setPreferredSize(BTN_DIMENSION);
+ txfFinalApoapsis.setHorizontalAlignment(JTextField.RIGHT);
+ lblHeading.setLabelFor(txfHeading);
+ txfHeading.setMaximumSize(BTN_DIMENSION);
+ txfHeading.setPreferredSize(BTN_DIMENSION);
+ txfHeading.setHorizontalAlignment(JTextField.RIGHT);
+ lblLimitTWR.setLabelFor(txfLimitTWR);
+ txfLimitTWR.setMaximumSize(BTN_DIMENSION);
+ txfLimitTWR.setPreferredSize(BTN_DIMENSION);
+ txfLimitTWR.setHorizontalAlignment(JTextField.RIGHT);
+
+ cbGravityCurveModel.setModel(
+ new DefaultComboBoxModel<>(
+ new String[] {
+ Module.SINUSOIDAL.get(),
+ Module.QUADRATIC.get(),
+ Module.CUBIC.get(),
+ Module.CIRCULAR.get(),
+ Module.EXPONENCIAL.get()
+ }));
+ cbGravityCurveModel.setSelectedIndex(3);
+ cbGravityCurveModel.setPreferredSize(BTN_DIMENSION);
+ cbGravityCurveModel.setMaximumSize(BTN_DIMENSION);
+
+ sldRoll.setPaintLabels(true);
+ sldRoll.setMajorTickSpacing(90);
+ sldRoll.setMaximum(270);
+ sldRoll.setSnapToTicks(true);
+ sldRoll.setValue(90);
+ sldRoll.setPreferredSize(new Dimension(110, 40));
+ sldRoll.setMaximumSize(new Dimension(110, 40));
+
+ chkDecoupleStages.setSelected(true);
+
+ btnLiftoff.addActionListener(this::handleLiftoff);
+ btnLiftoff.setPreferredSize(BTN_DIMENSION);
+ btnLiftoff.setMaximumSize(BTN_DIMENSION);
+ btnBack.addActionListener(MainGui::backToTelemetry);
+ btnBack.setPreferredSize(BTN_DIMENSION);
+ btnBack.setMaximumSize(BTN_DIMENSION);
+ }
+
+ @Override
+ public void layoutComponents() {
+ // Main Panel layout:
+ setPreferredSize(PNL_DIMENSION);
+ setSize(PNL_DIMENSION);
+ setLayout(new BorderLayout());
+
+ // Laying out components:
+ JPanel pnlFinalApoapsis = new JPanel();
+ pnlFinalApoapsis.setLayout(new BoxLayout(pnlFinalApoapsis, BoxLayout.X_AXIS));
+ pnlFinalApoapsis.setBorder(MARGIN_BORDER_10_PX_LR);
+ pnlFinalApoapsis.add(lblFinalApoapsis);
+ pnlFinalApoapsis.add(Box.createHorizontalGlue());
+ pnlFinalApoapsis.add(txfFinalApoapsis);
+
+ JPanel pnlHeading = new JPanel();
+ pnlHeading.setLayout(new BoxLayout(pnlHeading, BoxLayout.X_AXIS));
+ pnlHeading.setBorder(MARGIN_BORDER_10_PX_LR);
+ pnlHeading.add(lblHeading);
+ pnlHeading.add(Box.createHorizontalGlue());
+ pnlHeading.add(txfHeading);
+
+ JPanel pnlRoll = new JPanel();
+ pnlRoll.setLayout(new BoxLayout(pnlRoll, BoxLayout.X_AXIS));
+ pnlRoll.setBorder(MARGIN_BORDER_10_PX_LR);
+ pnlRoll.add(lblRoll);
+ pnlRoll.add(Box.createHorizontalGlue());
+ pnlRoll.add(sldRoll);
+
+ JPanel pnlLimitTWR = new JPanel();
+ pnlLimitTWR.setLayout(new BoxLayout(pnlLimitTWR, BoxLayout.X_AXIS));
+ pnlLimitTWR.setBorder(MARGIN_BORDER_10_PX_LR);
+ pnlLimitTWR.add(lblLimitTWR);
+ pnlLimitTWR.add(Box.createHorizontalGlue());
+ pnlLimitTWR.add(txfLimitTWR);
+
+ JPanel pnlCurveModel = new JPanel();
+ pnlCurveModel.setLayout(new BoxLayout(pnlCurveModel, BoxLayout.X_AXIS));
+ pnlCurveModel.setBorder(MARGIN_BORDER_10_PX_LR);
+ pnlCurveModel.add(lblCurveModel);
+ pnlCurveModel.add(Box.createHorizontalGlue());
+ pnlCurveModel.add(cbGravityCurveModel);
+
+ JPanel pnlButtons = new JPanel();
+ pnlButtons.setLayout(new BoxLayout(pnlButtons, BoxLayout.X_AXIS));
+ pnlButtons.add(btnLiftoff);
+ pnlButtons.add(Box.createHorizontalGlue());
+ pnlButtons.add(btnBack);
+
+ JPanel pnlSetup = new JPanel();
+ pnlSetup.setLayout(new BoxLayout(pnlSetup, BoxLayout.Y_AXIS));
+ pnlSetup.add(MainGui.createMarginComponent(0, 6));
+ pnlSetup.add(pnlFinalApoapsis);
+ pnlSetup.add(pnlHeading);
+ pnlSetup.add(pnlRoll);
+ pnlSetup.add(pnlLimitTWR);
+ pnlSetup.add(pnlCurveModel);
+
+ JPanel pnlOptions = new JPanel();
+ pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS));
+ pnlOptions.setBorder(new TitledBorder(Bundle.getString("pnl_lift_chk_options")));
+ pnlOptions.add(chkDecoupleStages);
+ pnlOptions.add(chkOpenPanels);
+
+ JPanel pnlMain = new JPanel();
+ pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
+ pnlMain.add(pnlSetup);
+ pnlSetup.setAlignmentY(Component.TOP_ALIGNMENT);
+ pnlMain.add(pnlOptions);
+ pnlOptions.setAlignmentY(Component.TOP_ALIGNMENT);
+
+ add(pnlMain, BorderLayout.CENTER);
+ add(pnlButtons, BorderLayout.SOUTH);
+ }
+
+ private boolean validateTextFields() {
+ try {
+ Float.parseFloat(txfFinalApoapsis.getText());
+ Float.parseFloat(txfHeading.getText());
+ Float.parseFloat(txfLimitTWR.getText());
+ } catch (NumberFormatException e) {
+ statusDisplay.setStatusMessage(Bundle.getString("pnl_lift_stat_only_numbers"));
+ return false;
}
+ return true;
+ }
- @Override
- public void setupComponents() {
- // Main Panel setup:
- setBorder(new TitledBorder(null, Bundle.getString("pnl_lift_pnl_title"), TitledBorder.LEADING, TitledBorder.TOP,
- null, null));
-
- // Setting-up components:
- lblFinalApoapsis.setLabelFor(txfFinalApoapsis);
- txfFinalApoapsis.setMaximumSize(BTN_DIMENSION);
- txfFinalApoapsis.setPreferredSize(BTN_DIMENSION);
- txfFinalApoapsis.setHorizontalAlignment(JTextField.RIGHT);
- lblHeading.setLabelFor(txfHeading);
- txfHeading.setMaximumSize(BTN_DIMENSION);
- txfHeading.setPreferredSize(BTN_DIMENSION);
- txfHeading.setHorizontalAlignment(JTextField.RIGHT);
- lblLimitTWR.setLabelFor(txfLimitTWR);
- txfLimitTWR.setMaximumSize(BTN_DIMENSION);
- txfLimitTWR.setPreferredSize(BTN_DIMENSION);
- txfLimitTWR.setHorizontalAlignment(JTextField.RIGHT);
-
- cbGravityCurveModel.setModel(new DefaultComboBoxModel<>(new String[]{Module.SINUSOIDAL.get(),
- Module.QUADRATIC.get(), Module.CUBIC.get(), Module.CIRCULAR.get(), Module.EXPONENCIAL.get()}));
- cbGravityCurveModel.setSelectedIndex(3);
- cbGravityCurveModel.setPreferredSize(BTN_DIMENSION);
- cbGravityCurveModel.setMaximumSize(BTN_DIMENSION);
-
- sldRoll.setPaintLabels(true);
- sldRoll.setMajorTickSpacing(90);
- sldRoll.setMaximum(270);
- sldRoll.setSnapToTicks(true);
- sldRoll.setValue(90);
- sldRoll.setPreferredSize(new Dimension(110, 40));
- sldRoll.setMaximumSize(new Dimension(110, 40));
-
- chkDecoupleStages.setSelected(true);
-
- btnLiftoff.addActionListener(this::handleLiftoff);
- btnLiftoff.setPreferredSize(BTN_DIMENSION);
- btnLiftoff.setMaximumSize(BTN_DIMENSION);
- btnBack.addActionListener(MainGui::backToTelemetry);
- btnBack.setPreferredSize(BTN_DIMENSION);
- btnBack.setMaximumSize(BTN_DIMENSION);
+ private void handleLiftoff(ActionEvent e) {
+ if (vesselManager == null) {
+ statusDisplay.setStatusMessage("Conexão não estabelecida.");
+ return;
}
-
- @Override
- public void layoutComponents() {
- // Main Panel layout:
- setPreferredSize(PNL_DIMENSION);
- setSize(PNL_DIMENSION);
- setLayout(new BorderLayout());
-
- // Laying out components:
- JPanel pnlFinalApoapsis = new JPanel();
- pnlFinalApoapsis.setLayout(new BoxLayout(pnlFinalApoapsis, BoxLayout.X_AXIS));
- pnlFinalApoapsis.setBorder(MARGIN_BORDER_10_PX_LR);
- pnlFinalApoapsis.add(lblFinalApoapsis);
- pnlFinalApoapsis.add(Box.createHorizontalGlue());
- pnlFinalApoapsis.add(txfFinalApoapsis);
-
- JPanel pnlHeading = new JPanel();
- pnlHeading.setLayout(new BoxLayout(pnlHeading, BoxLayout.X_AXIS));
- pnlHeading.setBorder(MARGIN_BORDER_10_PX_LR);
- pnlHeading.add(lblHeading);
- pnlHeading.add(Box.createHorizontalGlue());
- pnlHeading.add(txfHeading);
-
- JPanel pnlRoll = new JPanel();
- pnlRoll.setLayout(new BoxLayout(pnlRoll, BoxLayout.X_AXIS));
- pnlRoll.setBorder(MARGIN_BORDER_10_PX_LR);
- pnlRoll.add(lblRoll);
- pnlRoll.add(Box.createHorizontalGlue());
- pnlRoll.add(sldRoll);
-
- JPanel pnlLimitTWR = new JPanel();
- pnlLimitTWR.setLayout(new BoxLayout(pnlLimitTWR, BoxLayout.X_AXIS));
- pnlLimitTWR.setBorder(MARGIN_BORDER_10_PX_LR);
- pnlLimitTWR.add(lblLimitTWR);
- pnlLimitTWR.add(Box.createHorizontalGlue());
- pnlLimitTWR.add(txfLimitTWR);
-
- JPanel pnlCurveModel = new JPanel();
- pnlCurveModel.setLayout(new BoxLayout(pnlCurveModel, BoxLayout.X_AXIS));
- pnlCurveModel.setBorder(MARGIN_BORDER_10_PX_LR);
- pnlCurveModel.add(lblCurveModel);
- pnlCurveModel.add(Box.createHorizontalGlue());
- pnlCurveModel.add(cbGravityCurveModel);
-
- JPanel pnlButtons = new JPanel();
- pnlButtons.setLayout(new BoxLayout(pnlButtons, BoxLayout.X_AXIS));
- pnlButtons.add(btnLiftoff);
- pnlButtons.add(Box.createHorizontalGlue());
- pnlButtons.add(btnBack);
-
- JPanel pnlSetup = new JPanel();
- pnlSetup.setLayout(new BoxLayout(pnlSetup, BoxLayout.Y_AXIS));
- pnlSetup.add(MainGui.createMarginComponent(0, 6));
- pnlSetup.add(pnlFinalApoapsis);
- pnlSetup.add(pnlHeading);
- pnlSetup.add(pnlRoll);
- pnlSetup.add(pnlLimitTWR);
- pnlSetup.add(pnlCurveModel);
-
- JPanel pnlOptions = new JPanel();
- pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS));
- pnlOptions.setBorder(new TitledBorder(Bundle.getString("pnl_lift_chk_options")));
- pnlOptions.add(chkDecoupleStages);
- pnlOptions.add(chkOpenPanels);
-
- JPanel pnlMain = new JPanel();
- pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
- pnlMain.add(pnlSetup);
- pnlSetup.setAlignmentY(Component.TOP_ALIGNMENT);
- pnlMain.add(pnlOptions);
- pnlOptions.setAlignmentY(Component.TOP_ALIGNMENT);
-
- add(pnlMain, BorderLayout.CENTER);
- add(pnlButtons, BorderLayout.SOUTH);
- }
-
- private boolean validateTextFields() {
- try {
- Float.parseFloat(txfFinalApoapsis.getText());
- Float.parseFloat(txfHeading.getText());
- Float.parseFloat(txfLimitTWR.getText());
- } catch (NumberFormatException e) {
- StatusJPanel.setStatusMessage(Bundle.getString("pnl_lift_stat_only_numbers"));
- return false;
- }
- return true;
- }
-
- private void handleLiftoff(ActionEvent e) {
- if (validateTextFields()) {
- Map commands = new HashMap<>();
- commands.put(Module.MODULO.get(), Module.LIFTOFF.get());
- commands.put(Module.APOAPSIS.get(), txfFinalApoapsis.getText());
- commands.put(Module.DIRECTION.get(), txfHeading.getText());
- commands.put(Module.MAX_TWR.get(), txfLimitTWR.getText());
- commands.put(Module.ROLL.get(), String.valueOf(sldRoll.getValue()));
- commands.put(Module.INCLINATION.get(), cbGravityCurveModel.getSelectedItem().toString());
- commands.put(Module.STAGE.get(), String.valueOf(chkDecoupleStages.isSelected()));
- commands.put(Module.OPEN_PANELS.get(), String.valueOf(chkOpenPanels.isSelected()));
- MechPeste.newInstance().startModule(commands);
- MainGui.backToTelemetry(e);
- }
+ if (validateTextFields()) {
+ Map commands = new HashMap<>();
+ commands.put(Module.MODULO.get(), Module.LIFTOFF.get());
+ commands.put(Module.APOAPSIS.get(), txfFinalApoapsis.getText());
+ commands.put(Module.DIRECTION.get(), txfHeading.getText());
+ commands.put(Module.MAX_TWR.get(), txfLimitTWR.getText());
+ commands.put(Module.ROLL.get(), String.valueOf(sldRoll.getValue()));
+ commands.put(Module.INCLINATION.get(), cbGravityCurveModel.getSelectedItem().toString());
+ commands.put(Module.STAGE.get(), String.valueOf(chkDecoupleStages.isSelected()));
+ commands.put(Module.OPEN_PANELS.get(), String.valueOf(chkOpenPanels.isSelected()));
+ vesselManager.startModule(commands);
+ MainGui.backToTelemetry(e);
}
+ }
}
diff --git a/src/main/java/com/pesterenan/views/MainGui.java b/src/main/java/com/pesterenan/views/MainGui.java
index fa79424..e9ce014 100644
--- a/src/main/java/com/pesterenan/views/MainGui.java
+++ b/src/main/java/com/pesterenan/views/MainGui.java
@@ -1,195 +1,258 @@
package com.pesterenan.views;
+import com.pesterenan.model.VesselManager;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.Module;
-
-import javax.swing.*;
-import javax.swing.border.EmptyBorder;
-
-import java.awt.*;
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import javax.swing.Box;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JSeparator;
+import javax.swing.JTabbedPane;
+import javax.swing.UIManager;
+import javax.swing.border.EmptyBorder;
public class MainGui extends JFrame implements ActionListener, UIMethods {
- private static final long serialVersionUID = 1L;
-
- private final Dimension APP_DIMENSION = new Dimension(480, 300);
- public static final Dimension PNL_DIMENSION = new Dimension(464, 216);
- public static final Dimension BTN_DIMENSION = new Dimension(110, 25);
- public static final EmptyBorder MARGIN_BORDER_10_PX_LR = new EmptyBorder(0, 10, 0, 10);
- private static MainGui mainGui = null;
- private static StatusJPanel pnlStatus;
- private static FunctionsAndTelemetryJPanel pnlFunctionsAndTelemetry;
- private final JPanel ctpMainGui = new JPanel();
- private final static JPanel cardJPanels = new JPanel();
- private JMenuBar menuBar;
- private JMenu mnFile, mnOptions, mnHelp;
- private JMenuItem mntmInstallKrpc, mntmExit, mntmChangeVessels, mntmAbout;
-
- private final static CardLayout cardLayout = new CardLayout(0, 0);
- private LiftoffJPanel pnlLiftoff;
- private LandingJPanel pnlLanding;
- private CreateManeuverJPanel pnlCreateManeuvers;
- private RunManeuverJPanel pnlRunManeuvers;
- private RoverJPanel pnlRover;
- private DockingJPanel pnlDocking;
-
- private MainGui() {
- initComponents();
- setupComponents();
- layoutComponents();
- }
+ private static final long serialVersionUID = 1L;
- public static MainGui newInstance() {
- if (mainGui == null) {
- mainGui = new MainGui();
- }
- return mainGui;
- }
+ public static final Dimension PNL_DIMENSION = new Dimension(464, 216);
+ public static final Dimension BTN_DIMENSION = new Dimension(110, 25);
+ public static final EmptyBorder MARGIN_BORDER_10_PX_LR = new EmptyBorder(0, 10, 0, 10);
+ private static MainGui instance = null;
- @Override
- public void initComponents() {
- try {
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- } catch (Exception ignored) {
- }
-
- // Menu bar
- menuBar = new JMenuBar();
-
- // Menus
- mnFile = new JMenu(Bundle.getString("main_mn_file"));
- mnOptions = new JMenu(Bundle.getString("main_mn_options"));
- mnHelp = new JMenu(Bundle.getString("main_mn_help"));
-
- // Menu Items
- mntmInstallKrpc = new JMenuItem(Bundle.getString("main_mntm_install_krpc"));
- mntmChangeVessels = new JMenuItem(Bundle.getString("main_mntm_change_vessels"));
- mntmExit = new JMenuItem(Bundle.getString("main_mntm_exit"));
- mntmAbout = new JMenuItem(Bundle.getString("main_mntm_about"));
-
- // Panels
- pnlFunctionsAndTelemetry = new FunctionsAndTelemetryJPanel();
- pnlLiftoff = new LiftoffJPanel();
- pnlLanding = new LandingJPanel();
- pnlCreateManeuvers = new CreateManeuverJPanel();
- pnlRunManeuvers = new RunManeuverJPanel();
- pnlRover = new RoverJPanel();
- pnlDocking = new DockingJPanel();
- pnlStatus = new StatusJPanel();
- }
+ private static final JPanel cardJPanels = new JPanel();
- @Override
- public void setupComponents() {
- // Main Panel setup:
- setAlwaysOnTop(true);
- setTitle("MechPeste - Pesterenan");
- setJMenuBar(menuBar);
- setResizable(false);
- setLocation(100, 100);
- setContentPane(ctpMainGui);
- setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
-
- // Setting-up components:
- mntmAbout.addActionListener(this);
- mntmChangeVessels.addActionListener(this);
- mntmExit.addActionListener(this);
- mntmInstallKrpc.addActionListener(this);
-
- cardJPanels.setPreferredSize(PNL_DIMENSION);
- cardJPanels.setSize(PNL_DIMENSION);
- }
+ private static final CardLayout cardLayout = new CardLayout(0, 0);
- @Override
- public void layoutComponents() {
- // Main Panel layout:
- setPreferredSize(APP_DIMENSION);
- setSize(APP_DIMENSION);
- setVisible(true);
-
- // Laying out components:
- ctpMainGui.setLayout(new BorderLayout());
- ctpMainGui.add(cardJPanels, BorderLayout.CENTER);
- ctpMainGui.add(pnlStatus, BorderLayout.SOUTH);
-
- mnFile.add(mntmInstallKrpc);
- mnFile.add(new JSeparator());
- mnFile.add(mntmExit);
- mnOptions.add(mntmChangeVessels);
- mnHelp.add(mntmAbout);
- menuBar.add(mnFile);
- menuBar.add(mnOptions);
- menuBar.add(mnHelp);
-
- JTabbedPane pnlManeuverJTabbedPane = new JTabbedPane();
- pnlManeuverJTabbedPane.addTab("Criar Manobras", pnlCreateManeuvers);
- pnlManeuverJTabbedPane.addTab("Executar Manobras", pnlRunManeuvers);
-
- cardJPanels.setLayout(cardLayout);
- cardJPanels.add(pnlFunctionsAndTelemetry, Module.TELEMETRY.get());
- cardJPanels.add(pnlLiftoff, Module.LIFTOFF.get());
- cardJPanels.add(pnlLanding, Module.LANDING.get());
- cardJPanels.add(pnlManeuverJTabbedPane, Module.MANEUVER.get());
- cardJPanels.add(pnlRover, Module.ROVER.get());
- cardJPanels.add(pnlDocking, Module.DOCKING.get());
- }
+ public static MainGui getInstance() {
+ return instance;
+ }
- public void actionPerformed(ActionEvent e) {
- if (e.getSource() == mntmAbout) {
- handleMntmAboutActionPerformed(e);
- }
- if (e.getSource() == mntmInstallKrpc) {
- handleMntmInstallKrpcActionPerformed(e);
- }
- if (e.getSource() == mntmExit) {
- handleMntmExitActionPerformed(e);
- }
- if (e.getSource() == mntmChangeVessels) {
- handleMntmMultiControlActionPerformed(e);
- }
+ public static MainGui newInstance() {
+ if (instance == null) {
+ instance = new MainGui();
}
-
- private void handleMntmMultiControlActionPerformed(ActionEvent e) {
- new ChangeVesselDialog();
+ return instance;
+ }
+
+ public static Rectangle centerDialogOnScreen() {
+ Dimension SCREEN_DIMENSIONS = Toolkit.getDefaultToolkit().getScreenSize();
+ Dimension DIALOG_DIMENSIONS = new Dimension(400, 240);
+ int w = DIALOG_DIMENSIONS.width;
+ int h = DIALOG_DIMENSIONS.height;
+ int x = (SCREEN_DIMENSIONS.width - w) / 2;
+ int y = (SCREEN_DIMENSIONS.height - h) / 2;
+ return new Rectangle(x, y, w, h);
+ }
+
+ public static JPanel getCardJPanels() {
+ return cardJPanels;
+ }
+
+ public static void changeToPage(ActionEvent e) {
+ cardLayout.show(cardJPanels, e.getActionCommand());
+ }
+
+ public static void backToTelemetry(ActionEvent e) {
+ cardLayout.show(cardJPanels, Module.TELEMETRY.get());
+ }
+
+ public static Component createMarginComponent(int width, int height) {
+ Component marginComp = Box.createRigidArea(new Dimension(width, height));
+ return marginComp;
+ }
+
+ private FunctionsAndTelemetryJPanel pnlFunctionsAndTelemetry;
+
+ public FunctionsAndTelemetryJPanel getTelemetryPanel() {
+ return pnlFunctionsAndTelemetry;
+ }
+
+ private StatusJPanel pnlStatus;
+
+ private final Dimension APP_DIMENSION = new Dimension(480, 300);
+
+ private final JPanel ctpMainGui = new JPanel();
+
+ private JMenuBar menuBar;
+ private JMenu mnFile, mnOptions, mnHelp;
+ private JMenuItem mntmInstallKrpc, mntmExit, mntmChangeVessels, mntmAbout;
+ private LiftoffJPanel pnlLiftoff;
+ private LandingJPanel pnlLanding;
+
+ private CreateManeuverJPanel pnlCreateManeuvers;
+
+ private RunManeuverJPanel pnlRunManeuvers;
+
+ private RoverJPanel pnlRover;
+
+ private DockingJPanel pnlDocking;
+
+ private VesselManager vesselManager;
+
+ private MainGui() {
+ initComponents();
+ setupComponents();
+ layoutComponents();
+ }
+
+ public FunctionsAndTelemetryJPanel getFunctionsAndTelemetryPanel() {
+ return pnlFunctionsAndTelemetry;
+ }
+
+ public StatusJPanel getStatusPanel() {
+ return pnlStatus;
+ }
+
+ public LiftoffJPanel getLiftoffPanel() {
+ return pnlLiftoff;
+ }
+
+ public LandingJPanel getLandingPanel() {
+ return pnlLanding;
+ }
+
+ public CreateManeuverJPanel getCreateManeuverPanel() {
+ return pnlCreateManeuvers;
+ }
+
+ public void setVesselManager(VesselManager vesselManager) {
+ this.vesselManager = vesselManager;
+ pnlFunctionsAndTelemetry.setVesselManager(vesselManager);
+ pnlDocking.setVesselManager(vesselManager);
+ pnlRover.setVesselManager(vesselManager);
+ pnlLiftoff.setVesselManager(vesselManager);
+ pnlLanding.setVesselManager(vesselManager);
+ pnlCreateManeuvers.setVesselManager(vesselManager);
+ pnlRunManeuvers.setVesselManager(vesselManager);
+ }
+
+ @Override
+ public void initComponents() {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception ignored) {
}
- protected void handleMntmInstallKrpcActionPerformed(ActionEvent e) {
- new InstallKrpcDialog();
+ // Menu bar
+ menuBar = new JMenuBar();
+
+ // Menus
+ mnFile = new JMenu(Bundle.getString("main_mn_file"));
+ mnOptions = new JMenu(Bundle.getString("main_mn_options"));
+ mnHelp = new JMenu(Bundle.getString("main_mn_help"));
+
+ // Menu Items
+ mntmInstallKrpc = new JMenuItem(Bundle.getString("main_mntm_install_krpc"));
+ mntmChangeVessels = new JMenuItem(Bundle.getString("main_mntm_change_vessels"));
+ mntmExit = new JMenuItem(Bundle.getString("main_mntm_exit"));
+ mntmAbout = new JMenuItem(Bundle.getString("main_mntm_about"));
+
+ // Panels
+ pnlStatus = new StatusJPanel();
+ pnlFunctionsAndTelemetry = new FunctionsAndTelemetryJPanel(getStatusPanel());
+ pnlLiftoff = new LiftoffJPanel(getStatusPanel());
+ pnlLanding = new LandingJPanel(getStatusPanel());
+ pnlCreateManeuvers = new CreateManeuverJPanel(getStatusPanel());
+ pnlRunManeuvers = new RunManeuverJPanel(getStatusPanel());
+ pnlRover = new RoverJPanel(getStatusPanel());
+ pnlDocking = new DockingJPanel(getStatusPanel());
+ }
+
+ @Override
+ public void setupComponents() {
+ // Main Panel setup:
+ setAlwaysOnTop(true);
+ setTitle("MechPeste - Pesterenan");
+ setJMenuBar(menuBar);
+ setResizable(false);
+ setLocation(50, 50);
+ setContentPane(ctpMainGui);
+ setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ // Setting-up components:
+ mntmAbout.addActionListener(this);
+ mntmChangeVessels.addActionListener(this);
+ mntmExit.addActionListener(this);
+ mntmInstallKrpc.addActionListener(this);
+
+ cardJPanels.setPreferredSize(PNL_DIMENSION);
+ cardJPanels.setSize(PNL_DIMENSION);
+ }
+
+ @Override
+ public void layoutComponents() {
+ // Main Panel layout:
+ setPreferredSize(APP_DIMENSION);
+ setSize(APP_DIMENSION);
+ setVisible(true);
+
+ // Laying out components:
+ ctpMainGui.setLayout(new BorderLayout());
+ ctpMainGui.add(cardJPanels, BorderLayout.CENTER);
+ ctpMainGui.add(pnlStatus, BorderLayout.SOUTH);
+
+ mnFile.add(mntmInstallKrpc);
+ mnFile.add(new JSeparator());
+ mnFile.add(mntmExit);
+ mnOptions.add(mntmChangeVessels);
+ mnHelp.add(mntmAbout);
+ menuBar.add(mnFile);
+ menuBar.add(mnOptions);
+ menuBar.add(mnHelp);
+
+ JTabbedPane pnlManeuverJTabbedPane = new JTabbedPane();
+ pnlManeuverJTabbedPane.addTab("Criar Manobras", pnlCreateManeuvers);
+ pnlManeuverJTabbedPane.addTab("Executar Manobras", pnlRunManeuvers);
+
+ cardJPanels.setLayout(cardLayout);
+ cardJPanels.add(pnlFunctionsAndTelemetry, Module.TELEMETRY.get());
+ cardJPanels.add(pnlLiftoff, Module.LIFTOFF.get());
+ cardJPanels.add(pnlLanding, Module.LANDING.get());
+ cardJPanels.add(pnlManeuverJTabbedPane, Module.MANEUVER.get());
+ cardJPanels.add(pnlRover, Module.ROVER.get());
+ cardJPanels.add(pnlDocking, Module.DOCKING.get());
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == mntmAbout) {
+ handleMntmAboutActionPerformed(e);
}
-
- protected void handleMntmExitActionPerformed(ActionEvent e) {
- System.exit(0);
+ if (e.getSource() == mntmInstallKrpc) {
+ handleMntmInstallKrpcActionPerformed(e);
}
-
- public static Rectangle centerDialogOnScreen() {
- Dimension SCREEN_DIMENSIONS = Toolkit.getDefaultToolkit().getScreenSize();
- Dimension DIALOG_DIMENSIONS = new Dimension(400, 240);
- int w = DIALOG_DIMENSIONS.width;
- int h = DIALOG_DIMENSIONS.height;
- int x = (SCREEN_DIMENSIONS.width - w) / 2;
- int y = (SCREEN_DIMENSIONS.height - h) / 2;
- return new Rectangle(x, y, w, h);
+ if (e.getSource() == mntmExit) {
+ handleMntmExitActionPerformed(e);
}
-
- public static JPanel getCardJPanels() {
- return cardJPanels;
+ if (e.getSource() == mntmChangeVessels) {
+ handleMntmMultiControlActionPerformed(e);
}
+ }
- public static void changeToPage(ActionEvent e) {
- cardLayout.show(cardJPanels, e.getActionCommand());
- }
+ protected void handleMntmInstallKrpcActionPerformed(ActionEvent e) {
+ new InstallKrpcDialog();
+ }
- public static void backToTelemetry(ActionEvent e) {
- cardLayout.show(cardJPanels, Module.TELEMETRY.get());
- }
+ protected void handleMntmExitActionPerformed(ActionEvent e) {
+ System.exit(0);
+ }
- protected void handleMntmAboutActionPerformed(ActionEvent e) {
- new AboutJFrame();
- }
+ protected void handleMntmAboutActionPerformed(ActionEvent e) {
+ new AboutJFrame();
+ }
- public static Component createMarginComponent(int width, int height) {
- Component marginComp = Box.createRigidArea(new Dimension(width, height));
- return marginComp;
- }
+ private void handleMntmMultiControlActionPerformed(ActionEvent e) {
+ new ChangeVesselDialog(vesselManager);
+ }
}
diff --git a/src/main/java/com/pesterenan/views/RoverJPanel.java b/src/main/java/com/pesterenan/views/RoverJPanel.java
index 008a16d..5224840 100644
--- a/src/main/java/com/pesterenan/views/RoverJPanel.java
+++ b/src/main/java/com/pesterenan/views/RoverJPanel.java
@@ -1,172 +1,189 @@
package com.pesterenan.views;
-import com.pesterenan.MechPeste;
+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;
+
+import com.pesterenan.model.VesselManager;
import com.pesterenan.resources.Bundle;
import com.pesterenan.utils.Module;
-
-import javax.swing.*;
-import javax.swing.border.EtchedBorder;
-import javax.swing.border.TitledBorder;
-import java.awt.*;
+import java.awt.BorderLayout;
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;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+import javax.swing.border.EtchedBorder;
+import javax.swing.border.TitledBorder;
public class RoverJPanel extends JPanel implements UIMethods {
- private static final long serialVersionUID = 0L;
-
- private JLabel lblWaypointName, lblMaxSpeed;
- private JTextField txfWaypointName, txfMaxSpeed;
- private JButton btnBack, btnDrive;
- private ButtonGroup bgTargetChoice;
- private JRadioButton rbTargetVessel, rbWaypointOnMap;
-
- public RoverJPanel() {
- initComponents();
- setupComponents();
- layoutComponents();
+ private static final long serialVersionUID = 0L;
+
+ private JLabel lblWaypointName, lblMaxSpeed;
+ private JTextField txfWaypointName, txfMaxSpeed;
+ private JButton btnBack, btnDrive;
+ private ButtonGroup bgTargetChoice;
+ private JRadioButton rbTargetVessel, rbWaypointOnMap;
+ private VesselManager vesselManager;
+
+ private StatusDisplay statusDisplay;
+
+ public RoverJPanel(StatusDisplay statusDisplay) {
+ this.statusDisplay = statusDisplay;
+ initComponents();
+ setupComponents();
+ layoutComponents();
+ }
+
+ public void setVesselManager(VesselManager vesselManager) {
+ this.vesselManager = vesselManager;
+ }
+
+ @Override
+ public void initComponents() {
+ // Labels:
+ lblMaxSpeed = new JLabel(Bundle.getString("pnl_rover_lbl_max_speed"));
+ lblWaypointName = new JLabel(Bundle.getString("pnl_rover_waypoint_name"));
+
+ // Textfields:
+ txfMaxSpeed = new JTextField("10");
+ txfWaypointName = new JTextField(Bundle.getString("pnl_rover_default_name"));
+
+ // Buttons:
+ btnBack = new JButton(Bundle.getString("pnl_rover_btn_back"));
+ btnDrive = new JButton(Bundle.getString("pnl_rover_btn_drive"));
+
+ // Misc:
+ rbTargetVessel = new JRadioButton(Bundle.getString("pnl_rover_target_vessel"));
+ rbWaypointOnMap = new JRadioButton(Bundle.getString("pnl_rover_waypoint_on_map"));
+ }
+
+ @Override
+ public void setupComponents() {
+ // Main Panel setup:
+ setBorder(new TitledBorder(null, Bundle.getString("pnl_rover_border")));
+
+ // Setting-up components:
+ txfWaypointName.setEnabled(false);
+ txfWaypointName.setHorizontalAlignment(SwingConstants.CENTER);
+ txfWaypointName.setMaximumSize(BTN_DIMENSION);
+ txfWaypointName.setPreferredSize(BTN_DIMENSION);
+ txfMaxSpeed.setHorizontalAlignment(SwingConstants.RIGHT);
+ txfMaxSpeed.setMaximumSize(BTN_DIMENSION);
+ txfMaxSpeed.setPreferredSize(BTN_DIMENSION);
+
+ rbTargetVessel.setSelected(true);
+ rbTargetVessel.setActionCommand(Module.TARGET_VESSEL.get());
+ rbTargetVessel.addActionListener(this::handleTargetSelection);
+ rbWaypointOnMap.setActionCommand(Module.MAP_MARKER.get());
+ rbWaypointOnMap.addActionListener(this::handleTargetSelection);
+
+ bgTargetChoice = new ButtonGroup();
+ bgTargetChoice.add(rbTargetVessel);
+ bgTargetChoice.add(rbWaypointOnMap);
+
+ btnBack.addActionListener(MainGui::backToTelemetry);
+ btnBack.setMaximumSize(BTN_DIMENSION);
+ btnBack.setPreferredSize(BTN_DIMENSION);
+ btnDrive.addActionListener(this::handleDriveTo);
+ btnDrive.setMaximumSize(BTN_DIMENSION);
+ btnDrive.setPreferredSize(BTN_DIMENSION);
+ }
+
+ @Override
+ public void layoutComponents() {
+ // Main Panel layout:
+ setPreferredSize(PNL_DIMENSION);
+ setSize(PNL_DIMENSION);
+ setLayout(new BorderLayout());
+
+ // Layout components:
+ JPanel pnlWaypointName = new JPanel();
+ pnlWaypointName.setLayout(new BoxLayout(pnlWaypointName, BoxLayout.X_AXIS));
+ pnlWaypointName.add(lblWaypointName);
+ pnlWaypointName.add(Box.createHorizontalGlue());
+ pnlWaypointName.add(txfWaypointName);
+
+ 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(pnlWaypointName);
+ pnlRoverControls.add(pnlMaxSpeed);
+ pnlRoverControls.add(Box.createVerticalGlue());
+
+ JPanel pnlTargetChoice = new JPanel();
+ pnlTargetChoice.setBorder(
+ new TitledBorder(
+ new EtchedBorder(EtchedBorder.LOWERED), Bundle.getString("pnl_rover_target_choice")));
+ pnlTargetChoice.setLayout(new BoxLayout(pnlTargetChoice, BoxLayout.Y_AXIS));
+ pnlTargetChoice.add(rbTargetVessel);
+ pnlTargetChoice.add(rbWaypointOnMap);
+ pnlTargetChoice.add(Box.createHorizontalGlue());
+
+ JPanel pnlButtons = new JPanel();
+ pnlButtons.setLayout(new BoxLayout(pnlButtons, BoxLayout.X_AXIS));
+ pnlButtons.add(btnDrive);
+ pnlButtons.add(Box.createHorizontalGlue());
+ pnlButtons.add(btnBack);
+
+ JPanel pnlMain = new JPanel();
+ pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
+ pnlRoverControls.setAlignmentY(TOP_ALIGNMENT);
+ pnlTargetChoice.setAlignmentY(TOP_ALIGNMENT);
+ pnlMain.add(pnlRoverControls);
+ pnlMain.add(pnlTargetChoice);
+
+ setLayout(new BorderLayout());
+ add(pnlMain, BorderLayout.CENTER);
+ add(pnlButtons, BorderLayout.SOUTH);
+ }
+
+ private void handleTargetSelection(ActionEvent e) {
+ txfWaypointName.setEnabled(e.getSource().equals(rbWaypointOnMap));
+ }
+
+ private void handleDriveTo(ActionEvent e) {
+ if (validateTextFields()) {
+ Map commands = new HashMap<>();
+ commands.put(Module.MODULO.get(), Module.ROVER.get());
+ commands.put(
+ Module.ROVER_TARGET_TYPE.get(), bgTargetChoice.getSelection().getActionCommand());
+ commands.put(Module.MARKER_NAME.get(), txfWaypointName.getText());
+ commands.put(Module.MAX_SPEED.get(), txfMaxSpeed.getText());
+ vesselManager.startModule(commands);
}
-
- @Override
- public void initComponents() {
- // Labels:
- lblMaxSpeed = new JLabel(Bundle.getString("pnl_rover_lbl_max_speed"));
- lblWaypointName = new JLabel(Bundle.getString("pnl_rover_waypoint_name"));
-
- // Textfields:
- txfMaxSpeed = new JTextField("10");
- txfWaypointName = new JTextField(Bundle.getString("pnl_rover_default_name"));
-
- // Buttons:
- btnBack = new JButton(Bundle.getString("pnl_rover_btn_back"));
- btnDrive = new JButton(Bundle.getString("pnl_rover_btn_drive"));
-
- // Misc:
- rbTargetVessel = new JRadioButton(Bundle.getString("pnl_rover_target_vessel"));
- rbWaypointOnMap = new JRadioButton(Bundle.getString("pnl_rover_waypoint_on_map"));
- }
-
- @Override
- public void setupComponents() {
- // Main Panel setup:
- setBorder(new TitledBorder(null, Bundle.getString("pnl_rover_border")));
-
- // Setting-up components:
- txfWaypointName.setEnabled(false);
- txfWaypointName.setHorizontalAlignment(SwingConstants.CENTER);
- txfWaypointName.setMaximumSize(BTN_DIMENSION);
- txfWaypointName.setPreferredSize(BTN_DIMENSION);
- txfMaxSpeed.setHorizontalAlignment(SwingConstants.RIGHT);
- txfMaxSpeed.setMaximumSize(BTN_DIMENSION);
- txfMaxSpeed.setPreferredSize(BTN_DIMENSION);
-
- rbTargetVessel.setSelected(true);
- rbTargetVessel.setActionCommand(Module.TARGET_VESSEL.get());
- rbTargetVessel.addActionListener(this::handleTargetSelection);
- rbWaypointOnMap.setActionCommand(Module.MAP_MARKER.get());
- rbWaypointOnMap.addActionListener(this::handleTargetSelection);
-
- bgTargetChoice = new ButtonGroup();
- bgTargetChoice.add(rbTargetVessel);
- bgTargetChoice.add(rbWaypointOnMap);
-
- btnBack.addActionListener(MainGui::backToTelemetry);
- btnBack.setMaximumSize(BTN_DIMENSION);
- btnBack.setPreferredSize(BTN_DIMENSION);
- btnDrive.addActionListener(this::handleDriveTo);
- btnDrive.setMaximumSize(BTN_DIMENSION);
- btnDrive.setPreferredSize(BTN_DIMENSION);
- }
-
- @Override
- public void layoutComponents() {
- // Main Panel layout:
- setPreferredSize(PNL_DIMENSION);
- setSize(PNL_DIMENSION);
- setLayout(new BorderLayout());
-
- // Layout components:
- JPanel pnlWaypointName = new JPanel();
- pnlWaypointName.setLayout(new BoxLayout(pnlWaypointName, BoxLayout.X_AXIS));
- pnlWaypointName.add(lblWaypointName);
- pnlWaypointName.add(Box.createHorizontalGlue());
- pnlWaypointName.add(txfWaypointName);
-
- 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(pnlWaypointName);
- pnlRoverControls.add(pnlMaxSpeed);
- pnlRoverControls.add(Box.createVerticalGlue());
-
- JPanel pnlTargetChoice = new JPanel();
- pnlTargetChoice.setBorder(
- new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED), Bundle.getString("pnl_rover_target_choice")));
- pnlTargetChoice.setLayout(new BoxLayout(pnlTargetChoice, BoxLayout.Y_AXIS));
- pnlTargetChoice.add(rbTargetVessel);
- pnlTargetChoice.add(rbWaypointOnMap);
- pnlTargetChoice.add(Box.createHorizontalGlue());
-
- JPanel pnlButtons = new JPanel();
- pnlButtons.setLayout(new BoxLayout(pnlButtons, BoxLayout.X_AXIS));
- pnlButtons.add(btnDrive);
- pnlButtons.add(Box.createHorizontalGlue());
- pnlButtons.add(btnBack);
-
- JPanel pnlMain = new JPanel();
- pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
- pnlRoverControls.setAlignmentY(TOP_ALIGNMENT);
- pnlTargetChoice.setAlignmentY(TOP_ALIGNMENT);
- pnlMain.add(pnlRoverControls);
- pnlMain.add(pnlTargetChoice);
-
- setLayout(new BorderLayout());
- add(pnlMain, BorderLayout.CENTER);
- add(pnlButtons, BorderLayout.SOUTH);
- }
-
- private void handleTargetSelection(ActionEvent e) {
- txfWaypointName.setEnabled(e.getSource().equals(rbWaypointOnMap));
- }
-
- private void handleDriveTo(ActionEvent e) {
- if (validateTextFields()) {
- Map commands = new HashMap<>();
- commands.put(Module.MODULO.get(), Module.ROVER.get());
- commands.put(Module.ROVER_TARGET_TYPE.get(), bgTargetChoice.getSelection().getActionCommand());
- commands.put(Module.MARKER_NAME.get(), txfWaypointName.getText());
- commands.put(Module.MAX_SPEED.get(), txfMaxSpeed.getText());
- MechPeste.newInstance().startModule(commands);
- }
- }
-
- private boolean validateTextFields() {
- try {
- if (Float.parseFloat(txfMaxSpeed.getText()) < 3) {
- throw new NumberFormatException();
- }
- if (txfWaypointName.getText().equals("")) {
- throw new IllegalArgumentException();
- }
- } 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;
+ }
+
+ private boolean validateTextFields() {
+ try {
+ if (Float.parseFloat(txfMaxSpeed.getText()) < 3) {
+ throw new NumberFormatException();
+ }
+ if (txfWaypointName.getText().equals("")) {
+ throw new IllegalArgumentException();
+ }
+ } catch (NumberFormatException e) {
+ statusDisplay.setStatusMessage(Bundle.getString("pnl_rover_max_speed_above_3"));
+ return false;
+ } catch (IllegalArgumentException e) {
+ statusDisplay.setStatusMessage(Bundle.getString("pnl_rover_waypoint_name_not_empty"));
+ return false;
}
+ return true;
+ }
}
diff --git a/src/main/java/com/pesterenan/views/RunManeuverJPanel.java b/src/main/java/com/pesterenan/views/RunManeuverJPanel.java
index 90cd3ee..3e463e9 100644
--- a/src/main/java/com/pesterenan/views/RunManeuverJPanel.java
+++ b/src/main/java/com/pesterenan/views/RunManeuverJPanel.java
@@ -1,240 +1,262 @@
package com.pesterenan.views;
+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;
+
import com.pesterenan.MechPeste;
+import com.pesterenan.model.VesselManager;
import com.pesterenan.resources.Bundle;
-import com.pesterenan.utils.ControlePID;
import com.pesterenan.utils.Module;
-
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashMap;
+import java.util.Map;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.TitledBorder;
import krpc.client.RPCException;
import krpc.client.services.SpaceCenter.Node;
import krpc.client.services.SpaceCenter.Orbit;
import krpc.client.services.SpaceCenter.Vessel;
import krpc.client.services.SpaceCenter.VesselSituation;
-import javax.swing.*;
-import javax.swing.border.CompoundBorder;
-import javax.swing.border.TitledBorder;
-
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-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 RunManeuverJPanel extends JPanel implements ActionListener, UIMethods {
- private static final long serialVersionUID = 1L;
-
- private JLabel lblExecute;
- private JButton btnLowerOrbit, btnApoapsis, btnPeriapsis, btnExecute, btnBack, btnAlignPlanes, btnRendezvous;
- private JCheckBox chkFineAdjusment;
- private final ControlePID ctrlManeuver = new ControlePID();
-
- public RunManeuverJPanel() {
- initComponents();
- setupComponents();
- layoutComponents();
+ private static final long serialVersionUID = 1L;
+
+ private StatusDisplay statusDisplay;
+
+ private JLabel lblExecute;
+ private JButton btnLowerOrbit,
+ btnApoapsis,
+ btnPeriapsis,
+ btnExecute,
+ btnBack,
+ btnAlignPlanes,
+ btnRendezvous;
+ private JCheckBox chkFineAdjusment;
+ private VesselManager vesselManager;
+
+ public RunManeuverJPanel(StatusDisplay statusDisplay) {
+ this.statusDisplay = statusDisplay;
+ initComponents();
+ setupComponents();
+ layoutComponents();
+ }
+
+ public void setVesselManager(VesselManager vesselManager) {
+ this.vesselManager = vesselManager;
+ }
+
+ public void initComponents() {
+ // Labels:
+ lblExecute = new JLabel(Bundle.getString("pnl_mnv_lbl_exec_mnv"));
+
+ // Buttons:
+ btnApoapsis = new JButton(Bundle.getString("pnl_mnv_btn_apoapsis"));
+ btnBack = new JButton(Bundle.getString("pnl_mnv_btn_back"));
+ btnExecute = new JButton(Bundle.getString("pnl_mnv_btn_exec_mnv"));
+ btnLowerOrbit = new JButton(Bundle.getString("pnl_mnv_btn_lower_orbit"));
+ btnPeriapsis = new JButton(Bundle.getString("pnl_mnv_btn_periapsis"));
+ btnAlignPlanes = new JButton("Alinhar planos");
+ btnRendezvous = new JButton("Rendezvous");
+
+ // Misc:
+ chkFineAdjusment = new JCheckBox(Bundle.getString("pnl_mnv_chk_adj_mnv_rcs"));
+ }
+
+ public void createManeuver() {
+ System.out.println("Create maneuver");
+ try {
+ createManeuver(vesselManager.getSpaceCenter().getUT() + 60);
+ } catch (RPCException e) {
}
-
- public void initComponents() {
- // Labels:
- lblExecute = new JLabel(Bundle.getString("pnl_mnv_lbl_exec_mnv"));
-
- // Buttons:
- btnApoapsis = new JButton(Bundle.getString("pnl_mnv_btn_apoapsis"));
- btnBack = new JButton(Bundle.getString("pnl_mnv_btn_back"));
- btnExecute = new JButton(Bundle.getString("pnl_mnv_btn_exec_mnv"));
- btnLowerOrbit = new JButton(Bundle.getString("pnl_mnv_btn_lower_orbit"));
- btnPeriapsis = new JButton(Bundle.getString("pnl_mnv_btn_periapsis"));
- btnAlignPlanes = new JButton("Alinhar planos");
- btnRendezvous = new JButton("Rendezvous");
-
- // Misc:
- chkFineAdjusment = new JCheckBox(Bundle.getString("pnl_mnv_chk_adj_mnv_rcs"));
+ }
+
+ public void createManeuver(double atFutureTime) {
+ System.out.println("Create maneuver overloaded");
+ try {
+ Vessel vessel = vesselManager.getSpaceCenter().getActiveVessel();
+ System.out.println("vessel: " + vessel);
+
+ if (vessel.getSituation() != VesselSituation.ORBITING) {
+ statusDisplay.setStatusMessage("Não é possível criar a manobra fora de órbita.");
+ return;
+ }
+ vessel.getControl().addNode(atFutureTime, 0, 0, 0);
+ } catch (Exception e) {
}
-
- public static void createManeuver() {
- System.out.println("Create maneuver");
- try {
- createManeuver(MechPeste.getSpaceCenter().getUT() + 60);
- } catch (RPCException e) {
- }
+ }
+
+ public void positionManeuverAt(String node) {
+ try {
+ MechPeste.newInstance();
+ Vessel vessel = vesselManager.getSpaceCenter().getActiveVessel();
+ Orbit orbit = vessel.getOrbit();
+ Node currentManeuver = vessel.getControl().getNodes().get(0);
+ double timeToNode = 0;
+ switch (node) {
+ case "apoapsis":
+ timeToNode = vesselManager.getSpaceCenter().getUT() + orbit.getTimeToApoapsis();
+ break;
+ case "periapsis":
+ timeToNode = vesselManager.getSpaceCenter().getUT() + orbit.getTimeToPeriapsis();
+ break;
+ case "ascending":
+ double ascendingAnomaly =
+ orbit.trueAnomalyAtAN(vesselManager.getSpaceCenter().getTargetVessel().getOrbit());
+ timeToNode = orbit.uTAtTrueAnomaly(ascendingAnomaly);
+ break;
+ case "descending":
+ double descendingAnomaly =
+ orbit.trueAnomalyAtDN(vesselManager.getSpaceCenter().getTargetVessel().getOrbit());
+ timeToNode = orbit.uTAtTrueAnomaly(descendingAnomaly);
+ break;
+ }
+ currentManeuver.setUT(timeToNode);
+ // Print the maneuver node information
+ System.out.println("Maneuver Node updated:");
+ System.out.println(" Time to node: " + currentManeuver.getTimeTo() + " s");
+ } catch (Exception e) {
}
-
- public static void createManeuver(double atFutureTime) {
- System.out.println("Create maneuver overloaded");
- try {
- MechPeste.newInstance();
- Vessel vessel = MechPeste.getSpaceCenter().getActiveVessel();
- System.out.println("vessel: " + vessel);
-
- if (vessel.getSituation() != VesselSituation.ORBITING) {
- StatusJPanel.setStatusMessage("Não é possível criar a manobra fora de órbita.");
- return;
- }
- vessel.getControl().addNode(atFutureTime, 0, 0, 0);
- } catch (Exception e) {
- }
+ }
+
+ public void setupComponents() {
+ // Setting-up components:
+ btnAlignPlanes.addActionListener(this);
+ btnAlignPlanes.setMaximumSize(BTN_DIMENSION);
+ btnAlignPlanes.setPreferredSize(BTN_DIMENSION);
+ btnAlignPlanes.setEnabled(false); // FIX: Not yet ready
+
+ btnRendezvous.addActionListener(this);
+ btnRendezvous.setMaximumSize(BTN_DIMENSION);
+ btnRendezvous.setPreferredSize(BTN_DIMENSION);
+ btnRendezvous.setEnabled(false); // FIX: Not yet ready
+
+ btnApoapsis.addActionListener(this);
+ btnApoapsis.setMaximumSize(BTN_DIMENSION);
+ btnApoapsis.setPreferredSize(BTN_DIMENSION);
+
+ btnBack.addActionListener(this);
+ btnBack.setMaximumSize(BTN_DIMENSION);
+ btnBack.setPreferredSize(BTN_DIMENSION);
+
+ btnExecute.addActionListener(this);
+ btnExecute.setMaximumSize(BTN_DIMENSION);
+ btnExecute.setPreferredSize(BTN_DIMENSION);
+
+ btnLowerOrbit.addActionListener(this);
+ btnLowerOrbit.setMaximumSize(BTN_DIMENSION);
+ btnLowerOrbit.setPreferredSize(BTN_DIMENSION);
+
+ btnPeriapsis.addActionListener(this);
+ btnPeriapsis.setMaximumSize(BTN_DIMENSION);
+ btnPeriapsis.setPreferredSize(BTN_DIMENSION);
+ }
+
+ public void layoutComponents() {
+ // Main Panel layout:
+ setPreferredSize(PNL_DIMENSION);
+ setSize(PNL_DIMENSION);
+ setLayout(new BorderLayout());
+
+ JPanel pnlExecuteManeuver = new JPanel();
+ pnlExecuteManeuver.setLayout(new BoxLayout(pnlExecuteManeuver, BoxLayout.X_AXIS));
+ pnlExecuteManeuver.setBorder(MARGIN_BORDER_10_PX_LR);
+ pnlExecuteManeuver.add(lblExecute);
+ pnlExecuteManeuver.add(MainGui.createMarginComponent(10, 0));
+ pnlExecuteManeuver.add(btnExecute);
+
+ JPanel pnlAutoPosition = new JPanel();
+ pnlAutoPosition.setLayout(new BoxLayout(pnlAutoPosition, BoxLayout.X_AXIS));
+ pnlAutoPosition.setBorder(new TitledBorder("Auto posição:"));
+ pnlAutoPosition.add(btnAlignPlanes);
+ pnlAutoPosition.add(btnRendezvous);
+
+ JPanel pnlCircularize = new JPanel();
+ pnlCircularize.setLayout(new BoxLayout(pnlCircularize, BoxLayout.X_AXIS));
+ TitledBorder titled =
+ new TitledBorder(
+ null,
+ Bundle.getString("pnl_mnv_circularize"),
+ TitledBorder.LEADING,
+ TitledBorder.TOP,
+ null,
+ null);
+ CompoundBorder combined = new CompoundBorder(titled, MARGIN_BORDER_10_PX_LR);
+ pnlCircularize.setBorder(combined);
+ pnlCircularize.add(btnLowerOrbit);
+ pnlCircularize.add(Box.createHorizontalGlue());
+ pnlCircularize.add(btnApoapsis);
+ pnlCircularize.add(btnPeriapsis);
+
+ JPanel pnlSetup = new JPanel();
+ pnlSetup.setLayout(new BoxLayout(pnlSetup, BoxLayout.Y_AXIS));
+ pnlSetup.add(pnlExecuteManeuver);
+ pnlSetup.add(pnlAutoPosition);
+
+ JPanel pnlOptions = new JPanel();
+ pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS));
+ pnlOptions.setBorder(new TitledBorder(Bundle.getString("pnl_lift_chk_options")));
+ pnlOptions.add(chkFineAdjusment);
+
+ JPanel pnlFunctions = new JPanel();
+ pnlFunctions.setLayout(new BoxLayout(pnlFunctions, BoxLayout.X_AXIS));
+ pnlFunctions.add(pnlSetup);
+ pnlFunctions.add(pnlOptions);
+
+ JPanel pnlButtons = new JPanel();
+ pnlButtons.setLayout(new BoxLayout(pnlButtons, BoxLayout.X_AXIS));
+ pnlButtons.add(Box.createHorizontalGlue());
+ pnlButtons.add(btnBack);
+
+ JPanel pnlMain = new JPanel();
+ pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.Y_AXIS));
+ pnlFunctions.setAlignmentY(TOP_ALIGNMENT);
+ pnlMain.add(pnlFunctions);
+ pnlCircularize.setAlignmentY(TOP_ALIGNMENT);
+ pnlMain.add(pnlCircularize);
+
+ add(pnlMain, BorderLayout.CENTER);
+ add(pnlButtons, BorderLayout.SOUTH);
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == btnExecute) {
+ handleManeuverFunction(Module.EXECUTE.get());
}
-
- public static void positionManeuverAt(String node) {
- try {
- MechPeste.newInstance();
- Vessel vessel = MechPeste.getSpaceCenter().getActiveVessel();
- Orbit orbit = vessel.getOrbit();
- Node currentManeuver = vessel.getControl().getNodes().get(0);
- double timeToNode = 0;
- switch (node) {
- case "apoapsis" :
- timeToNode = MechPeste.getSpaceCenter().getUT() + orbit.getTimeToApoapsis();
- break;
- case "periapsis" :
- timeToNode = MechPeste.getSpaceCenter().getUT() + orbit.getTimeToPeriapsis();
- break;
- case "ascending" :
- double ascendingAnomaly = orbit
- .trueAnomalyAtAN(MechPeste.getSpaceCenter().getTargetVessel().getOrbit());
- timeToNode = orbit.uTAtTrueAnomaly(ascendingAnomaly);
- break;
- case "descending" :
- double descendingAnomaly = orbit
- .trueAnomalyAtDN(MechPeste.getSpaceCenter().getTargetVessel().getOrbit());
- timeToNode = orbit.uTAtTrueAnomaly(descendingAnomaly);
- break;
- }
- currentManeuver.setUT(timeToNode);
- // Print the maneuver node information
- System.out.println("Maneuver Node updated:");
- System.out.println(" Time to node: " + currentManeuver.getTimeTo() + " s");
- } catch (Exception e) {
- }
+ if (e.getSource() == btnLowerOrbit) {
+ handleManeuverFunction(Module.LOW_ORBIT.get());
}
-
- public void setupComponents() {
- // Setting-up components:
- btnAlignPlanes.addActionListener(this);
- btnAlignPlanes.setMaximumSize(BTN_DIMENSION);
- btnAlignPlanes.setPreferredSize(BTN_DIMENSION);
-
- btnRendezvous.addActionListener(this);
- btnRendezvous.setMaximumSize(BTN_DIMENSION);
- btnRendezvous.setPreferredSize(BTN_DIMENSION);
-
- btnApoapsis.addActionListener(this);
- btnApoapsis.setMaximumSize(BTN_DIMENSION);
- btnApoapsis.setPreferredSize(BTN_DIMENSION);
-
- btnBack.addActionListener(this);
- btnBack.setMaximumSize(BTN_DIMENSION);
- btnBack.setPreferredSize(BTN_DIMENSION);
-
- btnExecute.addActionListener(this);
- btnExecute.setMaximumSize(BTN_DIMENSION);
- btnExecute.setPreferredSize(BTN_DIMENSION);
-
- btnLowerOrbit.addActionListener(this);
- btnLowerOrbit.setMaximumSize(BTN_DIMENSION);
- btnLowerOrbit.setPreferredSize(BTN_DIMENSION);
-
- btnPeriapsis.addActionListener(this);
- btnPeriapsis.setMaximumSize(BTN_DIMENSION);
- btnPeriapsis.setPreferredSize(BTN_DIMENSION);
+ if (e.getSource() == btnApoapsis) {
+ handleManeuverFunction(Module.APOAPSIS.get());
}
-
- public void layoutComponents() {
- // Main Panel layout:
- setPreferredSize(PNL_DIMENSION);
- setSize(PNL_DIMENSION);
- setLayout(new BorderLayout());
-
- JPanel pnlExecuteManeuver = new JPanel();
- pnlExecuteManeuver.setLayout(new BoxLayout(pnlExecuteManeuver, BoxLayout.X_AXIS));
- pnlExecuteManeuver.setBorder(MARGIN_BORDER_10_PX_LR);
- pnlExecuteManeuver.add(lblExecute);
- pnlExecuteManeuver.add(MainGui.createMarginComponent(10, 0));
- pnlExecuteManeuver.add(btnExecute);
-
- JPanel pnlAutoPosition = new JPanel();
- pnlAutoPosition.setLayout(new BoxLayout(pnlAutoPosition, BoxLayout.X_AXIS));
- pnlAutoPosition.setBorder(new TitledBorder("Auto posição:"));
- pnlAutoPosition.add(btnAlignPlanes);
- pnlAutoPosition.add(btnRendezvous);
-
- JPanel pnlCircularize = new JPanel();
- pnlCircularize.setLayout(new BoxLayout(pnlCircularize, BoxLayout.X_AXIS));
- TitledBorder titled = new TitledBorder(null, Bundle.getString("pnl_mnv_circularize"), TitledBorder.LEADING,
- TitledBorder.TOP, null, null);
- CompoundBorder combined = new CompoundBorder(titled, MARGIN_BORDER_10_PX_LR);
- pnlCircularize.setBorder(combined);
- pnlCircularize.add(btnLowerOrbit);
- pnlCircularize.add(Box.createHorizontalGlue());
- pnlCircularize.add(btnApoapsis);
- pnlCircularize.add(btnPeriapsis);
-
- JPanel pnlSetup = new JPanel();
- pnlSetup.setLayout(new BoxLayout(pnlSetup, BoxLayout.Y_AXIS));
- pnlSetup.add(pnlExecuteManeuver);
- pnlSetup.add(pnlAutoPosition);
-
- JPanel pnlOptions = new JPanel();
- pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS));
- pnlOptions.setBorder(new TitledBorder(Bundle.getString("pnl_lift_chk_options")));
- pnlOptions.add(chkFineAdjusment);
-
- JPanel pnlFunctions = new JPanel();
- pnlFunctions.setLayout(new BoxLayout(pnlFunctions, BoxLayout.X_AXIS));
- pnlFunctions.add(pnlSetup);
- pnlFunctions.add(pnlOptions);
-
- JPanel pnlButtons = new JPanel();
- pnlButtons.setLayout(new BoxLayout(pnlButtons, BoxLayout.X_AXIS));
- pnlButtons.add(Box.createHorizontalGlue());
- pnlButtons.add(btnBack);
-
- JPanel pnlMain = new JPanel();
- pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.Y_AXIS));
- pnlFunctions.setAlignmentY(TOP_ALIGNMENT);
- pnlMain.add(pnlFunctions);
- pnlCircularize.setAlignmentY(TOP_ALIGNMENT);
- pnlMain.add(pnlCircularize);
-
- add(pnlMain, BorderLayout.CENTER);
- add(pnlButtons, BorderLayout.SOUTH);
+ if (e.getSource() == btnPeriapsis) {
+ handleManeuverFunction(Module.PERIAPSIS.get());
}
-
- @Override
- public void actionPerformed(ActionEvent e) {
- if (e.getSource() == btnExecute) {
- handleManeuverFunction(Module.EXECUTE.get());
- }
- if (e.getSource() == btnLowerOrbit) {
- handleManeuverFunction(Module.LOW_ORBIT.get());
- }
- if (e.getSource() == btnApoapsis) {
- handleManeuverFunction(Module.APOAPSIS.get());
- }
- if (e.getSource() == btnPeriapsis) {
- handleManeuverFunction(Module.PERIAPSIS.get());
- }
- if (e.getSource() == btnAlignPlanes) {
- handleManeuverFunction(Module.ADJUST.get());
- }
- if (e.getSource() == btnRendezvous) {
- handleManeuverFunction(Module.RENDEZVOUS.get());
- }
- if (e.getSource() == btnBack) {
- MainGui.backToTelemetry(e);
- }
+ if (e.getSource() == btnAlignPlanes) {
+ handleManeuverFunction(Module.ADJUST.get());
}
-
- protected void handleManeuverFunction(String maneuverFunction) {
- Map commands = new HashMap<>();
- commands.put(Module.MODULO.get(), Module.MANEUVER.get());
- commands.put(Module.FUNCTION.get(), maneuverFunction.toString());
- commands.put(Module.FINE_ADJUST.get(), String.valueOf(chkFineAdjusment.isSelected()));
- MechPeste.newInstance().startModule(commands);
+ if (e.getSource() == btnRendezvous) {
+ handleManeuverFunction(Module.RENDEZVOUS.get());
+ }
+ if (e.getSource() == btnBack) {
+ MainGui.backToTelemetry(e);
}
+ }
+
+ protected void handleManeuverFunction(String maneuverFunction) {
+ Map commands = new HashMap<>();
+ commands.put(Module.MODULO.get(), Module.MANEUVER.get());
+ commands.put(Module.FUNCTION.get(), maneuverFunction.toString());
+ commands.put(Module.FINE_ADJUST.get(), String.valueOf(chkFineAdjusment.isSelected()));
+ MechPeste.newInstance().getVesselManager().startModule(commands);
+ }
}
diff --git a/src/main/java/com/pesterenan/views/StatusDisplay.java b/src/main/java/com/pesterenan/views/StatusDisplay.java
new file mode 100644
index 0000000..89954c7
--- /dev/null
+++ b/src/main/java/com/pesterenan/views/StatusDisplay.java
@@ -0,0 +1,7 @@
+package com.pesterenan.views;
+
+public interface StatusDisplay {
+ void setStatusMessage(String message);
+
+ void setBtnConnectVisible(boolean visible);
+}
diff --git a/src/main/java/com/pesterenan/views/StatusJPanel.java b/src/main/java/com/pesterenan/views/StatusJPanel.java
index e3f6e34..da82833 100644
--- a/src/main/java/com/pesterenan/views/StatusJPanel.java
+++ b/src/main/java/com/pesterenan/views/StatusJPanel.java
@@ -1,76 +1,80 @@
package com.pesterenan.views;
-import com.pesterenan.MechPeste;
-import com.pesterenan.resources.Bundle;
-
-import javax.swing.*;
-
import static com.pesterenan.views.MainGui.BTN_DIMENSION;
import static com.pesterenan.views.MainGui.MARGIN_BORDER_10_PX_LR;
-import java.awt.*;
+import com.pesterenan.MechPeste;
+import com.pesterenan.resources.Bundle;
+import java.awt.BorderLayout;
+import java.awt.Dimension;
import java.awt.event.ActionEvent;
-
-public class StatusJPanel extends JPanel implements UIMethods {
- private static final long serialVersionUID = 1L;
-
- private static JLabel lblStatus;
- private static JButton btnConnect;
- private Dimension pnlDimension = new Dimension(464, 30);
-
- public StatusJPanel() {
- initComponents();
- setupComponents();
- layoutComponents();
- }
-
- @Override
- public void initComponents() {
- // Labels:
- lblStatus = new JLabel(Bundle.getString("lbl_stat_ready"));
-
- // Buttons:
- btnConnect = new JButton(Bundle.getString("btn_stat_connect"));
- }
-
- @Override
- public void setupComponents() {
- // Main Panel setup:
- setBorder(MARGIN_BORDER_10_PX_LR);
- setPreferredSize(pnlDimension);
-
- // Setting-up components:
- btnConnect.addActionListener(this::handleConnect);
- btnConnect.setPreferredSize(BTN_DIMENSION);
- btnConnect.setMaximumSize(BTN_DIMENSION);
- btnConnect.setVisible(false);
- }
-
- @Override
- public void layoutComponents() {
- // Main Panel layout:
- setLayout(new BorderLayout());
-
- // Laying out components:
- JPanel pnlMain = new JPanel();
- pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
- pnlMain.add(lblStatus);
- pnlMain.add(Box.createHorizontalGlue());
- pnlMain.add(btnConnect);
-
- add(pnlMain, BorderLayout.CENTER);
- }
-
- public static void setStatusMessage(String newStatus) {
- lblStatus.setText(newStatus);
- }
-
- public static void isBtnConnectVisible(boolean visible) {
- btnConnect.setVisible(visible);
- }
-
- private void handleConnect(ActionEvent e) {
- setStatusMessage(Bundle.getString("status_connecting"));
- MechPeste.newInstance().connectToKSP();
- }
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+public class StatusJPanel extends JPanel implements UIMethods, StatusDisplay {
+ private static final long serialVersionUID = 1L;
+
+ private static JLabel lblStatus;
+ private static JButton btnConnect;
+ private Dimension pnlDimension = new Dimension(464, 30);
+
+ public StatusJPanel() {
+ initComponents();
+ setupComponents();
+ layoutComponents();
+ }
+
+ @Override
+ public void initComponents() {
+ // Labels:
+ lblStatus = new JLabel(Bundle.getString("lbl_stat_ready"));
+
+ // Buttons:
+ btnConnect = new JButton(Bundle.getString("btn_stat_connect"));
+ }
+
+ @Override
+ public void setupComponents() {
+ // Main Panel setup:
+ setBorder(MARGIN_BORDER_10_PX_LR);
+ setPreferredSize(pnlDimension);
+
+ // Setting-up components:
+ btnConnect.addActionListener(this::handleConnect);
+ btnConnect.setPreferredSize(BTN_DIMENSION);
+ btnConnect.setMaximumSize(BTN_DIMENSION);
+ btnConnect.setVisible(false);
+ }
+
+ @Override
+ public void layoutComponents() {
+ // Main Panel layout:
+ setLayout(new BorderLayout());
+
+ // Laying out components:
+ JPanel pnlMain = new JPanel();
+ pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS));
+ pnlMain.add(lblStatus);
+ pnlMain.add(Box.createHorizontalGlue());
+ pnlMain.add(btnConnect);
+
+ add(pnlMain, BorderLayout.CENTER);
+ }
+
+ @Override
+ public void setStatusMessage(String message) {
+ lblStatus.setText(message);
+ }
+
+ @Override
+ public void setBtnConnectVisible(boolean visible) {
+ btnConnect.setVisible(visible);
+ }
+
+ private void handleConnect(ActionEvent e) {
+ MechPeste.newInstance().getConnectionManager().connect();
+ }
}
diff --git a/src/main/java/com/pesterenan/views/UIMethods.java b/src/main/java/com/pesterenan/views/UIMethods.java
index eff0f48..919d512 100644
--- a/src/main/java/com/pesterenan/views/UIMethods.java
+++ b/src/main/java/com/pesterenan/views/UIMethods.java
@@ -2,9 +2,9 @@
public interface UIMethods {
- public void initComponents();
+ public void initComponents();
- public void setupComponents();
+ public void setupComponents();
- public void layoutComponents();
+ public void layoutComponents();
}
diff --git a/src/main/resources/MechPesteBundle.properties b/src/main/resources/MechPesteBundle.properties
index 91f4d43..a5a635a 100644
--- a/src/main/resources/MechPesteBundle.properties
+++ b/src/main/resources/MechPesteBundle.properties
@@ -123,3 +123,6 @@ status_separating_stage = Decoupling stage...
status_starting_landing = Starting Automatic Landing\!
status_starting_landing_at = Starting automatic landing at\:
status_waiting_for_landing = Waiting for auto-landing...
+status_waiting_flight = Waiting for flight scene...
+status_stabilizing_roll=Stabilizing roll...
+status_orienting_to_maneuver=Orienting to maneuver...
\ No newline at end of file
diff --git a/src/main/resources/MechPesteBundle_pt.properties b/src/main/resources/MechPesteBundle_pt.properties
index b2636c5..efe0c51 100644
--- a/src/main/resources/MechPesteBundle_pt.properties
+++ b/src/main/resources/MechPesteBundle_pt.properties
@@ -122,3 +122,6 @@ status_separating_stage = Separando est\u00E1gio...
status_starting_landing = Iniciando Pouso Autom\u00E1tico\!
status_starting_landing_at = Iniciando pouso autom\u00E1tico em\:
status_waiting_for_landing = Esperando pelo pouso autom\u00E1tico...
+status_waiting_flight = Aguardando cena de voo...
+status_stabilizing_roll=Estabilizando rolagem... │
+status_orienting_to_maneuver=Orientando para a manobra... │