diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 0ef03cf..dd190d0 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -23,10 +23,10 @@ jobs: - name: Install KRPC as a Local Library run: | mvn install:install-file \ - -Dfile=./src/main/resources/krpc-java-0.5.2.jar \ + -Dfile=./src/main/resources/krpc-java-0.5.4.jar \ -DgroupId=io.github.krpc \ -DartifactId=krpc-java \ - -Dversion=0.5.2 \ + -Dversion=0.5.4 \ -Dpackaging=jar - name: Set up JDK 17 diff --git a/.github/workflows/release-new-version.yml b/.github/workflows/release-new-version.yml index b7e6a5a..863416d 100644 --- a/.github/workflows/release-new-version.yml +++ b/.github/workflows/release-new-version.yml @@ -21,10 +21,10 @@ jobs: - name: Install KRPC as a Local Library run: | mvn install:install-file \ - -Dfile=./src/main/resources/krpc-java-0.5.2.jar \ + -Dfile=./src/main/resources/krpc-java-0.5.4.jar \ -DgroupId=io.github.krpc \ -DartifactId=krpc-java \ - -Dversion=0.5.2 \ + -Dversion=0.5.4 \ -Dpackaging=jar - name: Set up JDK 17 diff --git a/.gitignore b/.gitignore index 4dc29f9..7b89667 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ .shelf/ .idea/ -.settings/ bin/ tmp/ *.tmp diff --git a/.settings/org.eclipse.core.runtime.prefs b/.settings/org.eclipse.core.runtime.prefs deleted file mode 100644 index deae05a..0000000 --- a/.settings/org.eclipse.core.runtime.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -line.separator=\r\n diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index fa50df0..0f0bc12 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,12 +1,22 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +# Java Version org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 org.eclipse.jdt.core.compiler.compliance=1.8 -org.eclipse.jdt.core.compiler.problem.assertIdentifier=error -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.enumIdentifier=error -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.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000..91a46d2 --- /dev/null +++ b/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,3 @@ +eclipse.preferences.version=1 +formatter_profile=_custom +formatter_settings_version=12 diff --git a/README.md b/README.md index c470c4c..1fd3f25 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ manobras, e pilotar rovers. --- É necessário ter o [Java](https://java.com/pt-BR/) instalado para utilizar o "MechPeste.jar". Uma versão mais atualizada do -mod [KRPC](https://github.com/krpc/krpc/releases/download/v0.5.2/krpc-0.5.2.zip) +mod [KRPC](https://github.com/krpc/krpc) pode ser instalada diretamente do aplicativo MechPeste pelo menu Arquivo > Instalar KRPC. ## **Como instalar:** @@ -78,14 +78,14 @@ mover para o alvo, desviando dos obstáculos à frente. Agora o MechPeste tem como base o gerenciador de dependências Maven. Para poder instalar a biblioteca do KRPC no entanto, como não está disponível no repositório público do Maven, é necessário fazer o download -e instalar a biblioteca KRPC em sua versão 0.5.2 com o seguinte comando: +e instalar a biblioteca KRPC em sua versão 0.5.4 com o seguinte comando: ``` bash mvn install:install-file \ - -Dfile=\krpc-java-0.5.2.jar \ + -Dfile=\krpc-java-0.5.4.jar \ -DgroupId=io.github.krpc \ -DartifactId=krpc-java \ - -Dversion=0.5.2 \ + -Dversion=0.5.4 \ -Dpackaging=jar \ ``` Substitua `` pela pasta onde está o arquivo do KRPC. Isso instalará essa biblioteca diff --git a/pom.xml b/pom.xml index 20049da..3936d8f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.pesterenan MechPeste - 0.7.1 + 0.8.0 @@ -15,8 +15,8 @@ 3.11.0 UTF-8 - - + + org.apache.maven.plugins maven-jar-plugin @@ -25,10 +25,10 @@ com.pesterenan.MechPeste - - - - + + + + org.apache.maven.plugins maven-assembly-plugin @@ -37,53 +37,66 @@ com.pesterenan.MechPeste - - + + jar-with-dependencies - + MechPeste-${project.version} false - + make-assembly package single - - - - - - + + + + + + com.diffplug.spotless + spotless-maven-plugin + 2.37.0 + + + + 4.19 + ${project.basedir}/.settings/org.eclipse.jdt.core.prefs + + + + + + 1.8 1.8 - + org.apache.maven maven-model 3.3.9 - + io.github.krpc krpc-java - 0.5.2 - + 0.5.4 + org.javatuples javatuples 1.2 - + com.google.protobuf protobuf-java 3.22.1 - - + + - + diff --git a/src/main/java/com/pesterenan/Main.java b/src/main/java/com/pesterenan/Main.java index ceb84df..ac0b287 100644 --- a/src/main/java/com/pesterenan/Main.java +++ b/src/main/java/com/pesterenan/Main.java @@ -159,8 +159,7 @@ public static void main(String[] args) { 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 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); @@ -190,17 +189,12 @@ private static float calculateThrottle(double minDistance, double maxDistance, d 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(), + 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); diff --git a/src/main/java/com/pesterenan/MechPeste.java b/src/main/java/com/pesterenan/MechPeste.java index 0367073..da9689e 100644 --- a/src/main/java/com/pesterenan/MechPeste.java +++ b/src/main/java/com/pesterenan/MechPeste.java @@ -27,186 +27,186 @@ import krpc.client.services.SpaceCenter.Vessel; 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 naveStr = v.hashCode() + " - \t" + v.getName(); - list.addElement(naveStr); - } catch (RPCException ignored) { - } - }); - } catch (RPCException | NullPointerException ignored) { - } - return list; - } - - 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 naveAtual = spaceCenter.getVessels().stream().filter(v -> v.hashCode() == selectedIndex).findFirst() - .get(); - String name = naveAtual.getName().length() > 40 - ? naveAtual.getName().substring(0, 40) + "..." - : naveAtual.getName(); - String vesselInfo = String.format("Nome: %s\t\t\t | Corpo: %s", name, - naveAtual.getOrbit().getBody().getName()); - return vesselInfo; - } catch (RPCException | NullPointerException ignored) { - } - return ""; - } - - public static void changeToVessel(int selectedIndex) { - try { - Vessel naveAtual = spaceCenter.getVessels().stream().filter(v -> v.hashCode() == selectedIndex).findFirst() - .get(); - spaceCenter.setActiveVessel(naveAtual); - } catch (RPCException | NullPointerException e) { - System.out.println(Bundle.getString("status_couldnt_switch_vessel")); - } - } - - public static void cancelControl(ActionEvent e) { - currentVessel.cancelControl(); - } - - 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 KRPC.GameScene getCurrentGameScene() throws RPCException { - return krpc.getCurrentGameScene(); - } - - public void startModule(Map commands) { - currentVessel.startModule(commands); - } - - 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 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) { - } - } - } + 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; + } + + 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(); + } + + 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 KRPC.GameScene getCurrentGameScene() throws RPCException { + return krpc.getCurrentGameScene(); + } + + public void startModule(Map commands) { + currentVessel.startModule(commands); + } + + 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 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) { + } + } + } } diff --git a/src/main/java/com/pesterenan/controllers/Controller.java b/src/main/java/com/pesterenan/controllers/Controller.java index 6d35cc3..c0901f7 100644 --- a/src/main/java/com/pesterenan/controllers/Controller.java +++ b/src/main/java/com/pesterenan/controllers/Controller.java @@ -4,20 +4,20 @@ public class Controller extends ActiveVessel implements Runnable { - public Controller() { - super(); - } + 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 void run() { + try { + while (!Thread.interrupted()) { + long currentTime = System.currentTimeMillis(); + if (currentTime > timer + 100) { + recordTelemetryData(); + timer = currentTime; + } + } + } catch (Exception ignored) { + } + } } diff --git a/src/main/java/com/pesterenan/controllers/DockingController.java b/src/main/java/com/pesterenan/controllers/DockingController.java index 93e3872..978fb31 100644 --- a/src/main/java/com/pesterenan/controllers/DockingController.java +++ b/src/main/java/com/pesterenan/controllers/DockingController.java @@ -6,7 +6,7 @@ import java.util.Map; import com.pesterenan.resources.Bundle; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import com.pesterenan.utils.Utilities; import com.pesterenan.utils.Vector; import com.pesterenan.views.DockingJPanel; @@ -23,287 +23,278 @@ 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(Modulos.VELOCIDADE_MAX.get())); - SAFE_DISTANCE = Double.parseDouble(commands.get(Modulos.DISTANCIA_SEGURA.get())); - drawing = Drawing.newInstance(getConnection()); - targetVessel = getSpaceCenter().getTargetVessel(); - control = getNaveAtual().getControl(); - vesselRefFrame = getNaveAtual().getReferenceFrame(); - orbitalRefVessel = getNaveAtual().getOrbitalReferenceFrame(); - - myDockingPort = getNaveAtual().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(Modulos.MODULO.get()).equals(Modulos.MODULO_DOCKING.get())) { - startDocking(); - } - } - - private void pointToTarget(Vector targetDirection) throws RPCException, InterruptedException { - getNaveAtual().getAutoPilot().setReferenceFrame(orbitalRefVessel); - getNaveAtual().getAutoPilot().setTargetDirection(targetDirection.toTriplet()); - getNaveAtual().getAutoPilot().setTargetRoll(90); - getNaveAtual().getAutoPilot().engage(); - // Fazer a nave apontar usando o piloto automático, na marra - while (Math.abs(getNaveAtual().getAutoPilot().getError()) > 3) { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - Thread.sleep(100); - System.out.println(getNaveAtual().getAutoPilot().getError()); - } - getNaveAtual().getAutoPilot().disengage(); - control.setSAS(true); - control.setSASMode(SASMode.STABILITY_ASSIST); - } - - private void getCloserToTarget(Vector targetPosition) throws InterruptedException, RPCException { - lastXTargetPos = targetPosition.x; - lastYTargetPos = targetPosition.y; - lastZTargetPos = targetPosition.z; - - while (Math.abs(lastYTargetPos) >= SAFE_DISTANCE) { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - targetPosition = new Vector(targetVessel.position(vesselRefFrame)); - controlShipRCS(targetPosition, SAFE_DISTANCE); - Thread.sleep(sleepTime); - } - - } - - public void startDocking() { - try { - // Setting up the control - control.setSAS(true); - control.setRCS(false); - control.setSASMode(SASMode.STABILITY_ASSIST); - createLines(positionMyDockingPort, positionTargetDockingPort); - - // PRIMEIRA PARTE DO DOCKING: APROXIMAÇÃO - Vector targetPosition = new Vector(targetVessel.position(vesselRefFrame)); - if (targetPosition.magnitude() > SAFE_DISTANCE) { - // Apontar para o alvo: - Vector targetDirection = new Vector(getNaveAtual().position(orbitalRefVessel)) - .subtract(new Vector(targetVessel.position(orbitalRefVessel))).multiply(-1); - pointToTarget(targetDirection); - - control.setRCS(true); - - getCloserToTarget(targetPosition); - } - - control.setSAS(false); - control.setRCS(false); - - // SEGUNDA PARTE FICAR DE FRENTE COM A DOCKING PORT: - Vector targetDockingPortDirection = new Vector(targetDockingPort.direction(orbitalRefVessel)) - .multiply(-1); - pointToTarget(targetDockingPortDirection); - - Thread.sleep(1000); - control.setRCS(true); - double safeDistance = 10; - while (true) { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - targetPosition = new Vector(targetDockingPort.position(vesselRefFrame)) - .subtract(new Vector(myDockingPort.position(vesselRefFrame))); - if (targetPosition.magnitude() < safeDistance) { - safeDistance = 1; - } - controlShipRCS(targetPosition, safeDistance); - Thread.sleep(sleepTime); - } - } catch (RPCException | InterruptedException | IllegalArgumentException e) { - StatusJPanel.setStatusMessage("Docking interrupted."); - } - } - - /* - * 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 - } - - 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 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 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 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() { + 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); + 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."); + } + } + + /* + * 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 + } + + 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 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/controllers/LandingController.java b/src/main/java/com/pesterenan/controllers/LandingController.java index df9072c..57cdc6f 100644 --- a/src/main/java/com/pesterenan/controllers/LandingController.java +++ b/src/main/java/com/pesterenan/controllers/LandingController.java @@ -6,7 +6,7 @@ import com.pesterenan.resources.Bundle; import com.pesterenan.utils.ControlePID; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import com.pesterenan.utils.Navigation; import com.pesterenan.utils.Utilities; @@ -16,270 +16,269 @@ 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 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(getNaveAtual()); - this.initializeParameters(); - } + public LandingController(Map commands) { + super(); + this.commands = commands; + this.navigation = new Navigation(getActiveVessel()); + this.initializeParameters(); + } - private void initializeParameters() { - altitudeCtrl = new ControlePID(getSpaceCenter(), sleepTime); - velocityCtrl = new ControlePID(getSpaceCenter(), sleepTime); - altitudeCtrl.setOutput(0, 1); - velocityCtrl.setOutput(0, 1); - } + private void initializeParameters() { + altitudeCtrl = new ControlePID(getSpaceCenter(), sleepTime); + velocityCtrl = new ControlePID(getSpaceCenter(), sleepTime); + altitudeCtrl.setOutput(0, 1); + velocityCtrl.setOutput(0, 1); + } - @Override - public void run() { - if (commands.get(Modulos.MODULO.get()).equals(Modulos.MODULO_POUSO_SOBREVOAR.get())) { - hoverArea(); - } - if (commands.get(Modulos.MODULO.get()).equals(Modulos.MODULO_POUSO.get())) { - autoLanding(); - } - } + @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 void hoverArea() { - try { - hoverAltitude = Double.parseDouble(commands.get(Modulos.ALTITUDE_SOBREVOO.get())); - hoveringMode = true; - ap.engage(); - tuneAutoPilot(); - while (hoveringMode) { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - try { - altitudeErrorPercentage = altitudeSup.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 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 autoLanding() { - try { - landingMode = true; - maxTWR = Float.parseFloat(commands.get(Modulos.MAX_TWR.get())); - hoverAfterApproximation = Boolean.parseBoolean(commands.get(Modulos.SOBREVOO_POS_POUSO.get())); - hoverAltitude = Double.parseDouble(commands.get(Modulos.ALTITUDE_SOBREVOO.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(); - } - getNaveAtual().getControl().setBrakes(true); - changeControlMode(); - Thread.sleep(sleepTime); - } - } catch (RPCException | StreamException | InterruptedException e) { - setCurrentStatus(Bundle.getString("status_ready")); - } - } + 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 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 (velVertical.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(velVertical.get() / sleepTime, - (-Utilities.clamp(altitudeSup.get() * 0.1, 3, 20) / sleepTime)); - throttle(Utilities.linearInterpolation(velPID, altPID, threshold)); - navigation.aimForLanding(); - if (threshold < 0.15 || altitudeSup.get() < landingDistanceThreshold) { - hoverAltitude = landingDistanceThreshold; - getNaveAtual().getControl().setGear(true); - if (hoverAfterApproximation) { - landingMode = false; - hoverArea(); - break; - } - currentMode = MODE.LANDING; - } - 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(velVertical.get(), MAX_VELOCITY); - throttle(altPID + velPID); - navigation.aimAtRadialOut(); - setCurrentStatus("Subindo altitude..."); - break; - case GOING_DOWN: - altitudeCtrl.reset(); - velocityCtrl.reset(); - controlThrottleByMatchingVerticalVelocity(-MAX_VELOCITY); - navigation.aimAtRadialOut(); - setCurrentStatus("Baixando altitude..."); - break; - case LANDING: - altitudeCtrl.reset(); - velocityCtrl.reset(); - controlThrottleByMatchingVerticalVelocity( - velHorizontal.get() > 4 ? 0 : -Utilities.clamp(altitudeSup.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(velVertical.get(), 0); - throttle(altPID + velPID); - navigation.aimAtRadialOut(); - setCurrentStatus("Sobrevoando area..."); - break; - } - } + 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; + } + 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; + } + } - private void controlThrottleByMatchingVerticalVelocity(double velocityToMatch) throws RPCException, - StreamException { - velocityCtrl.setOutput(0, 1); - throttle(velocityCtrl.calculate(velVertical.get(), velocityToMatch + velHorizontal.get())); - } + private void controlThrottleByMatchingVerticalVelocity(double velocityToMatch) + throws RPCException, StreamException { + velocityCtrl.setOutput(0, 1); + throttle(velocityCtrl.calculate(verticalVelocity.get(), velocityToMatch + horizontalVelocity.get())); + } - private void deOrbitShip() throws RPCException, StreamException, InterruptedException { - throttle(0.0f); - if (getNaveAtual().getSituation().equals(VesselSituation.ORBITING) || - getNaveAtual().getSituation().equals(VesselSituation.SUB_ORBITAL)) { - setCurrentStatus(Bundle.getString("status_going_suborbital")); - ap.engage(); - getNaveAtual().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 (periastro.get() > -apoastro.get()) { - navigation.aimForLanding(); - throttle(altitudeCtrl.calculate(targetPeriapsis, periastro.get())); - setCurrentStatus(Bundle.getString("status_lowering_periapsis")); - Thread.sleep(sleepTime); - } - getNaveAtual().getControl().setRCS(false); - throttle(0.0f); - } - } + 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); + } + } - /** - * 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); - } + /** + * 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); + } - private boolean hasTheVesselLanded() throws RPCException { - if (getNaveAtual().getSituation().equals(VesselSituation.LANDED) || - getNaveAtual().getSituation().equals(VesselSituation.SPLASHED)) { - setCurrentStatus(Bundle.getString("status_landed")); - hoveringMode = false; - landingMode = false; - throttle(0.0f); - getNaveAtual().getControl().setSAS(true); - getNaveAtual().getControl().setRCS(true); - getNaveAtual().getControl().setBrakes(false); - ap.disengage(); - return true; - } - return false; - } + private boolean hasTheVesselLanded() throws RPCException { + if (getActiveVessel().getSituation().equals(VesselSituation.LANDED) + || getActiveVessel().getSituation().equals(VesselSituation.SPLASHED)) { + setCurrentStatus(Bundle.getString("status_landed")); + hoveringMode = false; + landingMode = false; + throttle(0.0f); + getActiveVessel().getControl().setSAS(true); + getActiveVessel().getControl().setRCS(true); + getActiveVessel().getControl().setBrakes(false); + ap.disengage(); + return true; + } + return false; + } - private double calculateCurrentVelocityMagnitude() throws RPCException, StreamException { - double timeToGround = altitudeSup.get() / velVertical.get(); - double horizontalDistance = velHorizontal.get() * timeToGround; - return calculateEllipticTrajectory(horizontalDistance, altitudeSup.get()); - } + private double calculateCurrentVelocityMagnitude() throws RPCException, StreamException { + double timeToGround = surfaceAltitude.get() / verticalVelocity.get(); + double horizontalDistance = horizontalVelocity.get() * timeToGround; + return calculateEllipticTrajectory(horizontalDistance, surfaceAltitude.get()); + } - private double calculateZeroVelocityMagnitude() throws RPCException, StreamException { - double zeroVelocityDistance = calculateEllipticTrajectory(velHorizontal.get(), velVertical.get()); - double zeroVelocityBurnTime = zeroVelocityDistance / getMaxAcel(maxTWR); - return zeroVelocityDistance * zeroVelocityBurnTime; - } + private double calculateZeroVelocityMagnitude() throws RPCException, StreamException { + double zeroVelocityDistance = calculateEllipticTrajectory(horizontalVelocity.get(), verticalVelocity.get()); + double zeroVelocityBurnTime = zeroVelocityDistance / getMaxAcel(maxTWR); + return zeroVelocityDistance * zeroVelocityBurnTime; + } - 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 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 enum MODE { + DEORBITING, APPROACHING, GOING_UP, HOVERING, GOING_DOWN, LANDING, WAITING + } } diff --git a/src/main/java/com/pesterenan/controllers/LiftoffController.java b/src/main/java/com/pesterenan/controllers/LiftoffController.java index b81b0d8..2901639 100644 --- a/src/main/java/com/pesterenan/controllers/LiftoffController.java +++ b/src/main/java/com/pesterenan/controllers/LiftoffController.java @@ -2,217 +2,219 @@ 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.resources.Bundle; import com.pesterenan.utils.ControlePID; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import com.pesterenan.utils.Navigation; import com.pesterenan.utils.Utilities; + import krpc.client.RPCException; import krpc.client.StreamException; import krpc.client.services.SpaceCenter.Engine; import krpc.client.services.SpaceCenter.Fairing; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - 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 = Modulos.CIRCULAR.get(); - private Navigation navigation; - - public LiftoffController(Map commands) { - super(); - this.commands = commands; - this.navigation = new Navigation(getNaveAtual()); - initializeParameters(); - } - - private void initializeParameters() { - currentPitch = PITCH_UP; - setFinalApoapsisAlt(Float.parseFloat(commands.get(Modulos.APOASTRO.get()))); - setHeading(Float.parseFloat(commands.get(Modulos.DIRECAO.get()))); - setRoll(Float.parseFloat(commands.get(Modulos.ROLAGEM.get()))); - maxTWR = (float) Utilities.clamp(Float.parseFloat(commands.get(Modulos.MAX_TWR.get())), 1.2, 5.0); - setGravityCurveModel(commands.get(Modulos.INCLINACAO.get())); - willOpenPanelsAndAntenna = Boolean.parseBoolean(commands.get(Modulos.ABRIR_PAINEIS.get())); - willDecoupleStages = Boolean.parseBoolean(commands.get(Modulos.USAR_ESTAGIOS.get())); - thrControl = new ControlePID(getSpaceCenter(), 25); - thrControl.setOutput(0.0, 1.0); - } - - @Override - public void run() { - try { - tuneAutoPilot(); - liftoff(); - gravityCurve(); - finalizeCurve(); - circularizeOrbitOnApoapsis(); - } catch (RPCException | InterruptedException | StreamException ignored) { - setCurrentStatus(Bundle.getString("status_ready")); - } - } - - 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 (apoastro.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(apoastro.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(); - } - } - } - - private double calculateTWRBasedOnPressure(float currentPitch) throws RPCException { - float currentPressure = parametrosDeVoo.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); - } - - private void finalizeCurve() throws RPCException, StreamException, InterruptedException { - setCurrentStatus(Bundle.getString("status_maintaining_until_orbit")); - getNaveAtual().getControl().setRCS(true); - - while (parametrosDeVoo.getDynamicPressure() > 10) { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - navigation.aimAtPrograde(); - throttle(thrControl.calculate(apoastro.get() / getFinalApoapsis() * 1000, 1000)); - Thread.sleep(25); - } - throttle(0.0f); - if (willDecoupleStages) { - jettisonFairings(); - } - if (willOpenPanelsAndAntenna) { - openPanelsAndAntenna(); - } - } - - private void circularizeOrbitOnApoapsis() { - setCurrentStatus(Bundle.getString("status_planning_orbit")); - Map commands = new HashMap<>(); - commands.put(Modulos.MODULO.get(), Modulos.MODULE_MANEUVER.get()); - commands.put(Modulos.FUNCAO.get(), Modulos.APOASTRO.get()); - commands.put(Modulos.AJUSTE_FINO.get(), String.valueOf(false)); - MechPeste.newInstance().startModule(commands); - } - - private void jettisonFairings() throws RPCException, InterruptedException { - List fairings = getNaveAtual().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); - } - } - } - } - - private void openPanelsAndAntenna() throws RPCException, InterruptedException { - getNaveAtual().getControl().setSolarPanels(true); - getNaveAtual().getControl().setRadiators(true); - getNaveAtual().getControl().setAntennas(true); - } - - private double calculateCurrentPitch(double currentAltitude) { - if (gravityCurveModel.equals(Modulos.QUADRATICA.get())) { - return Utilities.easeInQuad(currentAltitude) * PITCH_UP; - } - if (gravityCurveModel.equals(Modulos.CUBICA.get())) { - return Utilities.easeInCubic(currentAltitude) * PITCH_UP; - } - if (gravityCurveModel.equals(Modulos.SINUSOIDAL.get())) { - return Utilities.easeInSine(currentAltitude) * PITCH_UP; - } - if (gravityCurveModel.equals(Modulos.EXPONENCIAL.get())) { - return Utilities.easeInExpo(currentAltitude) * PITCH_UP; - } - return Utilities.easeInCirc(currentAltitude) * PITCH_UP; - } - - private boolean isCurrentStageWithoutFuel() throws RPCException { - for (Engine engine : getNaveAtual().getParts().getEngines()) { - if (engine.getPart().getStage() == getNaveAtual().getControl().getCurrentStage() && !engine.getHasFuel()) { - return true; - } - } - return false; - } - - public float getHeading() { - return heading; - } - - 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); - } - - public float getFinalApoapsis() { - return finalApoapsisAlt; - } - - public float getRoll() { - return this.roll; - } - - 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 setGravityCurveModel(String model) { - this.gravityCurveModel = model; - } - - 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 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 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); + } + + @Override + public void run() { + try { + tuneAutoPilot(); + liftoff(); + gravityCurve(); + finalizeCurve(); + circularizeOrbitOnApoapsis(); + } catch (RPCException | InterruptedException | StreamException ignored) { + setCurrentStatus(Bundle.getString("status_ready")); + } + } + + 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(); + } + } + } + + 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); + } + + 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(); + } + } + + 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); + } + + 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); + } + } + } + } + + private void openPanelsAndAntenna() throws RPCException, InterruptedException { + getActiveVessel().getControl().setSolarPanels(true); + getActiveVessel().getControl().setRadiators(true); + 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; + } + + private boolean isCurrentStageWithoutFuel() throws RPCException { + for (Engine engine : getActiveVessel().getParts().getEngines()) { + if (engine.getPart().getStage() == getActiveVessel().getControl().getCurrentStage() + && !engine.getHasFuel()) { + return true; + } + } + return false; + } + + public float getHeading() { + return heading; + } + + 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); + } + + public float getFinalApoapsis() { + return finalApoapsisAlt; + } + + public float getRoll() { + return this.roll; + } + + 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 setGravityCurveModel(String model) { + this.gravityCurveModel = model; + } + + 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); + } } diff --git a/src/main/java/com/pesterenan/controllers/ManeuverController.java b/src/main/java/com/pesterenan/controllers/ManeuverController.java index 10f4f96..40356e9 100644 --- a/src/main/java/com/pesterenan/controllers/ManeuverController.java +++ b/src/main/java/com/pesterenan/controllers/ManeuverController.java @@ -11,7 +11,7 @@ import com.pesterenan.resources.Bundle; import com.pesterenan.utils.Attributes; import com.pesterenan.utils.ControlePID; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import com.pesterenan.utils.Navigation; import com.pesterenan.utils.Vector; import com.pesterenan.views.RunManeuverJPanel; @@ -29,527 +29,523 @@ 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(getNaveAtual()); - initializeParameters(); - } - - 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(Modulos.AJUSTE_FINO.get())); - try { - lowOrbitAltitude = new Attributes().getLowOrbitAltitude(currentBody.getName()); - System.out.println("lowOrbitAltitude: " + lowOrbitAltitude); - } catch (RPCException e) { - } - } - - @Override - public void run() { - calculateManeuver(); - if (!(commands.get(Modulos.FUNCAO.get()).equals(Modulos.RENDEZVOUS.get()) - || commands.get(Modulos.FUNCAO.get()).equals(Modulos.ORBITA_BAIXA.get()) - || commands.get(Modulos.FUNCAO.get()).equals(Modulos.AJUSTAR.get()))) { - executeNextManeuver(); - } - } - - private Node biEllipticTransferToOrbit(double targetAltitude, double timeToStart) { - double[] totalDv = { 0, 0, 0 }; - try { - Orbit currentOrbit = getNaveAtual().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); - - // Calculate the final radius for the target orbit - double targetRadius = currentBody.getEquatorialRadius() + targetAltitude; - - // 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); - - // Total delta-v for the bi-elliptic transfer - totalDv[0] = deltaV1 + deltaV2 + deltaV3 + deltaV4; - } catch (RPCException e) { - // Handle the exception - } - return createManeuver(timeToStart, totalDv); - } - - public void calculateManeuver() { - try { - tuneAutoPilot(); - System.out.println(commands + " calculate maneuvers"); - if (commands.get(Modulos.FUNCAO.get()).equals(Modulos.EXECUTAR.get())) { - return; - } - if (getNaveAtual().getSituation() == VesselSituation.LANDED || - getNaveAtual().getSituation() == VesselSituation.SPLASHED) { - throw new InterruptedException(); - } - if (commands.get(Modulos.FUNCAO.get()).equals(Modulos.AJUSTAR.get())) { - this.alignPlanesWithTargetVessel(); - return; - } - if (commands.get(Modulos.FUNCAO.get()).equals(Modulos.RENDEZVOUS.get())) { - this.rendezvousWithTargetVessel(); - return; - } - if (commands.get(Modulos.FUNCAO.get()).equals(Modulos.ORBITA_BAIXA.get())) { - biEllipticTransferToOrbit(lowOrbitAltitude, getNaveAtual().getOrbit().getTimeToPeriapsis()); - return; - } - double gravParameter = currentBody.getGravitationalParameter(); - double altitudeInicial = 0, tempoAteAltitude = 0; - if (commands.get(Modulos.FUNCAO.get()).equals(Modulos.APOASTRO.get())) { - altitudeInicial = getNaveAtual().getOrbit().getApoapsis(); - tempoAteAltitude = getNaveAtual().getOrbit().getTimeToApoapsis(); - } - if (commands.get(Modulos.FUNCAO.get()).equals(Modulos.PERIASTRO.get())) { - altitudeInicial = getNaveAtual().getOrbit().getPeriapsis(); - tempoAteAltitude = getNaveAtual().getOrbit().getTimeToPeriapsis(); - } - - double semiEixoMaior = getNaveAtual().getOrbit().getSemiMajorAxis(); - double velOrbitalAtual = Math.sqrt(gravParameter * ((2.0 / altitudeInicial) - (1.0 / semiEixoMaior))); - double velOrbitalAlvo = Math.sqrt(gravParameter * ((2.0 / altitudeInicial) - (1.0 / altitudeInicial))); - double deltaVdaManobra = velOrbitalAlvo - velOrbitalAtual; - double[] deltaV = { deltaVdaManobra, 0, 0 }; - createManeuver(tempoAteAltitude, deltaV); - } catch (RPCException | InterruptedException e) { - setCurrentStatus(Bundle.getString("status_maneuver_not_possible")); - } - } - - public void matchOrbitApoapsis() { - try { - Orbit targetOrbit = getTargetOrbit(); - System.out.println(targetOrbit.getApoapsis() + "-- APO"); - Node maneuver = biEllipticTransferToOrbit(targetOrbit.getApoapsis(), - getNaveAtual().getOrbit().getTimeToPeriapsis()); - while (true) { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - 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"); - } - } - - 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) { - } - return createManeuver(uTatClosestNode, dv); - } - - private double[] getTimeToIncNodes(Orbit targetOrbit) throws RPCException { - Orbit vesselOrbit = getNaveAtual().getOrbit(); - double ascendingNode = vesselOrbit.trueAnomalyAtAN(targetOrbit); - double descendingNode = vesselOrbit.trueAnomalyAtDN(targetOrbit); - return new double[] { vesselOrbit.uTAtTrueAnomaly(ascendingNode), vesselOrbit.uTAtTrueAnomaly(descendingNode) }; - } - - private void alignPlanesWithTargetVessel() { - try { - Vessel vessel = getNaveAtual(); - Orbit vesselOrbit = getNaveAtual().getOrbit(); - Orbit targetVesselOrbit = getSpaceCenter().getTargetVessel().getOrbit(); - boolean hasManeuverNodes = vessel.getControl().getNodes().size() > 0; - System.out.println("hasManeuverNodes: " + hasManeuverNodes); - if (!hasManeuverNodes) { - RunManeuverJPanel.createManeuver(); - } - 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); - } - } catch (Exception err) { - System.err.println(err); - } - } - - private void rendezvousWithTargetVessel() { - try { - boolean hasManeuverNodes = getNaveAtual().getControl().getNodes().size() > 0; - List currentManeuvers = getNaveAtual().getControl().getNodes(); - Node lastManeuverNode; - double lastManeuverNodeUT = 60; - if (hasManeuverNodes) { - currentManeuvers = getNaveAtual().getControl().getNodes(); - lastManeuverNode = currentManeuvers.get(currentManeuvers.size() - 1); - lastManeuverNodeUT += lastManeuverNode.getUT(); - RunManeuverJPanel.createManeuver(lastManeuverNodeUT); - } else { - RunManeuverJPanel.createManeuver(); - } - currentManeuvers = getNaveAtual().getControl().getNodes(); - lastManeuverNode = currentManeuvers.get(currentManeuvers.size() - 1); - - Orbit activeVesselOrbit = getNaveAtual().getOrbit(); - Orbit targetVesselOrbit = getSpaceCenter().getTargetVessel().getOrbit(); - ReferenceFrame currentBodyRefFrame = activeVesselOrbit.getBody().getNonRotatingReferenceFrame(); - - double angularDiff = 10; - while (angularDiff >= 0.005) { - double maneuverUT = lastManeuverNode.getUT(); - double targetOrbitPosition = new Vector( - targetVesselOrbit.positionAt(maneuverUT, currentBodyRefFrame)) - .magnitude(); - double maneuverAP = lastManeuverNode.getOrbit().getApoapsis(); - double maneuverPE = lastManeuverNode.getOrbit().getPeriapsis(); - ctrlManeuver.setPIDValues(0.25, 0.0, 0.01); - ctrlManeuver.setOutput(-100, 100); - - if (targetOrbitPosition < maneuverPE) { - while (Math.floor(targetOrbitPosition) != Math.floor(maneuverPE)) { - lastManeuverNode.setPrograde( - lastManeuverNode.getPrograde() - + ctrlManeuver.calculate(maneuverPE / targetOrbitPosition * 1000, 1000)); - maneuverPE = lastManeuverNode.getOrbit().getPeriapsis(); - Thread.sleep(25); - } - } - - 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); - } - // 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) { - } - } - - 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 Orbit getTargetOrbit() throws RPCException { - if (getSpaceCenter().getTargetBody() != null) { - return getSpaceCenter().getTargetBody().getOrbit(); - } - if (getSpaceCenter().getTargetVessel() != null) { - return getSpaceCenter().getTargetVessel().getOrbit(); - } - return null; - } - - private Node createManeuver(double laterTime, double[] deltaV) { - Node maneuverNode = null; - try { - getNaveAtual().getControl() - .addNode(getSpaceCenter().getUT() + laterTime, (float) deltaV[0], (float) deltaV[1], - (float) deltaV[2]); - List currentNodes = getNaveAtual().getControl().getNodes(); - maneuverNode = currentNodes.get(currentNodes.size() - 1); - } catch (UnsupportedOperationException | RPCException e) { - setCurrentStatus(Bundle.getString("status_maneuver_not_possible")); - } - return maneuverNode; - } - - public void executeNextManeuver() { - try { - Node maneuverNode = getNaveAtual().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")); - } - } - - 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); - } - - } - - public double calculateBurnTime(Node noDeManobra) throws RPCException { - - List motores = getNaveAtual().getParts().getEngines(); - for (Engine motor : motores) { - if (motor.getPart().getStage() == getNaveAtual().getControl().getCurrentStage() && !motor.getActive()) { - motor.setActive(true); - } - } - double empuxo = getNaveAtual().getAvailableThrust(); - double isp = getNaveAtual().getSpecificImpulse() * CONST_GRAV; - double massaTotal = getNaveAtual().getMass(); - double massaSeca = massaTotal / Math.exp(noDeManobra.getDeltaV() / isp); - double taxaDeQueima = empuxo / isp; - double duracaoDaQueima = (massaTotal - massaSeca) / taxaDeQueima; - - setCurrentStatus("Tempo de Queima da Manobra: " + duracaoDaQueima + " segundos"); - return duracaoDaQueima; - } - - public void executeBurn(Node noDeManobra, double duracaoDaQueima) { - try { - double inicioDaQueima = noDeManobra.getTimeTo() - (duracaoDaQueima / 2.0) - (fineAdjustment ? 5 : 0); - setCurrentStatus(Bundle.getString("status_maneuver_warp")); - if (inicioDaQueima > 30) { - getSpaceCenter().warpTo((getSpaceCenter().getUT() + inicioDaQueima - 10), 100000, 4); - } - // Mostrar tempo de ignição: - setCurrentStatus(String.format(Bundle.getString("status_maneuver_duration"), duracaoDaQueima)); - while (inicioDaQueima > 0) { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - inicioDaQueima = Math.max(noDeManobra.getTimeTo() - (duracaoDaQueima / 2.0), 0.0); - navigation.aimAtManeuver(noDeManobra); - setCurrentStatus(String.format(Bundle.getString("status_maneuver_ignition_in"), inicioDaQueima)); - Thread.sleep(100); - } - // Executar a manobra: - Stream> remainingBurn = getConnection().addStream(noDeManobra, - "remainingBurnVector", noDeManobra.getReferenceFrame()); - setCurrentStatus(Bundle.getString("status_maneuver_executing")); - while (noDeManobra != null) { - double burnDvLeft = remainingBurn.get().getValue1(); - if (Thread.interrupted()) { - throw new InterruptedException(); - } - if (burnDvLeft < (fineAdjustment ? 2 : 0.5)) { - throttle(0.0f); - break; - } - navigation.aimAtManeuver(noDeManobra); - float limitValue = burnDvLeft > 100 ? 1000 : 100; - throttle(ctrlManeuver.calculate((noDeManobra.getDeltaV() - Math.floor(burnDvLeft)) / - noDeManobra.getDeltaV() * limitValue, limitValue)); - Thread.sleep(25); - } - throttle(0.0f); - if (fineAdjustment) { - adjustManeuverWithRCS(remainingBurn); - } - ap.setReferenceFrame(surfaceReferenceFrame); - ap.disengage(); - getNaveAtual().getControl().setSAS(true); - getNaveAtual().getControl().setRCS(false); - remainingBurn.remove(); - noDeManobra.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")); - } - } - - private void adjustManeuverWithRCS(Stream> remainingDeltaV) throws RPCException, - StreamException, InterruptedException { - getNaveAtual().getControl().setRCS(true); - while (Math.floor(remainingDeltaV.get().getValue1()) > 0.2) { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - getNaveAtual().getControl().setForward((float) ctrlRCS.calculate(-remainingDeltaV.get().getValue1() * 10, - 0)); - Thread.sleep(25); - } - getNaveAtual().getControl().setForward(0); - } - - private boolean canFineAdjust(String string) { - if (string.equals("true")) { - try { - List rcsEngines = getNaveAtual().getParts().getRCS(); - if (rcsEngines.size() > 0) { - for (RCS rcs : rcsEngines) { - if (rcs.getHasFuel()) { - return true; - } - } - } - return false; - } catch (RPCException ignored) { - } - } - return false; - } - - private double calculatePhaseAngle(Triplet startPos, Triplet endPos) - throws RPCException, InterruptedException { - double targetPhaseAngle = 10; - double angularDifference = 15; - Vector startPosition = new Vector(startPos); - Vector endPosition = new Vector(endPos); - - // Phase angle - double dot = endPosition.dotProduct(startPosition); - double det = endPosition.determinant(startPosition); - targetPhaseAngle = Math.atan2(det, dot); - - double targetOrbit = endPosition.magnitude(); - - double activeVesselSMA = getNaveAtual().getOrbit().getSemiMajorAxis(); - angularDifference = targetPhaseAngle + Math.PI - * (1 - (1 / (2 * Math.sqrt(2))) * Math.sqrt(Math.pow((activeVesselSMA / targetOrbit + 1), 3))); - - return Math.abs(angularDifference); - } - - enum Compare { - INC, AP, PE - } + 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(); + } + + 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) { + } + } + + @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(); + } + } + + 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); + + // Calculate the final radius for the target orbit + double targetRadius = currentBody.getEquatorialRadius() + targetAltitude; + + // 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); + + // Total delta-v for the bi-elliptic transfer + totalDv[0] = deltaV1 + deltaV2 + deltaV3 + deltaV4; + } catch (RPCException e) { + // Handle the exception + } + return createManeuver(timeToStart, totalDv); + } + + 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(); + } + + 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")); + } + } + + 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(); + } + 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"); + } + } + + 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) { + } + return createManeuver(uTatClosestNode, dv); + } + + 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)}; + } + + 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(); + } + 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); + } + } catch (Exception err) { + System.err.println(err); + } + } + + 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); + } + } + + 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); + } + // 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) { + } + } + + 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 Orbit getTargetOrbit() throws RPCException { + if (getSpaceCenter().getTargetBody() != null) { + return getSpaceCenter().getTargetBody().getOrbit(); + } + if (getSpaceCenter().getTargetVessel() != null) { + return getSpaceCenter().getTargetVessel().getOrbit(); + } + return null; + } + + 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; + } + + 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")); + } + } + + 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); + } + + } + + 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); + } + } + 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; + } + + 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")); + } + } + + 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); + } + getActiveVessel().getControl().setForward(0); + } + + 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; + } + } + } + return false; + } catch (RPCException ignored) { + } + } + return false; + } + + private double calculatePhaseAngle(Triplet startPos, Triplet endPos) + throws RPCException, InterruptedException { + double targetPhaseAngle = 10; + double angularDifference = 15; + Vector startPosition = new Vector(startPos); + Vector endPosition = new Vector(endPos); + + // Phase angle + double dot = endPosition.dotProduct(startPosition); + double det = endPosition.determinant(startPosition); + targetPhaseAngle = Math.atan2(det, dot); + + double targetOrbit = endPosition.magnitude(); + + double activeVesselSMA = 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 + } } diff --git a/src/main/java/com/pesterenan/controllers/RoverController.java b/src/main/java/com/pesterenan/controllers/RoverController.java index aeab195..64ad213 100644 --- a/src/main/java/com/pesterenan/controllers/RoverController.java +++ b/src/main/java/com/pesterenan/controllers/RoverController.java @@ -2,7 +2,7 @@ import com.pesterenan.resources.Bundle; import com.pesterenan.utils.ControlePID; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import com.pesterenan.utils.PathFinding; import com.pesterenan.utils.Utilities; import com.pesterenan.utils.Vector; @@ -22,296 +22,283 @@ 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 void initializeParameters() { - try { - maxSpeed = Float.parseFloat(commands.get(Modulos.VELOCIDADE_MAX.get())); - roverReferenceFrame = getNaveAtual().getReferenceFrame(); - roverDirection = new Vector(getNaveAtual().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; - } - } - - @Override - public void run() { - if (commands.get(Modulos.MODULO.get()).equals(Modulos.MODULO_ROVER.get())) { - setTarget(); - driveRoverToTarget(); - } - } - - private void setTarget() { - try { - if (commands.get(Modulos.TIPO_ALVO_ROVER.get()).equals(Modulos.MARCADOR_MAPA.get())) { - pathFinding.addWaypointsOnSameBody(commands.get(Modulos.NOME_MARCADOR.get())); - setCurrentStatus("Calculando rota até o alvo..."); - pathFinding.buildPathToTarget(pathFinding.findNearestWaypoint()); - } - if (commands.get(Modulos.TIPO_ALVO_ROVER.get()).equals(Modulos.NAVE_ALVO.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; - } - } - - private void driveRoverToTarget() { - 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 { - getNaveAtual().getControl().setBrakes(true); - pathFinding.removeDrawnPath(); - isAutoRoverRunning = false; - setCurrentStatus(Bundle.getString("lbl_stat_ready")); - } catch (RPCException ignored2) { - } - } - } - - private void setNextPointInPath() throws RPCException, IOException, InterruptedException { - pathFinding.removePathsCurrentPoint(); - getNaveAtual().getControl().setBrakes(true); - if (pathFinding.isPathToTargetEmpty()) { - if (commands.get(Modulos.TIPO_ALVO_ROVER.get()).equals(Modulos.MARCADOR_MAPA.get())) { - pathFinding.removeWaypointFromList(); - if (pathFinding.isWaypointsToReachEmpty()) { - throw new InterruptedException(); - } - pathFinding.buildPathToTarget(pathFinding.findNearestWaypoint()); - } - - } else { - targetPoint = pathFinding.getPathsFirstPoint(); - } - } - - private boolean isFarFromTarget() throws RPCException { - double distance = Vector.distance(new Vector(getNaveAtual().position(orbitalReferenceFrame)), targetPoint); - return distance > distanceFromTargetLimit; - } - - private boolean needToChargeBatteries() throws RPCException, IOException, StreamException, InterruptedException { - float totalCharge = getNaveAtual().getResources().max("ElectricCharge"); - float currentCharge = getNaveAtual().getResources().amount("ElectricCharge"); - float minChargeLevel = 10.0f; - float chargePercentage = (float) Math.ceil(currentCharge * 100 / totalCharge); - return (chargePercentage < minChargeLevel); - } - - private void rechargeRover() throws RPCException, StreamException, InterruptedException { - - float totalCharge = getNaveAtual().getResources().max("ElectricCharge"); - float currentCharge = getNaveAtual().getResources().amount("ElectricCharge"); - - setRoverThrottle(0); - getNaveAtual().getControl().setLights(false); - getNaveAtual().getControl().setBrakes(true); - - if (velHorizontal.get() < 1 && getNaveAtual().getControl().getBrakes()) { - Thread.sleep(1000); - double chargeTime; - double totalEnergyFlow = 0; - List solarPanels = getNaveAtual().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); - getNaveAtual().getControl().setLights(true); - } - } - - private void driveRover() throws RPCException, IOException, StreamException { - Vector targetDirection = posSurfToRover(posOrbToSurf(targetPoint)).normalize(); - Vector radarSourcePosition = posRoverToSurf( - new Vector(getNaveAtual().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( - getNaveAtual().boundingBox(roverReferenceFrame))) - .normalize()).heading(); - double deltaAngle = Math.abs(targetAndRadarAngle - roverAngle); - getNaveAtual().getControl().setSAS(deltaAngle < 1); - // Control Rover Throttle - setRoverThrottle(acelCtrl.calculate(velHorizontal.get() / maxSpeed * 50, 50)); - // Control Rover Steering - if (deltaAngle > 1) { - setRoverSteering(sterringCtrl.calculate(roverAngle / (targetAndRadarAngle) * 100, 100)); - } else { - setRoverSteering(0.0f); - } - 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 lateralEsq = new Vector(LBU.x, LBU.y * 0.5 + RFD.y * 0.5, LBU.z * 0.5 + RFD.z * 0.5); - Vector latFrontEsq = new Vector(LBU.x, RFD.y * 0.5, LBU.z * 0.5 + RFD.z * 0.5); - Vector frontalEsq = new Vector(LBU.x, RFD.y, LBU.z * 0.5 + RFD.z * 0.5); - Vector frontalEsq2 = new Vector(LBU.x * 0.5, RFD.y, LBU.z * 0.5 + RFD.z * 0.5); - Vector frontal = new Vector(LBU.x * 0.5 + RFD.x * 0.5, RFD.y, LBU.z * 0.5 + RFD.z * 0.5); - Vector frontalDir2 = new Vector(RFD.x * 0.5, RFD.y, LBU.z * 0.5 + RFD.z * 0.5); - Vector frontalDir = new Vector(RFD.x, RFD.y, LBU.z * 0.5 + RFD.z * 0.5); - Vector latFrontDir = new Vector(RFD.x, RFD.y * 0.5, LBU.z * 0.5 + RFD.z * 0.5); - Vector lateralDir = 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 lateralEsqAngulo = new Vector(-Math.sin(Math.toRadians(90)), Math.cos(Math.toRadians(90)), 0.0); - Vector latFrontEsqAngulo = new Vector(-Math.sin(Math.toRadians(67.5)), Math.cos(Math.toRadians(67.5)), 0.0); - Vector frontalEsqAngulo = new Vector(-Math.sin(Math.toRadians(45)), Math.cos(Math.toRadians(45)), 0.0); - Vector frontalEsqAngulo2 = new Vector(-Math.sin(Math.toRadians(22.5)), Math.cos(Math.toRadians(22.5)), 0.0); - Vector frontalAngulo = new Vector(0.0, 1.0, 0.0); - Vector frontalDirAngulo2 = new Vector(Math.sin(Math.toRadians(22.5)), Math.cos(Math.toRadians(22.5)), 0.0); - Vector frontalDirAngulo = new Vector(Math.sin(Math.toRadians(45)), Math.cos(Math.toRadians(45)), 0.0); - Vector latFrontDirAngulo = new Vector(Math.sin(Math.toRadians(67.5)), Math.cos(Math.toRadians(67.5)), 0.0); - Vector lateralDirAngulo = new Vector(Math.sin(Math.toRadians(90)), Math.cos(Math.toRadians(90)), 0.0); - - // Raytracing distance from points: - Vector lateralEsqRay = calculateRaycastDirection(lateralEsq, lateralEsqAngulo, 15); - Vector latFrontEsqRay = calculateRaycastDirection(latFrontEsq, latFrontEsqAngulo, 19); - Vector frontalEsqRay = calculateRaycastDirection(frontalEsq, frontalEsqAngulo, 23); - Vector frontalEsqRay2 = calculateRaycastDirection(frontalEsq2, frontalEsqAngulo2, 27); - Vector frontalRay = calculateRaycastDirection(frontal, frontalAngulo, 35); - Vector frontalDirRay2 = calculateRaycastDirection(frontalDir2, frontalDirAngulo2, 27); - Vector frontalDirRay = calculateRaycastDirection(frontalDir, frontalDirAngulo, 23); - Vector latFrontDirRay = calculateRaycastDirection(latFrontDir, latFrontDirAngulo, 19); - Vector lateralDirRay = calculateRaycastDirection(lateralDir, lateralDirAngulo, 15); - - Vector calculatedDirection = new Vector().sum(lateralEsqRay) - .sum(latFrontEsqRay) - .sum(frontalEsqRay) - .sum(frontalEsqRay2) - .sum(frontalRay) - .sum(frontalDirRay2) - .sum(frontalDirRay) - .sum(latFrontDirRay) - .sum(lateralDirRay); - - return (calculatedDirection.normalize()); - } - - 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 Vector posOrbToSurf(Vector vector) throws RPCException { - return new Vector( - getSpaceCenter().transformPosition(vector.toTriplet(), orbitalReferenceFrame, surfaceReferenceFrame)); - } - - private void setRoverThrottle(double throttle) throws RPCException, StreamException { - if (velHorizontal.get() < (maxSpeed * 1.01)) { - getNaveAtual().getControl().setBrakes(false); - getNaveAtual().getControl().setWheelThrottle((float) throttle); - } else { - getNaveAtual().getControl().setBrakes(true); - } - } - - private void setRoverSteering(double steering) throws RPCException { - getNaveAtual().getControl().setWheelSteering((float) steering); - } - - private enum MODE { - DRIVE, NEXT_POINT, CHARGING - } + 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 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; + } + } + + @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; + } + } + + private void driveRoverToTarget() { + 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) { + } + } + } + + 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 boolean isFarFromTarget() throws RPCException { + double distance = Vector.distance(new Vector(getActiveVessel().position(orbitalReferenceFrame)), targetPoint); + return distance > distanceFromTargetLimit; + } + + 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 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 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); + } + 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), + 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 Vector posOrbToSurf(Vector vector) throws RPCException { + return new Vector( + getSpaceCenter().transformPosition(vector.toTriplet(), orbitalReferenceFrame, surfaceReferenceFrame)); + } + + 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); + } + } + + private void setRoverSteering(double steering) throws RPCException { + getActiveVessel().getControl().setWheelSteering((float) steering); + } + + 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 99efa65..849d94f 100644 --- a/src/main/java/com/pesterenan/model/ActiveVessel.java +++ b/src/main/java/com/pesterenan/model/ActiveVessel.java @@ -8,7 +8,7 @@ import com.pesterenan.controllers.RoverController; import com.pesterenan.controllers.DockingController; import com.pesterenan.resources.Bundle; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import com.pesterenan.utils.Telemetry; import com.pesterenan.utils.Vector; import krpc.client.RPCException; @@ -29,211 +29,210 @@ public class ActiveVessel { - protected Vessel naveAtual; - private final Map telemetryData = new HashMap<>(); - public AutoPilot ap; - public Flight parametrosDeVoo; - public ReferenceFrame orbitalReferenceFrame; - protected Stream massaTotal; - public ReferenceFrame surfaceReferenceFrame; - public float bateriaTotal; - public float gravityAcel; - public CelestialBody currentBody; - public Stream altitude; - public Stream altitudeSup; - public Stream apoastro; - public Stream periastro; - public Stream velVertical; - public Stream tempoMissao; - public Stream velHorizontal; - 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(); - } - - private void initializeParameters() { - try { - setNaveAtual(getSpaceCenter().getActiveVessel()); - currentVesselId = getNaveAtual().hashCode(); - ap = getNaveAtual().getAutoPilot(); - currentBody = getNaveAtual().getOrbit().getBody(); - gravityAcel = currentBody.getSurfaceGravity(); - orbitalReferenceFrame = currentBody.getReferenceFrame(); - surfaceReferenceFrame = getNaveAtual().getSurfaceReferenceFrame(); - parametrosDeVoo = getNaveAtual().flight(orbitalReferenceFrame); - massaTotal = getConnection().addStream(getNaveAtual(), "getMass"); - altitude = getConnection().addStream(parametrosDeVoo, "getMeanAltitude"); - altitudeSup = getConnection().addStream(parametrosDeVoo, "getSurfaceAltitude"); - apoastro = getConnection().addStream(getNaveAtual().getOrbit(), "getApoapsisAltitude"); - periastro = getConnection().addStream(getNaveAtual().getOrbit(), "getPeriapsisAltitude"); - velVertical = getConnection().addStream(parametrosDeVoo, "getVerticalSpeed"); - velHorizontal = getConnection().addStream(parametrosDeVoo, "getHorizontalSpeed"); - } catch (RPCException | StreamException e) { - MechPeste.newInstance().checkConnection(); - } - } - - public String getCurrentStatus() { - if (controller != null) { - return controller.getCurrentStatus(); - } - return currentStatus; - } - - public void setCurrentStatus(String status) { - currentStatus = status; - } - - public int getCurrentVesselId() { - return currentVesselId; - } - - public Vessel getNaveAtual() { - return naveAtual; - } - - public void setNaveAtual(Vessel currentVessel) { - naveAtual = currentVessel; - } - - public void throttle(float acel) throws RPCException { - getNaveAtual().getControl().setThrottle(Math.min(acel, 1.0f)); - } - - 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 liftoff() { - try { - getNaveAtual().getControl().setSAS(true); - throttleUp(getMaxThrottleForTWR(2.0), 1); - if (getNaveAtual().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(naveAtual); - getNaveAtual().getControl().activateNextStage(); - } - setCurrentStatus(Bundle.getString("status_liftoff")); - } catch (RPCException | InterruptedException | StreamException ignored) { - setCurrentStatus(Bundle.getString("status_liftoff_abort")); - } - } - - protected void decoupleStage() throws RPCException, InterruptedException { - setCurrentStatus(Bundle.getString("status_separating_stage")); - MechPeste.getSpaceCenter().setActiveVessel(getNaveAtual()); - double currentThrottle = getNaveAtual().getControl().getThrottle(); - throttle(0); - Thread.sleep(1000); - getNaveAtual().getControl().activateNextStage(); - throttleUp(currentThrottle, 1); - } - - 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 getNaveAtual().getAvailableThrust() / (massaTotal.get() * gravityAcel); - } - - 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 void startModule(Map commands) { - String currentFunction = commands.get(Modulos.MODULO.get()); - if (controllerThread != null) { - controllerThread.interrupt(); - runningModule = false; - } - if (currentFunction.equals(Modulos.MODULO_DECOLAGEM.get())) { - controller = new LiftoffController(commands); - runningModule = true; - } - if (currentFunction.equals(Modulos.MODULO_POUSO_SOBREVOAR.get()) || - currentFunction.equals(Modulos.MODULO_POUSO.get())) { - controller = new LandingController(commands); - runningModule = true; - } - if (currentFunction.equals(Modulos.MODULE_MANEUVER.get())) { - controller = new ManeuverController(commands); - runningModule = true; - } - if (currentFunction.equals(Modulos.MODULO_ROVER.get())) { - controller = new RoverController(commands); - runningModule = true; - } - if (currentFunction.equals(Modulos.MODULO_DOCKING.get())) { - controller = new DockingController(commands); - System.out.println("escolheu modulo docking"); - runningModule = true; - } - controllerThread = new Thread(controller, currentVesselId + " - " + currentFunction); - controllerThread.start(); - } - - public void recordTelemetryData() throws RPCException { - if (getNaveAtual().getOrbit().getBody() != currentBody) { - initializeParameters(); - } - synchronized (telemetryData) { - try { - telemetryData.put(Telemetry.ALTITUDE, altitude.get() < 0 ? 0 : altitude.get()); - telemetryData.put(Telemetry.ALT_SURF, altitudeSup.get() < 0 ? 0 : altitudeSup.get()); - telemetryData.put(Telemetry.APOAPSIS, apoastro.get() < 0 ? 0 : apoastro.get()); - telemetryData.put(Telemetry.PERIAPSIS, periastro.get() < 0 ? 0 : periastro.get()); - telemetryData.put(Telemetry.VERT_SPEED, velVertical.get()); - telemetryData.put(Telemetry.HORZ_SPEED, velHorizontal.get() < 0 ? 0 : velHorizontal.get()); - } catch (RPCException | StreamException ignored) { - } - } - } - - public Map getTelemetryData() { - return telemetryData; - } - - public void cancelControl() { - try { - ap.disengage(); - throttle(0); - if (controllerThread != null) { - controllerThread.interrupt(); - runningModule = false; - } - } catch (RPCException ignored) { - } - } - - public boolean hasModuleRunning() { - return runningModule; - } + 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(); + } + + 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 String getCurrentStatus() { + if (controller != null) { + return controller.getCurrentStatus(); + } + return currentStatus; + } + + public void setCurrentStatus(String status) { + currentStatus = status; + } + + public int getCurrentVesselId() { + return currentVesselId; + } + + public Vessel getActiveVessel() { + return activeVessel; + } + + 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(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 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")); + } + } + + 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); + getActiveVessel().getControl().activateNextStage(); + throttleUp(currentThrottle, 1); + } + + 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 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 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(); + } + + 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 Map getTelemetryData() { + return telemetryData; + } + + public void cancelControl() { + try { + ap.disengage(); + throttle(0); + if (controllerThread != null) { + controllerThread.interrupt(); + runningModule = false; + } + } catch (RPCException ignored) { + } + } + + public boolean hasModuleRunning() { + return runningModule; + } } diff --git a/src/main/java/com/pesterenan/resources/Bundle.java b/src/main/java/com/pesterenan/resources/Bundle.java index 3523229..1d4e53b 100644 --- a/src/main/java/com/pesterenan/resources/Bundle.java +++ b/src/main/java/com/pesterenan/resources/Bundle.java @@ -5,17 +5,17 @@ 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 76e835f..f7ca60b 100644 --- a/src/main/java/com/pesterenan/updater/KrpcInstaller.java +++ b/src/main/java/com/pesterenan/updater/KrpcInstaller.java @@ -15,79 +15,76 @@ 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.2/krpc-0.5.2.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.2.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.2.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 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"); + } + } } diff --git a/src/main/java/com/pesterenan/utils/Attributes.java b/src/main/java/com/pesterenan/utils/Attributes.java index 1046b85..51174d8 100644 --- a/src/main/java/com/pesterenan/utils/Attributes.java +++ b/src/main/java/com/pesterenan/utils/Attributes.java @@ -5,7 +5,7 @@ public class Attributes { - private static Map safeLowOrbitAltitudes = new HashMap(); + private static Map safeLowOrbitAltitudes = new HashMap(); public Attributes() { safeLowOrbitAltitudes.put("Bop", 10_000.0); diff --git a/src/main/java/com/pesterenan/utils/ControlePID.java b/src/main/java/com/pesterenan/utils/ControlePID.java index 51ea12f..1fce344 100644 --- a/src/main/java/com/pesterenan/utils/ControlePID.java +++ b/src/main/java/com/pesterenan/utils/ControlePID.java @@ -4,101 +4,101 @@ 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() { - } - - public ControlePID(SpaceCenter spaceCenter, double timeSample) { - this.spaceCenter = spaceCenter; - setTimeSample(timeSample); - } - - public ControlePID(double kp, double ki, double kd, double outputMin, double outputMax) { - this.kp = kp; - this.ki = ki; - this.kd = kd; - this.outputMin = outputMin; - this.outputMax = outputMax; - } - - public void reset() { - this.previousError = 0; - this.previousMeasurement = 0; - this.proportionalTerm = 0; - this.integralTerm = 0; - this.derivativeTerm = 0; - } - - public double 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); - } - - private double limitOutput(double value) { - return Utilities.clamp(value, outputMin, outputMax); - } - - public void setOutput(double min, double max) { - if (min > max) { - return; - } - outputMin = min; - outputMax = max; - integralTerm = limitOutput(integralTerm); - } - - 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(); - } - } + 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() { + } + + public ControlePID(SpaceCenter spaceCenter, double timeSample) { + this.spaceCenter = spaceCenter; + setTimeSample(timeSample); + } + + public ControlePID(double kp, double ki, double kd, double outputMin, double outputMax) { + this.kp = kp; + this.ki = ki; + this.kd = kd; + this.outputMin = outputMin; + this.outputMax = outputMax; + } + + public void reset() { + this.previousError = 0; + this.previousMeasurement = 0; + this.proportionalTerm = 0; + this.integralTerm = 0; + this.derivativeTerm = 0; + } + + public double 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); + } + + private double limitOutput(double value) { + return Utilities.clamp(value, outputMin, outputMax); + } + + public void setOutput(double min, double max) { + if (min > max) { + return; + } + outputMin = min; + outputMax = max; + integralTerm = limitOutput(integralTerm); + } + + 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(); + } + } } diff --git a/src/main/java/com/pesterenan/utils/Module.java b/src/main/java/com/pesterenan/utils/Module.java new file mode 100644 index 0000000..2a6b5cd --- /dev/null +++ b/src/main/java/com/pesterenan/utils/Module.java @@ -0,0 +1,37 @@ +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"); + + final String t; + + Module(String t) { + this.t = t; + } + + public String get() { + return this.t; + } +} diff --git a/src/main/java/com/pesterenan/utils/Modulos.java b/src/main/java/com/pesterenan/utils/Modulos.java deleted file mode 100644 index d583171..0000000 --- a/src/main/java/com/pesterenan/utils/Modulos.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.pesterenan.utils; - -public enum Modulos { - - ABRIR_PAINEIS("Abrir Painéis"), - AJUSTAR("Ajustar"), - AJUSTE_FINO("Ajuste Fino"), - ALTITUDE_SOBREVOO("Altitude Sobrevoo"), - APOASTRO("Apoastro"), - CIRCULAR("Circular"), - CUBICA("Cúbica"), - DIRECAO("Direção"), - DISTANCIA_SEGURA("Distância Segura"), - EXECUTAR("Executar"), - EXPONENCIAL("Exponencial"), - FUNCAO("Função"), - INCLINACAO("Inclinação"), - MARCADOR_MAPA("Marcador no mapa"), - MAX_TWR("Max_TWR"), - MODULE_MANEUVER("MANEUVER"), - MODULO("Módulo"), - MODULO_CRIAR_MANOBRAS("CRIAR_MANOBRAS"), - MODULO_DECOLAGEM("LIFTOFF"), - MODULO_DOCKING("DOCKING"), - MODULO_POUSO("LANDING"), - MODULO_POUSO_SOBREVOAR("HOVER"), - MODULO_ROVER("ROVER"), - MODULO_TELEMETRIA("TELEMETRY"), - NAVE_ALVO("Nave alvo"), - NOME_MARCADOR("Nome do marcador"), - ORBITA_BAIXA("ÓRBITA BAIXA"), - PERIASTRO("Periastro"), - POUSAR("Pousar nave"), - QUADRATICA("Quadrática"), - RENDEZVOUS("Rendezvous"), - ROLAGEM("Rolagem"), - SINUSOIDAL("Sinusoidal"), - SOBREVOO_POS_POUSO("SOBREVOO PÓS POUSO"), - TIPO_ALVO_ROVER("Tipo de Alvo do Rover"), - USAR_ESTAGIOS("Usar Estágios"), - VELOCIDADE_MAX("Velocidade Máxima"); - - final String t; - - Modulos(String t) { - this.t = 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 389b33e..9e8792d 100644 --- a/src/main/java/com/pesterenan/utils/Navigation.java +++ b/src/main/java/com/pesterenan/utils/Navigation.java @@ -11,148 +11,144 @@ 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 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 Navigation(Vessel currentVessel) { + this.currentVessel = currentVessel; + initializeParameters(); + } - 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) { - } - } + 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 void aimAtManeuver(Node maneuver) throws RPCException { - aimAtDirection(getSpaceCenter().transformDirection(PROGRADE, maneuver.getReferenceFrame(), orbitalReference)); - } + public void aimAtManeuver(Node maneuver) throws RPCException { + aimAtDirection(getSpaceCenter().transformDirection(PROGRADE, maneuver.getReferenceFrame(), orbitalReference)); + } - 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 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 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 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)); - } + public void aimAtPrograde() throws RPCException { + aimAtDirection(getSpaceCenter().transformDirection(PROGRADE, currentVessel.getSurfaceVelocityReferenceFrame(), + orbitalReference)); + } - public void aimAtRadialOut() throws RPCException { - aimAtDirection(getSpaceCenter().transformDirection(RADIAL, currentVessel.getSurfaceReferenceFrame(), - orbitalReference)); - } + public void aimAtRadialOut() throws RPCException { + aimAtDirection(getSpaceCenter().transformDirection(RADIAL, currentVessel.getSurfaceReferenceFrame(), + orbitalReference)); + } - public void aimAtRetrograde() throws RPCException { - aimAtDirection(getSpaceCenter().transformDirection(RETROGRADE, - currentVessel.getSurfaceVelocityReferenceFrame(), - orbitalReference)); - } + public void aimAtRetrograde() throws RPCException { + aimAtDirection(getSpaceCenter().transformDirection(RETROGRADE, currentVessel.getSurfaceVelocityReferenceFrame(), + orbitalReference)); + } - public void aimAtDirection(Triplet currentDirection) throws RPCException { - currentVessel.getAutoPilot().setReferenceFrame(orbitalReference); - currentVessel.getAutoPilot().setTargetDirection(currentDirection); - } + public void aimAtDirection(Triplet currentDirection) throws RPCException { + currentVessel.getAutoPilot().setReferenceFrame(orbitalReference); + currentVessel.getAutoPilot().setTargetDirection(currentDirection); + } } diff --git a/src/main/java/com/pesterenan/utils/PathFinding.java b/src/main/java/com/pesterenan/utils/PathFinding.java index f5848e0..f55510f 100644 --- a/src/main/java/com/pesterenan/utils/PathFinding.java +++ b/src/main/java/com/pesterenan/utils/PathFinding.java @@ -20,193 +20,197 @@ public class PathFinding extends Controller { - private WaypointManager waypointManager; - private String waypointName; - private List waypointsToReach; - private List pathToTarget; - private Drawing drawing; - private Drawing.Polygon polygonPath; - - public PathFinding() { - super(); - initializeParameters(); - } - - 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()); - } - - 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(getNaveAtual().position(orbitalReferenceFrame)), - waypointPosOnSurface(w1)); - w2Distance = Vector.distance(new Vector(getNaveAtual().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( - currentBody.surfacePosition(waypoint.getLatitude(), waypoint.getLongitude(), orbitalReferenceFrame)); - } - - 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 Vector getPathsFirstPoint() { - return pathToTarget.get(0); - } - - public void removePathsCurrentPoint() { - if (isPathToTargetEmpty()) { - return; - } - pathToTarget.remove(0); - } - - public void removeWaypointFromList() throws RPCException { - if (waypointsToReach.isEmpty()) { - return; - } - waypointsToReach.remove(0); - } - - /** - * 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(getNaveAtual().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()), 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) { - } - } - - 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); - } - - 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 transformSurfToOrb(Vector vector) throws IOException, RPCException { - return new Vector( - getSpaceCenter().transformPosition(vector.toTriplet(), surfaceReferenceFrame, orbitalReferenceFrame)); - } - - private Vector transformOrbToSurf(Vector vector) throws IOException, RPCException { - return new Vector( - getSpaceCenter().transformPosition(vector.toTriplet(), orbitalReferenceFrame, surfaceReferenceFrame)); - } + private WaypointManager waypointManager; + private String waypointName; + private List waypointsToReach; + private List pathToTarget; + private Drawing drawing; + private Drawing.Polygon polygonPath; + + public PathFinding() { + super(); + initializeParameters(); + } + + 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()); + } + + 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(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( + currentBody.surfacePosition(waypoint.getLatitude(), waypoint.getLongitude(), orbitalReferenceFrame)); + } + + 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 Vector getPathsFirstPoint() { + return pathToTarget.get(0); + } + + public void removePathsCurrentPoint() { + if (isPathToTargetEmpty()) { + return; + } + pathToTarget.remove(0); + } + + public void removeWaypointFromList() throws RPCException { + if (waypointsToReach.isEmpty()) { + return; + } + waypointsToReach.remove(0); + } + + /** + * 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()), 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) { + } + } + + 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); + } + + 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 transformSurfToOrb(Vector vector) throws IOException, RPCException { + return new Vector( + getSpaceCenter().transformPosition(vector.toTriplet(), surfaceReferenceFrame, orbitalReferenceFrame)); + } + + private Vector transformOrbToSurf(Vector vector) throws IOException, RPCException { + return new Vector( + getSpaceCenter().transformPosition(vector.toTriplet(), orbitalReferenceFrame, surfaceReferenceFrame)); + } } diff --git a/src/main/java/com/pesterenan/utils/Telemetry.java b/src/main/java/com/pesterenan/utils/Telemetry.java index 70ad005..ab46f77 100644 --- a/src/main/java/com/pesterenan/utils/Telemetry.java +++ b/src/main/java/com/pesterenan/utils/Telemetry.java @@ -1,10 +1,5 @@ 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 86bdccc..a310da6 100644 --- a/src/main/java/com/pesterenan/utils/Utilities.java +++ b/src/main/java/com/pesterenan/utils/Utilities.java @@ -4,80 +4,79 @@ 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 06c69e4..2919433 100644 --- a/src/main/java/com/pesterenan/utils/Vector.java +++ b/src/main/java/com/pesterenan/utils/Vector.java @@ -4,217 +4,234 @@ 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 a6084ca..728153b 100644 --- a/src/main/java/com/pesterenan/utils/VersionUtil.java +++ b/src/main/java/com/pesterenan/utils/VersionUtil.java @@ -16,10 +16,8 @@ public static String getVersion() { 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"))); + model = reader.read(new InputStreamReader( + VersionUtil.class.getResourceAsStream("/META-INF/maven/com.pesterenan/MechPeste/pom.xml"))); } version = model.getVersion(); return version; diff --git a/src/main/java/com/pesterenan/views/AboutJFrame.java b/src/main/java/com/pesterenan/views/AboutJFrame.java index e402033..e3a5919 100644 --- a/src/main/java/com/pesterenan/views/AboutJFrame.java +++ b/src/main/java/com/pesterenan/views/AboutJFrame.java @@ -17,67 +17,67 @@ 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, lblAboutInfo; + 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()); - 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"); + @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("MechPeste - por Pesterenan"); - 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); - lblAboutInfo.setAlignmentX(CENTER_ALIGNMENT); + // Setting-up components: + lblMechpeste.setFont(new Font("Trajan Pro", Font.BOLD, 18)); + lblMechpeste.setAlignmentX(CENTER_ALIGNMENT); + lblAboutInfo.setAlignmentX(CENTER_ALIGNMENT); - btnOk.addActionListener(e -> { - this.dispose(); - }); - btnOk.setPreferredSize(BTN_DIMENSION); - btnOk.setMaximumSize(BTN_DIMENSION); - btnOk.setAlignmentX(CENTER_ALIGNMENT); - } + btnOk.addActionListener(e -> { + this.dispose(); + }); + 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(lblAboutInfo); + pnlMain.add(Box.createVerticalGlue()); + pnlMain.add(btnOk); + pnlMain.add(createMarginComponent(10, 10)); - getContentPane().add(pnlMain); - setVisible(true); - } + getContentPane().add(pnlMain); + setVisible(true); + } } diff --git a/src/main/java/com/pesterenan/views/ChangeVesselDialog.java b/src/main/java/com/pesterenan/views/ChangeVesselDialog.java index 3702480..188801c 100644 --- a/src/main/java/com/pesterenan/views/ChangeVesselDialog.java +++ b/src/main/java/com/pesterenan/views/ChangeVesselDialog.java @@ -11,144 +11,143 @@ 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."); - } - - @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); - } + 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."); + } + + @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); + } } diff --git a/src/main/java/com/pesterenan/views/CreateManeuverJPanel.java b/src/main/java/com/pesterenan/views/CreateManeuverJPanel.java index 6c3a5ae..a47af7e 100644 --- a/src/main/java/com/pesterenan/views/CreateManeuverJPanel.java +++ b/src/main/java/com/pesterenan/views/CreateManeuverJPanel.java @@ -36,7 +36,7 @@ public class CreateManeuverJPanel extends JPanel implements ActionListener, UIMe private static int selectedManeuverIndex = 0; private static JRadioButton rbPrograde, rbNormal, rbRadial, rbTime; private static ButtonGroup bgManeuverType; - private static Map sliderValues = new HashMap<>(); + private static Map sliderValues = new HashMap<>(); private final ControlePID ctrlManeuver = new ControlePID(); public CreateManeuverJPanel() { @@ -344,18 +344,18 @@ private void positionManeuverAt(String node) { Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex); double timeToNode = 0; switch (node) { - case "apoapsis": + case "apoapsis" : timeToNode = MechPeste.getSpaceCenter().getUT() + orbit.getTimeToApoapsis(); break; - case "periapsis": + case "periapsis" : timeToNode = MechPeste.getSpaceCenter().getUT() + orbit.getTimeToPeriapsis(); break; - case "ascending": + case "ascending" : double ascendingAnomaly = orbit .trueAnomalyAtAN(MechPeste.getSpaceCenter().getTargetVessel().getOrbit()); timeToNode = orbit.uTAtTrueAnomaly(ascendingAnomaly); break; - case "descending": + case "descending" : double descendingAnomaly = orbit .trueAnomalyAtDN(MechPeste.getSpaceCenter().getTargetVessel().getOrbit()); timeToNode = orbit.uTAtTrueAnomaly(descendingAnomaly); @@ -379,16 +379,16 @@ private void changeManeuverDeltaV(String command) { currentSliderValue = command == "decrease" ? -currentSliderValue : currentSliderValue; switch (maneuverType) { - case "prograde": + case "prograde" : currentManeuver.setPrograde(currentManeuver.getPrograde() + currentSliderValue); break; - case "normal": + case "normal" : currentManeuver.setNormal(currentManeuver.getNormal() + currentSliderValue); break; - case "radial": + case "radial" : currentManeuver.setRadial(currentManeuver.getRadial() + currentSliderValue); break; - case "time": + case "time" : currentManeuver.setUT(currentManeuver.getUT() + currentSliderValue); break; } diff --git a/src/main/java/com/pesterenan/views/DockingJPanel.java b/src/main/java/com/pesterenan/views/DockingJPanel.java index 84fa835..151c929 100644 --- a/src/main/java/com/pesterenan/views/DockingJPanel.java +++ b/src/main/java/com/pesterenan/views/DockingJPanel.java @@ -2,7 +2,7 @@ import com.pesterenan.MechPeste; import com.pesterenan.resources.Bundle; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import javax.swing.*; import javax.swing.border.TitledBorder; @@ -17,140 +17,140 @@ 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 void handleStartDocking(ActionEvent e) { - if (validateTextFields()) { - Map commands = new HashMap<>(); - commands.put(Modulos.MODULO.get(), Modulos.MODULO_DOCKING.get()); - commands.put(Modulos.DISTANCIA_SEGURA.get(), txfSafeDistance.getText()); - commands.put(Modulos.VELOCIDADE_MAX.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 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 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; + } } diff --git a/src/main/java/com/pesterenan/views/FunctionsAndTelemetryJPanel.java b/src/main/java/com/pesterenan/views/FunctionsAndTelemetryJPanel.java index 5a6dc03..816b06a 100644 --- a/src/main/java/com/pesterenan/views/FunctionsAndTelemetryJPanel.java +++ b/src/main/java/com/pesterenan/views/FunctionsAndTelemetryJPanel.java @@ -2,7 +2,7 @@ import com.pesterenan.MechPeste; import com.pesterenan.resources.Bundle; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import com.pesterenan.utils.Telemetry; import com.pesterenan.utils.Utilities; @@ -18,180 +18,180 @@ 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(Modulos.MODULO_POUSO.get()); - btnLanding.setMaximumSize(btnFuncDimension); - btnLanding.setPreferredSize(btnFuncDimension); - btnLiftoff.addActionListener(this::changeFunctionPanel); - btnLiftoff.setActionCommand(Modulos.MODULO_DECOLAGEM.get()); - btnLiftoff.setMaximumSize(btnFuncDimension); - btnLiftoff.setPreferredSize(btnFuncDimension); - btnManeuvers.addActionListener(this::changeFunctionPanel); - btnManeuvers.setActionCommand(Modulos.MODULE_MANEUVER.get()); - btnManeuvers.setMaximumSize(btnFuncDimension); - btnManeuvers.setPreferredSize(btnFuncDimension); - btnRover.addActionListener(this::changeFunctionPanel); - btnRover.setActionCommand(Modulos.MODULO_ROVER.get()); - btnRover.setMaximumSize(btnFuncDimension); - btnRover.setPreferredSize(btnFuncDimension); - btnDocking.addActionListener(this::changeFunctionPanel); - btnDocking.setActionCommand(Modulos.MODULO_DOCKING.get()); - btnDocking.setMaximumSize(btnFuncDimension); - btnDocking.setPreferredSize(btnFuncDimension); - } - - @Override - 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 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; + } + } + } + } } diff --git a/src/main/java/com/pesterenan/views/InstallKrpcDialog.java b/src/main/java/com/pesterenan/views/InstallKrpcDialog.java index a9b0164..370cdfc 100644 --- a/src/main/java/com/pesterenan/views/InstallKrpcDialog.java +++ b/src/main/java/com/pesterenan/views/InstallKrpcDialog.java @@ -10,191 +10,136 @@ 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 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()); - }); - 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())); - 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); - } + 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, + 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()); + }); + 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())); + 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); + } } diff --git a/src/main/java/com/pesterenan/views/LandingJPanel.java b/src/main/java/com/pesterenan/views/LandingJPanel.java index ce315b1..a547286 100644 --- a/src/main/java/com/pesterenan/views/LandingJPanel.java +++ b/src/main/java/com/pesterenan/views/LandingJPanel.java @@ -2,7 +2,7 @@ import com.pesterenan.MechPeste; import com.pesterenan.resources.Bundle; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import javax.swing.*; import javax.swing.border.Border; @@ -18,153 +18,151 @@ import static com.pesterenan.views.MainGui.PNL_DIMENSION; 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(); - } - - @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(Modulos.MODULO_POUSO.get()); - btnAutoLanding.setPreferredSize(BTN_DIMENSION); - btnAutoLanding.setMaximumSize(BTN_DIMENSION); - btnHover.addActionListener(this::handleLandingAction); - btnHover.setActionCommand(Modulos.MODULO_POUSO_SOBREVOAR.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(Modulos.MODULO.get(), e.getActionCommand()); - validateTextFields(); - commands.put(Modulos.ALTITUDE_SOBREVOO.get(), txfHover.getText()); - commands.put(Modulos.MAX_TWR.get(), txfMaxTWR.getText()); - commands.put(Modulos.SOBREVOO_POS_POUSO.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 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(); + } + + @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) { + 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()); + } } diff --git a/src/main/java/com/pesterenan/views/LiftoffJPanel.java b/src/main/java/com/pesterenan/views/LiftoffJPanel.java index 7c5e488..b7b0e10 100644 --- a/src/main/java/com/pesterenan/views/LiftoffJPanel.java +++ b/src/main/java/com/pesterenan/views/LiftoffJPanel.java @@ -2,7 +2,7 @@ import com.pesterenan.MechPeste; import com.pesterenan.resources.Bundle; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import javax.swing.*; import javax.swing.border.TitledBorder; @@ -17,199 +17,198 @@ 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(); - } - - @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[] { Modulos.SINUSOIDAL.get(), Modulos.QUADRATICA.get(), Modulos.CUBICA.get(), - Modulos.CIRCULAR.get(), Modulos.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) { - 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(Modulos.MODULO.get(), Modulos.MODULO_DECOLAGEM.get()); - commands.put(Modulos.APOASTRO.get(), txfFinalApoapsis.getText()); - commands.put(Modulos.DIRECAO.get(), txfHeading.getText()); - commands.put(Modulos.MAX_TWR.get(), txfLimitTWR.getText()); - commands.put(Modulos.ROLAGEM.get(), String.valueOf(sldRoll.getValue())); - commands.put(Modulos.INCLINACAO.get(), cbGravityCurveModel.getSelectedItem().toString()); - commands.put(Modulos.USAR_ESTAGIOS.get(), String.valueOf(chkDecoupleStages.isSelected())); - commands.put(Modulos.ABRIR_PAINEIS.get(), String.valueOf(chkOpenPanels.isSelected())); - MechPeste.newInstance().startModule(commands); - MainGui.backToTelemetry(e); - } - } + 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(); + } + + @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) { + 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); + } + } } diff --git a/src/main/java/com/pesterenan/views/MainGui.java b/src/main/java/com/pesterenan/views/MainGui.java index f824d7f..fa79424 100644 --- a/src/main/java/com/pesterenan/views/MainGui.java +++ b/src/main/java/com/pesterenan/views/MainGui.java @@ -1,7 +1,7 @@ package com.pesterenan.views; import com.pesterenan.resources.Bundle; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import javax.swing.*; import javax.swing.border.EmptyBorder; @@ -12,184 +12,184 @@ 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(); - } - - public static MainGui newInstance() { - if (mainGui == null) { - mainGui = new MainGui(); - } - return mainGui; - } - - @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(); - } - - @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); - } - - @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, Modulos.MODULO_TELEMETRIA.get()); - cardJPanels.add(pnlLiftoff, Modulos.MODULO_DECOLAGEM.get()); - cardJPanels.add(pnlLanding, Modulos.MODULO_POUSO.get()); - cardJPanels.add(pnlManeuverJTabbedPane, Modulos.MODULE_MANEUVER.get()); - cardJPanels.add(pnlRover, Modulos.MODULO_ROVER.get()); - cardJPanels.add(pnlDocking, Modulos.MODULO_DOCKING.get()); - } - - public void actionPerformed(ActionEvent e) { - if (e.getSource() == mntmAbout) { - handleMntmAboutActionPerformed(e); - } - if (e.getSource() == mntmInstallKrpc) { - handleMntmInstallKrpcActionPerformed(e); - } - if (e.getSource() == mntmExit) { - handleMntmExitActionPerformed(e); - } - if (e.getSource() == mntmChangeVessels) { - handleMntmMultiControlActionPerformed(e); - } - } - - private void handleMntmMultiControlActionPerformed(ActionEvent e) { - new ChangeVesselDialog(); - } - - protected void handleMntmInstallKrpcActionPerformed(ActionEvent e) { - new InstallKrpcDialog(); - } - - protected void handleMntmExitActionPerformed(ActionEvent e) { - System.exit(0); - } - - 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, Modulos.MODULO_TELEMETRIA.get()); - } - - 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 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(); + } + + public static MainGui newInstance() { + if (mainGui == null) { + mainGui = new MainGui(); + } + return mainGui; + } + + @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(); + } + + @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); + } + + @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); + } + if (e.getSource() == mntmInstallKrpc) { + handleMntmInstallKrpcActionPerformed(e); + } + if (e.getSource() == mntmExit) { + handleMntmExitActionPerformed(e); + } + if (e.getSource() == mntmChangeVessels) { + handleMntmMultiControlActionPerformed(e); + } + } + + private void handleMntmMultiControlActionPerformed(ActionEvent e) { + new ChangeVesselDialog(); + } + + protected void handleMntmInstallKrpcActionPerformed(ActionEvent e) { + new InstallKrpcDialog(); + } + + protected void handleMntmExitActionPerformed(ActionEvent e) { + System.exit(0); + } + + 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()); + } + + 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; + } } diff --git a/src/main/java/com/pesterenan/views/RoverJPanel.java b/src/main/java/com/pesterenan/views/RoverJPanel.java index 8590f82..008a16d 100644 --- a/src/main/java/com/pesterenan/views/RoverJPanel.java +++ b/src/main/java/com/pesterenan/views/RoverJPanel.java @@ -2,7 +2,7 @@ import com.pesterenan.MechPeste; import com.pesterenan.resources.Bundle; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import javax.swing.*; import javax.swing.border.EtchedBorder; @@ -18,155 +18,155 @@ 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(); - } - - @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(Modulos.NAVE_ALVO.get()); - rbTargetVessel.addActionListener(this::handleTargetSelection); - rbWaypointOnMap.setActionCommand(Modulos.MARCADOR_MAPA.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(Modulos.MODULO.get(), Modulos.MODULO_ROVER.get()); - commands.put(Modulos.TIPO_ALVO_ROVER.get(), bgTargetChoice.getSelection().getActionCommand()); - commands.put(Modulos.NOME_MARCADOR.get(), txfWaypointName.getText()); - commands.put(Modulos.VELOCIDADE_MAX.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 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(); + } + + @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; + } } diff --git a/src/main/java/com/pesterenan/views/RunManeuverJPanel.java b/src/main/java/com/pesterenan/views/RunManeuverJPanel.java index 037ecd8..90cd3ee 100644 --- a/src/main/java/com/pesterenan/views/RunManeuverJPanel.java +++ b/src/main/java/com/pesterenan/views/RunManeuverJPanel.java @@ -3,7 +3,7 @@ import com.pesterenan.MechPeste; import com.pesterenan.resources.Bundle; import com.pesterenan.utils.ControlePID; -import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Module; import krpc.client.RPCException; import krpc.client.services.SpaceCenter.Node; @@ -26,215 +26,215 @@ 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(); - } - - 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 static void createManeuver() { - System.out.println("Create maneuver"); - try { - createManeuver(MechPeste.getSpaceCenter().getUT() + 60); - } catch (RPCException 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 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) { - } - } - - 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); - } - - 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(Modulos.EXECUTAR.get()); - } - if (e.getSource() == btnLowerOrbit) { - handleManeuverFunction(Modulos.ORBITA_BAIXA.get()); - } - if (e.getSource() == btnApoapsis) { - handleManeuverFunction(Modulos.APOASTRO.get()); - } - if (e.getSource() == btnPeriapsis) { - handleManeuverFunction(Modulos.PERIASTRO.get()); - } - if (e.getSource() == btnAlignPlanes) { - handleManeuverFunction(Modulos.AJUSTAR.get()); - } - if (e.getSource() == btnRendezvous) { - handleManeuverFunction(Modulos.RENDEZVOUS.get()); - } - if (e.getSource() == btnBack) { - MainGui.backToTelemetry(e); - } - } - - protected void handleManeuverFunction(String maneuverFunction) { - Map commands = new HashMap<>(); - commands.put(Modulos.MODULO.get(), Modulos.MODULE_MANEUVER.get()); - commands.put(Modulos.FUNCAO.get(), maneuverFunction.toString()); - commands.put(Modulos.AJUSTE_FINO.get(), String.valueOf(chkFineAdjusment.isSelected())); - MechPeste.newInstance().startModule(commands); - } + 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(); + } + + 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 static void createManeuver() { + System.out.println("Create maneuver"); + try { + createManeuver(MechPeste.getSpaceCenter().getUT() + 60); + } catch (RPCException 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 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) { + } + } + + 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); + } + + 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()); + } + 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); + } + } + + 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); + } } diff --git a/src/main/java/com/pesterenan/views/StatusJPanel.java b/src/main/java/com/pesterenan/views/StatusJPanel.java index 456ae8c..e3f6e34 100644 --- a/src/main/java/com/pesterenan/views/StatusJPanel.java +++ b/src/main/java/com/pesterenan/views/StatusJPanel.java @@ -12,65 +12,65 @@ 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(); - } + 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(); + } } diff --git a/src/main/java/com/pesterenan/views/UIMethods.java b/src/main/java/com/pesterenan/views/UIMethods.java index 5338fd0..eff0f48 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 26d39fc..91f4d43 100644 --- a/src/main/resources/MechPesteBundle.properties +++ b/src/main/resources/MechPesteBundle.properties @@ -10,7 +10,7 @@ installer_dialog_btn_cancel = Cancel installer_dialog_btn_download = Download file and install installer_dialog_pnl_path = Path to KSP's folder\: installer_dialog_title = KRPC Installer -installer_dialog_txt_info = Here you can download the latest version of KRPC to use with MechPeste.
The app will connect and download the 0.5.2 version from the original KRPC's Github. +installer_dialog_txt_info = Here you can download the latest version of KRPC to use with MechPeste.
The app will connect and download the 0.5.4 version from the original KRPC's Github. lbl_stat_ready = Ready. main_mn_file = File main_mn_help = Help diff --git a/src/main/resources/MechPesteBundle_pt.properties b/src/main/resources/MechPesteBundle_pt.properties index 0975975..b2636c5 100644 --- a/src/main/resources/MechPesteBundle_pt.properties +++ b/src/main/resources/MechPesteBundle_pt.properties @@ -10,7 +10,7 @@ installer_dialog_btn_cancel = Cancelar installer_dialog_btn_download = Fazer download e instalar installer_dialog_pnl_path = Caminho para a Pasta do KSP\: installer_dialog_title = Instalador do KRPC -installer_dialog_txt_info = Aqui voc\u00ea pode baixar a \u00faltima vers\u00e3o do KRPC para usar com o MechPeste.
O app ir\u00e1 se conectar e baixar a vers\u00e3o 0.5.2 do Github original do KRPC. +installer_dialog_txt_info = Aqui voc\u00ea pode baixar a \u00faltima vers\u00e3o do KRPC para usar com o MechPeste.
O app ir\u00e1 se conectar e baixar a vers\u00e3o 0.5.4 do Github original do KRPC. lbl_stat_ready = Pronto. main_mn_file = Arquivo main_mn_help = Ajuda diff --git a/src/main/resources/krpc-java-0.5.2.jar b/src/main/resources/krpc-java-0.5.4.jar similarity index 75% rename from src/main/resources/krpc-java-0.5.2.jar rename to src/main/resources/krpc-java-0.5.4.jar index a645a94..b5b29dd 100644 Binary files a/src/main/resources/krpc-java-0.5.2.jar and b/src/main/resources/krpc-java-0.5.4.jar differ