diff --git a/.classpath b/.classpath index 5a6230c..653dfd7 100644 --- a/.classpath +++ b/.classpath @@ -1,13 +1,57 @@ - - + - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml new file mode 100644 index 0000000..e6e6dae --- /dev/null +++ b/.github/workflows/ci-workflow.yml @@ -0,0 +1,37 @@ +name: MechPeste CI workflow + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Install KRPC as a Local Library + run: | + mvn install:install-file \ + -Dfile=./src/main/resources/krpc-java-0.5.2.jar \ + -DgroupId=io.github.krpc \ + -DartifactId=krpc-java \ + -Dversion=0.5.2 \ + -Dpackaging=jar + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + cache: maven + + - name: Build MechPeste with Maven + run: mvn -B package --file pom.xml + + # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive + - name: Update dependency graph + uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 diff --git a/.github/workflows/release-new-version.yml b/.github/workflows/release-new-version.yml new file mode 100644 index 0000000..6e6b866 --- /dev/null +++ b/.github/workflows/release-new-version.yml @@ -0,0 +1,37 @@ +name: Release a new MechPeste version + +on: + workflow_dispatch: + pull_request: + types: + - closed + +jobs: + release: + runs-on: ubuntu-latest + + steps: + - name: Check out the code + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + cache: maven + + - name: Build MechPeste with Maven + run: mvn -B package --file pom.xml + + - name: Upload Release Artifact + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./target/MechPeste-${{ steps.maven.outputs.version }}.jar + asset_name: MechPeste-${{ steps.maven.outputs.version }}.jar + asset_content_type: application/java-archive + + - name: Get Maven version + id: maven + run: echo "::set-output name=version::$(mvn -q -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec)" diff --git a/.gitignore b/.gitignore index e9ea9a6..4dc29f9 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ local.properties .loadpath .metadata workspace.xml -settings.json \ No newline at end of file +settings.json +target/ diff --git a/.project b/.project index 9e5a886..f8b3eba 100644 --- a/.project +++ b/.project @@ -10,8 +10,14 @@ + + org.eclipse.m2e.core.maven2Builder + + + + org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs index 99f26c0..2b76340 100644 --- a/.settings/org.eclipse.core.resources.prefs +++ b/.settings/org.eclipse.core.resources.prefs @@ -1,2 +1,2 @@ eclipse.preferences.version=1 -encoding/=UTF-8 +encoding//src/main/java=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 0c68a61..fa50df0 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -3,5 +3,10 @@ org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 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 diff --git a/.vscode/launch.json b/.vscode/launch.json index beb5d53..c826b57 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,5 +1,12 @@ { "configurations": [ + { + "type": "java", + "name": "Main", + "request": "launch", + "mainClass": "com.pesterenan.Main", + "projectName": "MechPeste-Java" + }, { "type": "java", "name": "Launch MechPeste", diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..1967018 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,16 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "java (build)", + "paths": [ + "${workspace}" + ], + "isFullBuild": true, + "group": "build", + "problemMatcher": [], + "label": "java (build): Build Workspace", + "detail": "$(tools) Build all the Java projects in workspace." + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 3985eb1..c470c4c 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.1/krpc-0.5.1.zip) +mod [KRPC](https://github.com/krpc/krpc/releases/download/v0.5.2/krpc-0.5.2.zip) pode ser instalada diretamente do aplicativo MechPeste pelo menu Arquivo > Instalar KRPC. ## **Como instalar:** @@ -73,3 +73,25 @@ texto e também a velocidade máxima que o rover pode alcançar. A velocidade mínima permitida é de 3m/s. Clique em Pilotar e ele comecará a se mover para o alvo, desviando dos obstáculos à frente. + +### Desenvolvimento do MechPeste com Maven + +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: + +``` bash +mvn install:install-file \ + -Dfile=\krpc-java-0.5.2.jar \ + -DgroupId=io.github.krpc \ + -DartifactId=krpc-java \ + -Dversion=0.5.2 \ + -Dpackaging=jar \ +``` +Substitua `` pela pasta onde está o arquivo do KRPC. Isso instalará essa biblioteca +no seu repositório local. + +Agora você poderá usar comandos do Maven para instalar e construir a aplicação: +```bash +mvn clean install package +``` diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..2807bf2 --- /dev/null +++ b/pom.xml @@ -0,0 +1,89 @@ + + 4.0.0 + + com.pesterenan + MechPeste + 0.7.0 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + UTF-8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + com.pesterenan.MechPeste + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.3.0 + + + + com.pesterenan.MechPeste + + + + jar-with-dependencies + + MechPeste-${project.version} + false + + + + make-assembly + package + + single + + + + + + + + + 1.8 + 1.8 + + + + + org.apache.maven + maven-model + 3.3.9 + + + io.github.krpc + krpc-java + 0.5.2 + + + org.javatuples + javatuples + 1.2 + + + com.google.protobuf + protobuf-java + 3.22.1 + + + + diff --git a/src/com/pesterenan/resources/javatuples-1.2.jar b/src/com/pesterenan/resources/javatuples-1.2.jar deleted file mode 100644 index 8944308..0000000 Binary files a/src/com/pesterenan/resources/javatuples-1.2.jar and /dev/null differ diff --git a/src/com/pesterenan/resources/krpc-java-0.5.1.jar b/src/com/pesterenan/resources/krpc-java-0.5.1.jar deleted file mode 100644 index f2348b8..0000000 Binary files a/src/com/pesterenan/resources/krpc-java-0.5.1.jar and /dev/null differ diff --git a/src/com/pesterenan/resources/protobuf-java-3.22.1.jar b/src/com/pesterenan/resources/protobuf-java-3.22.1.jar deleted file mode 100644 index 7685cda..0000000 Binary files a/src/com/pesterenan/resources/protobuf-java-3.22.1.jar and /dev/null differ diff --git a/src/com/pesterenan/utils/ControlePID.java b/src/com/pesterenan/utils/ControlePID.java deleted file mode 100644 index a94e5af..0000000 --- a/src/com/pesterenan/utils/ControlePID.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.pesterenan.utils; - -public class ControlePID { - private double limiteMin = -1; - private double limiteMax = 1; - private double kp = 0.025; - private double ki = 0.001; - private double kd = 0.01; - private double proportionalTerm, integralTerm, derivativeTerm = 0; - private double lastValue, lastTime = 0; - - public double calcPID(double currentValue, double limitValue) { - double now = System.currentTimeMillis(); - double changeInTime = now - this.lastTime; - double timeSample = 25; - - if (changeInTime >= timeSample) { - double error = limitValue - currentValue; - double changeInValues = (currentValue - this.lastValue); - - this.proportionalTerm = this.kp * error; - this.integralTerm = limitOutput(this.integralTerm + ki * error); - this.derivativeTerm = kd * -changeInValues; - this.lastValue = currentValue; - this.lastTime = now; - } - return limitOutput(proportionalTerm + ki * this.integralTerm + derivativeTerm); - } - - private double limitOutput(double valor) { - return Utilities.clamp(valor, this.limiteMin, this.limiteMax); - } - - public void adjustOutput(double min, double max) { - if (min > max) { - return; - } - this.limiteMin = min; - this.limiteMax = max; - this.integralTerm = limitOutput(this.integralTerm); - - } - - public void adjustPID(double Kp, double Ki, double Kd) { - if (Kp > 0) { - this.kp = Kp; - } - if (Ki >= 0) { - this.ki = Ki; - } - if (Kd >= 0) { - this.kd = Kd; - } - } - -} \ No newline at end of file diff --git a/src/com/pesterenan/utils/Navigation.java b/src/com/pesterenan/utils/Navigation.java deleted file mode 100644 index 70cc9d8..0000000 --- a/src/com/pesterenan/utils/Navigation.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.pesterenan.utils; - -import krpc.client.RPCException; -import krpc.client.Stream; -import krpc.client.StreamException; -import org.javatuples.Triplet; - -import static com.pesterenan.MechPeste.getConnection; -import static com.pesterenan.MechPeste.getSpaceCenter; -import static krpc.client.services.SpaceCenter.*; - -public class Navigation { - - public static final Triplet RADIAL = new Triplet<>(1.0, 0.0, 0.0); - public static final Triplet ANTI_RADIAL = new Triplet<>(-1.0, 0.0, 0.0); - public static final Triplet PROGRADE = new Triplet<>(0.0, 1.0, 0.0); - public static final Triplet RETROGRADE = new Triplet<>(0.0, -1.0, 0.0); - public static final Triplet NORMAL = new Triplet<>(0.0, 0.0, 1.0); - public static final Triplet ANTI_NORMAL = new Triplet<>(0.0, 0.0, -1.0); - // private Drawing drawing; - private Vessel currentVessel; - private Flight flightParameters; - private Stream horizontalSpeed; - private ReferenceFrame orbitalReference; - - public Navigation(Vessel currentVessel) { - this.currentVessel = currentVessel; - initializeParameters(); - } - - 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 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 aimAtPrograde() throws RPCException { - aimAtDirection(getSpaceCenter().transformDirection(PROGRADE, currentVessel.getSurfaceVelocityReferenceFrame(), - 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 aimAtDirection(Triplet currentDirection) throws RPCException { - currentVessel.getAutoPilot().setReferenceFrame(orbitalReference); - currentVessel.getAutoPilot().setTargetDirection(currentDirection); - } - -} diff --git a/src/com/pesterenan/views/InstallKrpcDialog.java b/src/com/pesterenan/views/InstallKrpcDialog.java deleted file mode 100644 index 2a905fa..0000000 --- a/src/com/pesterenan/views/InstallKrpcDialog.java +++ /dev/null @@ -1,217 +0,0 @@ -package com.pesterenan.views; - -import com.pesterenan.resources.Bundle; -import com.pesterenan.updater.KrpcInstaller; - -import javax.swing.*; -import javax.swing.GroupLayout.Alignment; -import javax.swing.LayoutStyle.ComponentPlacement; -import javax.swing.border.BevelBorder; -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); - } -} diff --git a/src/com/pesterenan/views/UIMethods.java b/src/com/pesterenan/views/UIMethods.java deleted file mode 100644 index 3a34ae7..0000000 --- a/src/com/pesterenan/views/UIMethods.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.pesterenan.views; - -public interface UIMethods { - - public void initComponents(); - - public void setupComponents(); - - public void layoutComponents(); -} \ No newline at end of file diff --git a/src/main/java/com/pesterenan/Main.java b/src/main/java/com/pesterenan/Main.java new file mode 100644 index 0000000..ceb84df --- /dev/null +++ b/src/main/java/com/pesterenan/Main.java @@ -0,0 +1,229 @@ +package com.pesterenan; + +import java.io.IOException; + +import com.pesterenan.utils.Utilities; +import com.pesterenan.utils.Vector; + +import krpc.client.Connection; +import krpc.client.RPCException; +import krpc.client.services.Drawing; +import krpc.client.services.Drawing.Line; +import krpc.client.services.SpaceCenter; +import krpc.client.services.SpaceCenter.Control; +import krpc.client.services.SpaceCenter.DockingPort; +import krpc.client.services.SpaceCenter.ReferenceFrame; +import krpc.client.services.SpaceCenter.SASMode; +import krpc.client.services.SpaceCenter.Vessel; + +public class Main { + private static Connection connection; + private static SpaceCenter spaceCenter; + private static Drawing drawing; + private static Control control; + + private static Vessel activeVessel; + private static Vessel targetVessel; + + private static ReferenceFrame orbitalRefVessel; + private static ReferenceFrame vesselRefFrame; + private static ReferenceFrame orbitalRefBody; + private static final double SPEED_LIMIT = 3.0; + private static final double DISTANCE_LIMIT = 25.0; + private static Line distanceLine; + private static Line distLineXAxis; + private static Line distLineYAxis; + private static Line distLineZAxis; + private static DockingPort myDockingPort; + private static DockingPort targetDockingPort; + private static Vector positionMyDockingPort; + private static Vector positionTargetDockingPort; + + private static void initializeParameters() { + try { + connection = Connection.newInstance(); + spaceCenter = SpaceCenter.newInstance(connection); + drawing = Drawing.newInstance(connection); + activeVessel = spaceCenter.getActiveVessel(); + targetVessel = spaceCenter.getTargetVessel(); + vesselRefFrame = activeVessel.getReferenceFrame(); + orbitalRefVessel = activeVessel.getOrbitalReferenceFrame(); + orbitalRefBody = activeVessel.getOrbit().getBody().getReferenceFrame(); + + myDockingPort = activeVessel.getParts().getDockingPorts().get(0); + targetDockingPort = targetVessel.getParts().getDockingPorts().get(0); + + positionMyDockingPort = new Vector(myDockingPort.position(orbitalRefVessel)); + positionTargetDockingPort = new Vector(targetDockingPort.position(orbitalRefVessel)); + + createLines(positionMyDockingPort, positionTargetDockingPort); + + } catch (IOException | RPCException e) { + e.printStackTrace(); + } + } + + public static void main(String[] args) { + try { + // Initialize parameters for the script, connection and setup: + initializeParameters(); + + // Setting up the control + control = activeVessel.getControl(); + control.setSAS(true); + control.setRCS(false); + control.setSASMode(SASMode.STABILITY_ASSIST); + + Vector targetDirection = new Vector(activeVessel.position(orbitalRefVessel)) + .subtract(new Vector(targetVessel.position(orbitalRefVessel))).multiply(-1); + activeVessel.getAutoPilot().setReferenceFrame(orbitalRefVessel); + activeVessel.getAutoPilot().setTargetDirection(targetDirection.toTriplet()); + activeVessel.getAutoPilot().setTargetRoll(90); + activeVessel.getAutoPilot().engage(); + // Fazer a nave apontar usando o piloto automático, na marra + while (Math.abs(activeVessel.getAutoPilot().getError()) > 1) { + activeVessel.getAutoPilot().wait_(); + } + control.setRCS(true); + activeVessel.getAutoPilot().disengage(); + control.setSAS(true); + control.setSASMode(SASMode.STABILITY_ASSIST); + + // PRIMEIRA PARTE DO DOCKING: APROXIMAÇÃO + + Vector targetPosition = new Vector(targetVessel.position(vesselRefFrame)); + double lastXTargetPos = targetPosition.x; + double lastYTargetPos = targetPosition.y; + double lastZTargetPos = targetPosition.z; + long sleepTime = 25; + double currentXAxisSpeed = 0; + double currentYAxisSpeed = 0; + double currentZAxisSpeed = 0; + while (Math.abs(lastYTargetPos) >= DISTANCE_LIMIT) { + targetPosition = new Vector(targetVessel.position(vesselRefFrame)); + + // Atualizar posições para linhas + positionMyDockingPort = new Vector(myDockingPort.position(vesselRefFrame)); + positionTargetDockingPort = new Vector(targetDockingPort.position(vesselRefFrame)); + updateLines(positionMyDockingPort, positionTargetDockingPort); + + // Calcular velocidade de cada eixo: + currentXAxisSpeed = (targetPosition.x - lastXTargetPos) * sleepTime; + currentYAxisSpeed = (targetPosition.y - lastYTargetPos) * sleepTime; + currentZAxisSpeed = (targetPosition.z - lastZTargetPos) * sleepTime; + + // Calcular a aceleração para cada eixo no RCS: + float forwardsError = calculateThrottle(DISTANCE_LIMIT, DISTANCE_LIMIT * 2, currentYAxisSpeed, + targetPosition.y, SPEED_LIMIT); + float sidewaysError = calculateThrottle(0, 10, currentXAxisSpeed, targetPosition.x, SPEED_LIMIT); + float upwardsError = calculateThrottle(0, 10, currentZAxisSpeed, targetPosition.z, SPEED_LIMIT); + control.setForward((float) forwardsError); + control.setRight((float) sidewaysError); + control.setUp((float) -upwardsError); + + // Guardar últimas posições: + lastXTargetPos = targetPosition.x; + lastYTargetPos = targetPosition.y; + lastZTargetPos = targetPosition.z; + Thread.sleep(sleepTime); + } + + // SEGUNDA PARTE APONTAR PRO LADO CONTRARIO: + Vector direcaoContrariaDockingPortAlvo = new Vector(targetDockingPort.direction(orbitalRefVessel)) + .multiply(-1); + control.setSAS(false); + control.setRCS(false); + activeVessel.getAutoPilot().engage(); + activeVessel.getAutoPilot().setReferenceFrame(orbitalRefVessel); + activeVessel.getAutoPilot().setTargetDirection(direcaoContrariaDockingPortAlvo.toTriplet()); + activeVessel.getAutoPilot().setTargetRoll(90); + while (Math.abs(activeVessel.getAutoPilot().getError()) > 1) { + activeVessel.getAutoPilot().wait_(); + } + activeVessel.getAutoPilot().disengage(); + control.setSAS(true); + control.setSASMode(SASMode.STABILITY_ASSIST); + Thread.sleep(1000); + control.setRCS(true); + + while (targetVessel != null) { + targetPosition = new Vector(targetDockingPort.position(vesselRefFrame)); + + // Atualizar posições para linhas + positionMyDockingPort = new Vector(myDockingPort.position(vesselRefFrame)); + updateLines(positionMyDockingPort, targetPosition); + + // Calcular velocidade de cada eixo: + currentXAxisSpeed = (targetPosition.x - lastXTargetPos) * sleepTime; + currentYAxisSpeed = (targetPosition.y - lastYTargetPos) * sleepTime; + currentZAxisSpeed = (targetPosition.z - lastZTargetPos) * sleepTime; + + // Calcular a aceleração para cada eixo no RCS: + float forwardsError = calculateThrottle(5, 10, currentYAxisSpeed, + targetPosition.y, SPEED_LIMIT); + float sidewaysError = calculateThrottle(-1, 10, currentXAxisSpeed, targetPosition.x, SPEED_LIMIT); + float upwardsError = calculateThrottle(-1, 10, currentZAxisSpeed, targetPosition.z, SPEED_LIMIT); + control.setForward((float) forwardsError); + control.setRight((float) sidewaysError); + control.setUp((float) -upwardsError); + + // Guardar últimas posições: + lastXTargetPos = targetPosition.x; + lastYTargetPos = targetPosition.y; + lastZTargetPos = targetPosition.z; + Thread.sleep(sleepTime); + } + // // Close the connection when finished + // connection.close(); + } catch (RPCException | InterruptedException e) { + e.printStackTrace(); + } + } + + private static float calculateThrottle(double minDistance, double maxDistance, double currentSpeed, + double currentPosition, double speedLimit) { + double limiter = Utilities.remap(minDistance, maxDistance, 0, 1, Math.abs(currentPosition), true); + double change = (Utilities.remap(-speedLimit, speedLimit, -1.0, 1.0, + currentSpeed + (Math.signum(currentPosition) * (limiter * speedLimit)), true)); + return (float) change; + } + + private static void createLines(Vector start, Vector end) { + try { + distanceLine = drawing.addLine(start.toTriplet(), + end.toTriplet(), vesselRefFrame, true); + distLineXAxis = drawing.addLine(start.toTriplet(), + new Vector(end.x, 0.0, 0.0).toTriplet(), + vesselRefFrame, true); + distLineYAxis = drawing.addLine(start.toTriplet(), + new Vector(end.x, end.y, 0.0).toTriplet(), + vesselRefFrame, true); + distLineZAxis = drawing.addLine(start.toTriplet(), + end.toTriplet(), + vesselRefFrame, true); + distanceLine.setThickness(0.5f); + distLineXAxis.setThickness(0.25f); + distLineYAxis.setThickness(0.25f); + distLineZAxis.setThickness(0.25f); + distLineXAxis.setColor(new Vector(1.0, 0.0, 0.0).toTriplet()); + distLineYAxis.setColor(new Vector(0.0, 1.0, 0.0).toTriplet()); + distLineZAxis.setColor(new Vector(0.0, 0.0, 1.0).toTriplet()); + } catch (RPCException e) { + } + } + + private static void updateLines(Vector start, Vector end) { + // Updating drawing lines: + try { + distanceLine.setStart(start.toTriplet()); + distanceLine.setEnd(end.toTriplet()); + distLineXAxis.setStart(start.toTriplet()); + distLineXAxis.setEnd(new Vector(end.x, 0.0, 0.0).toTriplet()); + distLineYAxis.setStart(distLineXAxis.getEnd()); + distLineYAxis.setEnd(new Vector(end.x, end.y, 0.0).toTriplet()); + distLineZAxis.setStart(distLineYAxis.getEnd()); + distLineZAxis.setEnd(end.toTriplet()); + } catch (RPCException e) { + } + } +} diff --git a/src/com/pesterenan/MechPeste.java b/src/main/java/com/pesterenan/MechPeste.java similarity index 78% rename from src/com/pesterenan/MechPeste.java rename to src/main/java/com/pesterenan/MechPeste.java index 4f6fc12..0367073 100644 --- a/src/com/pesterenan/MechPeste.java +++ b/src/main/java/com/pesterenan/MechPeste.java @@ -1,26 +1,31 @@ package com.pesterenan; +import static com.pesterenan.views.StatusJPanel.isBtnConnectVisible; +import static com.pesterenan.views.StatusJPanel.setStatusMessage; + +import java.awt.event.ActionEvent; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.swing.DefaultListModel; +import javax.swing.ListModel; + import com.pesterenan.model.ActiveVessel; import com.pesterenan.resources.Bundle; import com.pesterenan.utils.Vector; +import com.pesterenan.views.CreateManeuverJPanel; import com.pesterenan.views.FunctionsAndTelemetryJPanel; import com.pesterenan.views.MainGui; + import krpc.client.Connection; import krpc.client.RPCException; import krpc.client.services.KRPC; import krpc.client.services.SpaceCenter; +import krpc.client.services.SpaceCenter.Node; import krpc.client.services.SpaceCenter.Vessel; -import javax.swing.*; -import java.awt.event.ActionEvent; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import static com.pesterenan.views.StatusJPanel.isBtnConnectVisible; -import static com.pesterenan.views.StatusJPanel.setStatusMessage; - public class MechPeste { private static KRPC krpc; private static MechPeste mechPeste; @@ -29,10 +34,6 @@ public class MechPeste { private static int currentVesselId = -1; private static ActiveVessel currentVessel = null; - private MechPeste() { - MainGui.newInstance(); - } - public static void main(String[] args) { MechPeste.newInstance().connectToKSP(); MechPeste.newInstance().checkActiveVessel(); @@ -70,6 +71,53 @@ public static ListModel getActiveVessels(String search) { 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; @@ -96,61 +144,14 @@ private static boolean filterVessels(Vessel vessel, String search) { return false; } - 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")); - } + private MechPeste() { + MainGui.newInstance(); } public KRPC.GameScene getCurrentGameScene() throws RPCException { return krpc.getCurrentGameScene(); } - 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()); - } - Thread.sleep(100); - } catch (RPCException | InterruptedException ignored) { - } - } - } - public void startModule(Map commands) { currentVessel.startModule(commands); } @@ -182,7 +183,30 @@ public void checkConnection() { } } - public static void cancelControl(ActionEvent e) { - currentVessel.cancelControl(); + private void checkActiveVessel() { + while (getConnection() != null) { + try { + if (!MechPeste.newInstance().getCurrentGameScene().equals(KRPC.GameScene.FLIGHT)) { + Thread.sleep(100); + return; + } + int activeVesselId = spaceCenter.getActiveVessel().hashCode(); + // If the current active vessel changes, create a new connection + if (currentVesselId != activeVesselId) { + currentVessel = new ActiveVessel(); + currentVesselId = currentVessel.getCurrentVesselId(); + } + if (currentVesselId != -1) { + currentVessel.recordTelemetryData(); + if (currentVessel.hasModuleRunning()) { + setStatusMessage(currentVessel.getCurrentStatus()); + } + FunctionsAndTelemetryJPanel.updateTelemetry(currentVessel.getTelemetryData()); + CreateManeuverJPanel.updatePanel(getCurrentManeuvers()); + } + Thread.sleep(100); + } catch (RPCException | InterruptedException ignored) { + } + } } -} \ No newline at end of file +} diff --git a/src/com/pesterenan/controllers/Controller.java b/src/main/java/com/pesterenan/controllers/Controller.java similarity index 100% rename from src/com/pesterenan/controllers/Controller.java rename to src/main/java/com/pesterenan/controllers/Controller.java diff --git a/src/main/java/com/pesterenan/controllers/DockingController.java b/src/main/java/com/pesterenan/controllers/DockingController.java new file mode 100644 index 0000000..eaea4b7 --- /dev/null +++ b/src/main/java/com/pesterenan/controllers/DockingController.java @@ -0,0 +1,297 @@ +package com.pesterenan.controllers; + +import static com.pesterenan.MechPeste.getConnection; +import static com.pesterenan.MechPeste.getSpaceCenter; + +import java.util.Map; + +import com.pesterenan.utils.Modulos; +import com.pesterenan.utils.Utilities; +import com.pesterenan.utils.Vector; +import com.pesterenan.views.StatusJPanel; + +import krpc.client.RPCException; +import krpc.client.services.Drawing; +import krpc.client.services.Drawing.Line; +import krpc.client.services.SpaceCenter.Control; +import krpc.client.services.SpaceCenter.DockingPort; +import krpc.client.services.SpaceCenter.ReferenceFrame; +import krpc.client.services.SpaceCenter.SASMode; +import krpc.client.services.SpaceCenter.Vessel; + +public class DockingController extends Controller { + + private Drawing drawing; + private Vessel targetVessel; + private Control control; + + private ReferenceFrame orbitalRefVessel; + private ReferenceFrame vesselRefFrame; + private ReferenceFrame orbitalRefBody; + private Line distanceLine; + private Line distLineXAxis; + private Line distLineYAxis; + private Line distLineZAxis; + private DockingPort myDockingPort; + private DockingPort targetDockingPort; + private Vector positionMyDockingPort; + private Vector positionTargetDockingPort; + + private final double DISTANCE_LIMIT = 25.0; + private double SPEED_LIMIT = 3.0; + private double currentXAxisSpeed = 0.0; + private double currentYAxisSpeed = 0.0; + private double currentZAxisSpeed = 0.0; + private double lastXTargetPos = 0.0; + private double lastYTargetPos = 0.0; + private double lastZTargetPos = 0.0; + private long sleepTime = 25; + private DOCKING_STEPS dockingStep; + + public DockingController(Map commands) { + super(); + this.commands = commands; + initializeParameters(); + } + + private void initializeParameters() { + try { + SPEED_LIMIT = Double.parseDouble(commands.get(Modulos.VELOCIDADE_MAX.get())); + drawing = Drawing.newInstance(getConnection()); + targetVessel = getSpaceCenter().getTargetVessel(); + control = getNaveAtual().getControl(); + vesselRefFrame = getNaveAtual().getReferenceFrame(); + orbitalRefVessel = getNaveAtual().getOrbitalReferenceFrame(); + orbitalRefBody = getNaveAtual().getOrbit().getBody().getReferenceFrame(); + + myDockingPort = getNaveAtual().getParts().getDockingPorts().get(0); + targetDockingPort = targetVessel.getParts().getDockingPorts().get(0); + + positionMyDockingPort = new Vector(myDockingPort.position(orbitalRefVessel)); + positionTargetDockingPort = new Vector(targetDockingPort.position(orbitalRefVessel)); + } catch (RPCException ignored) { + } + } + + @Override + public void run() { + if (commands.get(Modulos.MODULO.get()).equals(Modulos.MODULO_DOCKING.get())) { + startDocking(); + } + } + + private void pointToTarget(Vector targetDirection) throws RPCException, InterruptedException { + getNaveAtual().getAutoPilot().setReferenceFrame(orbitalRefVessel); + getNaveAtual().getAutoPilot().setTargetDirection(targetDirection.toTriplet()); + getNaveAtual().getAutoPilot().setTargetRoll(90); + getNaveAtual().getAutoPilot().engage(); + // Fazer a nave apontar usando o piloto automático, na marra + while (Math.abs(getNaveAtual().getAutoPilot().getError()) > 3) { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + Thread.sleep(100); + System.out.println(getNaveAtual().getAutoPilot().getError()); + } + getNaveAtual().getAutoPilot().disengage(); + control.setSAS(true); + control.setSASMode(SASMode.STABILITY_ASSIST); + } + + private void getCloserToTarget(Vector targetPosition) throws InterruptedException, RPCException { + lastXTargetPos = targetPosition.x; + lastYTargetPos = targetPosition.y; + lastZTargetPos = targetPosition.z; + + while (Math.abs(lastYTargetPos) >= DISTANCE_LIMIT) { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + targetPosition = new Vector(targetVessel.position(vesselRefFrame)); + controlShipRCS(targetPosition, DISTANCE_LIMIT); + Thread.sleep(sleepTime); + } + + } + + public void startDocking() { + try { + // Setting up the control + control.setSAS(true); + control.setRCS(false); + control.setSASMode(SASMode.STABILITY_ASSIST); + createLines(positionMyDockingPort, positionTargetDockingPort); + + // PRIMEIRA PARTE DO DOCKING: APROXIMAÇÃO + Vector targetPosition = new Vector(targetVessel.position(vesselRefFrame)); + if (targetPosition.magnitude() > DISTANCE_LIMIT) { + // Apontar para o alvo: + Vector targetDirection = new Vector(getNaveAtual().position(orbitalRefVessel)) + .subtract(new Vector(targetVessel.position(orbitalRefVessel))).multiply(-1); + pointToTarget(targetDirection); + + control.setRCS(true); + + getCloserToTarget(targetPosition); + } + + control.setSAS(false); + control.setRCS(false); + + // SEGUNDA PARTE FICAR DE FRENTE COM A DOCKING PORT: + Vector targetDockingPortDirection = new Vector(targetDockingPort.direction(orbitalRefVessel)) + .multiply(-1); + pointToTarget(targetDockingPortDirection); + + Thread.sleep(1000); + control.setRCS(true); + double safeDistance = 10; + while (true) { + if (Thread.interrupted()) { + throw new InterruptedException(); + } + targetPosition = new Vector(targetDockingPort.position(vesselRefFrame)) + .subtract(new Vector(myDockingPort.position(vesselRefFrame))); + if (targetPosition.magnitude() < safeDistance) { + safeDistance = 1; + } + controlShipRCS(targetPosition, safeDistance); + Thread.sleep(sleepTime); + } + } catch (RPCException | InterruptedException | IllegalArgumentException e) { + StatusJPanel.setStatusMessage("Docking aborted."); + } + } + + /* + * Possibilidades do docking: + * primeiro: a nave ta na orientação certa, e só precisa seguir em frente X e Z + * = 0, Y positivo + * segundo: a nave ta na orientação certa, mas precisa corrigir a posição X e Z, + * Y positivo + * terceiro: a nave está atrás da docking port, precisa corrigir Y primeiro, Y + * negativo + * quarto: a nave está atrás da docking port, precisa afastar X e Z longe da + * nave primeiro, Y negativo + */ + + private enum DOCKING_STEPS { + APPROACH, LINE_UP_WITH_TARGET, GO_IN_FRONT_OF_TARGET + } + + private DOCKING_STEPS checkDockingStep(Vector targetPosition, double forwardsDistanceLimit) { + double sidewaysDistance = Math.abs(targetPosition.x); + double upwardsDistance = Math.abs(targetPosition.z); + boolean isInFrontOfTarget = Math.signum(targetPosition.y) == 1; + boolean isOnTheBackOfTarget = Math.signum(targetPosition.y) == -1 && targetPosition.y < forwardsDistanceLimit; + + if (isOnTheBackOfTarget) { + return DOCKING_STEPS.GO_IN_FRONT_OF_TARGET; + } + if (isInFrontOfTarget && (sidewaysDistance > 5 || upwardsDistance > 5)) { + return DOCKING_STEPS.LINE_UP_WITH_TARGET; + } + return DOCKING_STEPS.APPROACH; + } + + private void controlShipRCS(Vector targetPosition, double forwardsDistanceLimit) { + try { + // Atualizar posições para linhas + positionMyDockingPort = new Vector(myDockingPort.position(vesselRefFrame)); + updateLines(positionMyDockingPort, targetPosition); + + // Calcular velocidade de cada eixo: + currentXAxisSpeed = (targetPosition.x - lastXTargetPos) * sleepTime; + currentYAxisSpeed = (targetPosition.y - lastYTargetPos) * sleepTime; + currentZAxisSpeed = (targetPosition.z - lastZTargetPos) * sleepTime; + + dockingStep = checkDockingStep(targetPosition, forwardsDistanceLimit); + float forwardsError, upwardsError, sidewaysError = 0; + switch (dockingStep) { + case APPROACH: + // Calcular a aceleração para cada eixo no RCS: + forwardsError = calculateThrottle(forwardsDistanceLimit, forwardsDistanceLimit * 3, currentYAxisSpeed, + targetPosition.y, SPEED_LIMIT); + sidewaysError = calculateThrottle(0, 5, currentXAxisSpeed, targetPosition.x, SPEED_LIMIT); + upwardsError = calculateThrottle(0, 5, currentZAxisSpeed, targetPosition.z, SPEED_LIMIT); + control.setForward(forwardsError); + control.setRight(sidewaysError); + control.setUp(-upwardsError); + break; + case LINE_UP_WITH_TARGET: + forwardsError = calculateThrottle(forwardsDistanceLimit, forwardsDistanceLimit * 3, currentYAxisSpeed, + targetPosition.y, 0); + sidewaysError = calculateThrottle(0, 10, currentXAxisSpeed, targetPosition.x, SPEED_LIMIT); + upwardsError = calculateThrottle(0, 10, currentZAxisSpeed, targetPosition.z, SPEED_LIMIT); + control.setForward(forwardsError); + control.setRight(sidewaysError); + control.setUp(-upwardsError); + break; + case GO_IN_FRONT_OF_TARGET: + forwardsError = calculateThrottle(-20, -10, currentYAxisSpeed, + targetPosition.y, SPEED_LIMIT); + sidewaysError = calculateThrottle(0, 5, currentXAxisSpeed, targetPosition.x, 0); + upwardsError = calculateThrottle(0, 5, currentZAxisSpeed, targetPosition.z, 0); + control.setForward(forwardsError); + control.setRight(sidewaysError); + control.setUp(-upwardsError); + break; + } + System.out.println(dockingStep); + + // Guardar últimas posições: + lastXTargetPos = targetPosition.x; + lastYTargetPos = targetPosition.y; + lastZTargetPos = targetPosition.z; + } catch (RPCException ignored) { + } + } + + private float calculateThrottle(double minDistance, double maxDistance, double currentSpeed, + double currentPosition, double speedLimit) { + double limiter = Utilities.remap(minDistance, maxDistance, 0, 1, Math.abs(currentPosition), true); + double change = (Utilities.remap(-speedLimit, speedLimit, -1.0, 1.0, + currentSpeed + (Math.signum(currentPosition) * (limiter * speedLimit)), true)); + return (float) change; + } + + private void createLines(Vector start, Vector end) { + try { + distanceLine = drawing.addLine(start.toTriplet(), + end.toTriplet(), vesselRefFrame, true); + distLineXAxis = drawing.addLine(start.toTriplet(), + new Vector(end.x, 0.0, 0.0).toTriplet(), + vesselRefFrame, true); + distLineYAxis = drawing.addLine(start.toTriplet(), + new Vector(end.x, end.y, 0.0).toTriplet(), + vesselRefFrame, true); + distLineZAxis = drawing.addLine(start.toTriplet(), + end.toTriplet(), + vesselRefFrame, true); + distanceLine.setThickness(0.5f); + distLineXAxis.setThickness(0.25f); + distLineYAxis.setThickness(0.25f); + distLineZAxis.setThickness(0.25f); + distLineXAxis.setColor(new Vector(1.0, 0.0, 0.0).toTriplet()); + distLineYAxis.setColor(new Vector(0.0, 1.0, 0.0).toTriplet()); + distLineZAxis.setColor(new Vector(0.0, 0.0, 1.0).toTriplet()); + } catch (RPCException e) { + } + } + + private void updateLines(Vector start, Vector end) { + // Updating drawing lines: + try { + distanceLine.setStart(start.toTriplet()); + distanceLine.setEnd(end.toTriplet()); + distLineXAxis.setStart(start.toTriplet()); + distLineXAxis.setEnd(new Vector(end.x, 0.0, 0.0).toTriplet()); + distLineYAxis.setStart(distLineXAxis.getEnd()); + distLineYAxis.setEnd(new Vector(end.x, end.y, 0.0).toTriplet()); + distLineZAxis.setStart(distLineYAxis.getEnd()); + distLineZAxis.setEnd(end.toTriplet()); + } catch (RPCException e) { + } + } + +} diff --git a/src/com/pesterenan/controllers/LandingController.java b/src/main/java/com/pesterenan/controllers/LandingController.java similarity index 76% rename from src/com/pesterenan/controllers/LandingController.java rename to src/main/java/com/pesterenan/controllers/LandingController.java index 55c0e34..df9072c 100644 --- a/src/com/pesterenan/controllers/LandingController.java +++ b/src/main/java/com/pesterenan/controllers/LandingController.java @@ -1,24 +1,28 @@ package com.pesterenan.controllers; +import static com.pesterenan.MechPeste.getSpaceCenter; + +import java.util.Map; + import com.pesterenan.resources.Bundle; import com.pesterenan.utils.ControlePID; import com.pesterenan.utils.Modulos; import com.pesterenan.utils.Navigation; import com.pesterenan.utils.Utilities; + import krpc.client.RPCException; import krpc.client.StreamException; import krpc.client.services.SpaceCenter.VesselSituation; -import java.util.Map; - public class LandingController extends Controller { public static final double MAX_VELOCITY = 5; - private static final double velP = 0.025; - private static final double velI = 0.001; - private static final double velD = 0.01; - private final ControlePID altitudeCtrl = new ControlePID(); - private final ControlePID velocityCtrl = new ControlePID(); + private static final long sleepTime = 50; + private static final double velP = 0.05; + private static final double velI = 0.005; + private static final double velD = 0.001; + private ControlePID altitudeCtrl; + private ControlePID velocityCtrl; private Navigation navigation; private final int HUNDRED_PERCENT = 100; private double hoverAltitude; @@ -37,8 +41,10 @@ public LandingController(Map commands) { } private void initializeParameters() { - altitudeCtrl.adjustOutput(0, 1); - velocityCtrl.adjustOutput(0, 1); + altitudeCtrl = new ControlePID(getSpaceCenter(), sleepTime); + velocityCtrl = new ControlePID(getSpaceCenter(), sleepTime); + altitudeCtrl.setOutput(0, 1); + velocityCtrl.setOutput(0, 1); } @Override @@ -70,12 +76,11 @@ private void hoverArea() { currentMode = MODE.GOING_UP; } else { currentMode = MODE.HOVERING; - currentMode = MODE.HOVERING; } changeControlMode(); } catch (RPCException | StreamException ignored) { } - Thread.sleep(50); + Thread.sleep(sleepTime); } } catch (InterruptedException | RPCException ignored) { // disengageAfterException(Bundle.getString("status_liftoff_abort")); @@ -103,7 +108,7 @@ private void autoLanding() { } getNaveAtual().getControl().setBrakes(true); changeControlMode(); - Thread.sleep(100); + Thread.sleep(sleepTime); } } catch (RPCException | StreamException | InterruptedException e) { setCurrentStatus(Bundle.getString("status_ready")); @@ -112,7 +117,7 @@ private void autoLanding() { private void changeControlMode() throws RPCException, StreamException, InterruptedException { adjustPIDbyTWR(); - double velPID, altPID; + double velPID, altPID = 0; // Change vessel behavior depending on which mode is active switch (currentMode) { case DEORBITING: @@ -128,19 +133,22 @@ private void changeControlMode() throws RPCException, StreamException, Interrupt } break; case APPROACHING: - altitudeCtrl.adjustOutput(0, 1); - velocityCtrl.adjustOutput(0, 1); + altitudeCtrl.reset(); + velocityCtrl.reset(); + altitudeCtrl.setOutput(0, 1); + velocityCtrl.setOutput(0, 1); double currentVelocity = calculateCurrentVelocityMagnitude(); double zeroVelocity = calculateZeroVelocityMagnitude(); double landingDistanceThreshold = Math.max(hoverAltitude, getMaxAcel(maxTWR) * 3); double threshold = Utilities.clamp( ((currentVelocity + zeroVelocity) - landingDistanceThreshold) / landingDistanceThreshold, 0, 1); - altPID = altitudeCtrl.calcPID(currentVelocity / zeroVelocity * HUNDRED_PERCENT, HUNDRED_PERCENT); - velPID = velocityCtrl.calcPID(velVertical.get(), -Utilities.clamp(altitudeSup.get() * 0.1, 1, 10)); + altPID = altitudeCtrl.calculate(currentVelocity / sleepTime, zeroVelocity / sleepTime); + velPID = velocityCtrl.calculate(velVertical.get() / sleepTime, + (-Utilities.clamp(altitudeSup.get() * 0.1, 3, 20) / sleepTime)); throttle(Utilities.linearInterpolation(velPID, altPID, threshold)); navigation.aimForLanding(); - if (threshold < 0.25 || altitudeSup.get() < landingDistanceThreshold) { + if (threshold < 0.15 || altitudeSup.get() < landingDistanceThreshold) { hoverAltitude = landingDistanceThreshold; getNaveAtual().getControl().setGear(true); if (hoverAfterApproximation) { @@ -153,31 +161,39 @@ private void changeControlMode() throws RPCException, StreamException, Interrupt setCurrentStatus("Se aproximando do momento do pouso..."); break; case GOING_UP: - altitudeCtrl.adjustOutput(-0.5, 0.5); - velocityCtrl.adjustOutput(-0.5, 0.5); - altPID = altitudeCtrl.calcPID(altitudeErrorPercentage, HUNDRED_PERCENT); - velPID = velocityCtrl.calcPID(velVertical.get(), MAX_VELOCITY); + altitudeCtrl.reset(); + velocityCtrl.reset(); + altitudeCtrl.setOutput(-0.5, 0.5); + velocityCtrl.setOutput(-0.5, 0.5); + altPID = altitudeCtrl.calculate(altitudeErrorPercentage, HUNDRED_PERCENT); + velPID = velocityCtrl.calculate(velVertical.get(), MAX_VELOCITY); throttle(altPID + velPID); navigation.aimAtRadialOut(); setCurrentStatus("Subindo altitude..."); break; case GOING_DOWN: + altitudeCtrl.reset(); + velocityCtrl.reset(); controlThrottleByMatchingVerticalVelocity(-MAX_VELOCITY); navigation.aimAtRadialOut(); setCurrentStatus("Baixando altitude..."); break; case LANDING: + altitudeCtrl.reset(); + velocityCtrl.reset(); controlThrottleByMatchingVerticalVelocity( - velHorizontal.get() > 2 ? 0 : -Utilities.clamp(altitudeSup.get() * 0.1, 1, 10)); + velHorizontal.get() > 4 ? 0 : -Utilities.clamp(altitudeSup.get() * 0.1, 1, 10)); navigation.aimForLanding(); setCurrentStatus("Pousando..."); hasTheVesselLanded(); break; case HOVERING: - altitudeCtrl.adjustOutput(-0.5, 0.5); - velocityCtrl.adjustOutput(-0.5, 0.5); - altPID = altitudeCtrl.calcPID(altitudeErrorPercentage, HUNDRED_PERCENT); - velPID = velocityCtrl.calcPID(velVertical.get(), 0); + altitudeCtrl.reset(); + velocityCtrl.reset(); + altitudeCtrl.setOutput(-0.5, 0.5); + velocityCtrl.setOutput(-0.5, 0.5); + altPID = altitudeCtrl.calculate(altitudeErrorPercentage, HUNDRED_PERCENT); + velPID = velocityCtrl.calculate(velVertical.get(), 0); throttle(altPID + velPID); navigation.aimAtRadialOut(); setCurrentStatus("Sobrevoando area..."); @@ -187,8 +203,8 @@ private void changeControlMode() throws RPCException, StreamException, Interrupt private void controlThrottleByMatchingVerticalVelocity(double velocityToMatch) throws RPCException, StreamException { - velocityCtrl.adjustOutput(0, 1); - throttle(velocityCtrl.calcPID(velVertical.get(), velocityToMatch)); + velocityCtrl.setOutput(0, 1); + throttle(velocityCtrl.calculate(velVertical.get(), velocityToMatch + velHorizontal.get())); } private void deOrbitShip() throws RPCException, StreamException, InterruptedException { @@ -202,13 +218,15 @@ private void deOrbitShip() throws RPCException, StreamException, InterruptedExce navigation.aimForLanding(); setCurrentStatus(Bundle.getString("status_orienting_ship")); ap.wait_(); - Thread.sleep(100); + Thread.sleep(sleepTime); } + double targetPeriapsis = currentBody.getAtmosphereDepth(); + targetPeriapsis = targetPeriapsis > 0 ? targetPeriapsis / 2 : -currentBody.getEquatorialRadius() / 2; while (periastro.get() > -apoastro.get()) { navigation.aimForLanding(); - throttle(altitudeCtrl.calcPID(-currentBody.getEquatorialRadius() / 2, periastro.get())); + throttle(altitudeCtrl.calculate(targetPeriapsis, periastro.get())); setCurrentStatus(Bundle.getString("status_lowering_periapsis")); - Thread.sleep(100); + Thread.sleep(sleepTime); } getNaveAtual().getControl().setRCS(false); throttle(0.0f); @@ -220,14 +238,11 @@ private void deOrbitShip() throws RPCException, StreamException, InterruptedExce */ private void adjustPIDbyTWR() throws RPCException, StreamException { double currentTWR = Math.min(getTWR(), maxTWR); - velocityCtrl.adjustPID(currentTWR * velP, velI, velD); - altitudeCtrl.adjustPID(currentTWR * velP, velI, velD); - } - - private double calculateCurrentVelocityMagnitude() throws RPCException, StreamException { - double timeToGround = altitudeSup.get() / velVertical.get(); - double horizontalDistance = velHorizontal.get() * timeToGround; - return calculateEllipticTrajectory(horizontalDistance, altitudeSup.get()); + // double currentTWR = getMaxAcel(maxTWR); + double pGain = currentTWR / (sleepTime); + System.out.println(pGain); + altitudeCtrl.setPIDValues(pGain * 0.1, 0.0002, pGain * 0.1 * 2); + velocityCtrl.setPIDValues(pGain * 0.1, 0.1, 0.001); } private boolean hasTheVesselLanded() throws RPCException { @@ -246,6 +261,12 @@ private boolean hasTheVesselLanded() throws RPCException { return false; } + private double calculateCurrentVelocityMagnitude() throws RPCException, StreamException { + double timeToGround = altitudeSup.get() / velVertical.get(); + double horizontalDistance = velHorizontal.get() * timeToGround; + return calculateEllipticTrajectory(horizontalDistance, altitudeSup.get()); + } + private double calculateZeroVelocityMagnitude() throws RPCException, StreamException { double zeroVelocityDistance = calculateEllipticTrajectory(velHorizontal.get(), velVertical.get()); double zeroVelocityBurnTime = zeroVelocityDistance / getMaxAcel(maxTWR); diff --git a/src/com/pesterenan/controllers/LiftoffController.java b/src/main/java/com/pesterenan/controllers/LiftoffController.java similarity index 88% rename from src/com/pesterenan/controllers/LiftoffController.java rename to src/main/java/com/pesterenan/controllers/LiftoffController.java index b565948..b81b0d8 100644 --- a/src/com/pesterenan/controllers/LiftoffController.java +++ b/src/main/java/com/pesterenan/controllers/LiftoffController.java @@ -1,5 +1,7 @@ package com.pesterenan.controllers; +import static com.pesterenan.MechPeste.getSpaceCenter; + import com.pesterenan.MechPeste; import com.pesterenan.resources.Bundle; import com.pesterenan.utils.ControlePID; @@ -18,14 +20,14 @@ public class LiftoffController extends Controller { private static final float PITCH_UP = 90; - private final ControlePID thrControl = new ControlePID(); + private ControlePID thrControl; private float currentPitch; private float finalApoapsisAlt; private float heading; private float roll; private float maxTWR; - private boolean willDecoupleStages, willDeployPanelsAndRadiators; + private boolean willDecoupleStages, willOpenPanelsAndAntenna; private String gravityCurveModel = Modulos.CIRCULAR.get(); private Navigation navigation; @@ -43,9 +45,10 @@ private void initializeParameters() { 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())); - willDeployPanelsAndRadiators = Boolean.parseBoolean(commands.get(Modulos.ABRIR_PAINEIS.get())); + willOpenPanelsAndAntenna = Boolean.parseBoolean(commands.get(Modulos.ABRIR_PAINEIS.get())); willDecoupleStages = Boolean.parseBoolean(commands.get(Modulos.USAR_ESTAGIOS.get())); - thrControl.adjustOutput(0.0, 1.0); + thrControl = new ControlePID(getSpaceCenter(), 25); + thrControl.setOutput(0.0, 1.0); } @Override @@ -79,7 +82,7 @@ private void gravityCurve() throws RPCException, StreamException, InterruptedExc currentPitch = (float) (calculateCurrentPitch(altitudeProgress)); double currentMaxTWR = calculateTWRBasedOnPressure(currentPitch); ap.setTargetPitch(currentPitch); - throttle(Math.min(thrControl.calcPID(apoastro.get() / getFinalApoapsis() * 1000, 1000), + throttle(Math.min(thrControl.calculate(apoastro.get() / getFinalApoapsis() * 1000, 1000), getMaxThrottleForTWR(currentMaxTWR))); if (willDecoupleStages && isCurrentStageWithoutFuel()) { @@ -87,7 +90,7 @@ private void gravityCurve() throws RPCException, StreamException, InterruptedExc } setCurrentStatus(String.format(Bundle.getString("status_liftoff_inclination") + " %.1f", currentPitch)); - Thread.sleep(250); + Thread.sleep(25); if (Thread.interrupted()) { throw new InterruptedException(); } @@ -111,22 +114,22 @@ private void finalizeCurve() throws RPCException, StreamException, InterruptedEx throw new InterruptedException(); } navigation.aimAtPrograde(); - throttle(thrControl.calcPID(apoastro.get() / getFinalApoapsis() * 1000, 1000)); - Thread.sleep(100); + throttle(thrControl.calculate(apoastro.get() / getFinalApoapsis() * 1000, 1000)); + Thread.sleep(25); } throttle(0.0f); if (willDecoupleStages) { jettisonFairings(); } - if (willDeployPanelsAndRadiators) { - deployPanelsAndRadiators(); + if (willOpenPanelsAndAntenna) { + openPanelsAndAntenna(); } } private void circularizeOrbitOnApoapsis() { setCurrentStatus(Bundle.getString("status_planning_orbit")); Map commands = new HashMap<>(); - commands.put(Modulos.MODULO.get(), Modulos.MODULO_EXEC_MANOBRAS.get()); + 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); @@ -148,9 +151,10 @@ private void jettisonFairings() throws RPCException, InterruptedException { } } - private void deployPanelsAndRadiators() throws RPCException, InterruptedException { + private void openPanelsAndAntenna() throws RPCException, InterruptedException { getNaveAtual().getControl().setSolarPanels(true); getNaveAtual().getControl().setRadiators(true); + getNaveAtual().getControl().setAntennas(true); } private double calculateCurrentPitch(double currentAltitude) { diff --git a/src/com/pesterenan/controllers/ManeuverController.java b/src/main/java/com/pesterenan/controllers/ManeuverController.java similarity index 52% rename from src/com/pesterenan/controllers/ManeuverController.java rename to src/main/java/com/pesterenan/controllers/ManeuverController.java index 398c2d9..10f4f96 100644 --- a/src/com/pesterenan/controllers/ManeuverController.java +++ b/src/main/java/com/pesterenan/controllers/ManeuverController.java @@ -1,9 +1,21 @@ package com.pesterenan.controllers; +import static com.pesterenan.MechPeste.getConnection; +import static com.pesterenan.MechPeste.getSpaceCenter; + +import java.util.List; +import java.util.Map; + +import org.javatuples.Triplet; + import com.pesterenan.resources.Bundle; +import com.pesterenan.utils.Attributes; import com.pesterenan.utils.ControlePID; import com.pesterenan.utils.Modulos; import com.pesterenan.utils.Navigation; +import com.pesterenan.utils.Vector; +import com.pesterenan.views.RunManeuverJPanel; + import krpc.client.RPCException; import krpc.client.Stream; import krpc.client.StreamException; @@ -11,20 +23,15 @@ import krpc.client.services.SpaceCenter.Node; import krpc.client.services.SpaceCenter.Orbit; import krpc.client.services.SpaceCenter.RCS; +import krpc.client.services.SpaceCenter.ReferenceFrame; +import krpc.client.services.SpaceCenter.Vessel; import krpc.client.services.SpaceCenter.VesselSituation; -import org.javatuples.Triplet; - -import java.util.List; -import java.util.Map; - -import static com.pesterenan.MechPeste.getConnection; -import static com.pesterenan.MechPeste.getSpaceCenter; public class ManeuverController extends Controller { public final static float CONST_GRAV = 9.81f; - private final ControlePID ctrlRCS = new ControlePID(); - private final ControlePID ctrlManeuver = new ControlePID(); + private ControlePID ctrlRCS; + private ControlePID ctrlManeuver; private Navigation navigation; private boolean fineAdjustment; private double lowOrbitAltitude; @@ -37,38 +44,65 @@ public ManeuverController(Map commands) { } private void initializeParameters() { - ctrlRCS.adjustOutput(0.5, 1.0); + ctrlRCS = new ControlePID(getSpaceCenter(), 25); + ctrlManeuver = new ControlePID(getSpaceCenter(), 25); + ctrlManeuver.setPIDValues(1, 0.001, 0.1); + ctrlRCS.setOutput(0.5, 1.0); fineAdjustment = canFineAdjust(commands.get(Modulos.AJUSTE_FINO.get())); - lowOrbitAltitude = calculateSafeLowOrbitAltitude(); - System.out.println(lowOrbitAltitude); + try { + lowOrbitAltitude = new Attributes().getLowOrbitAltitude(currentBody.getName()); + System.out.println("lowOrbitAltitude: " + lowOrbitAltitude); + } catch (RPCException e) { + } } @Override public void run() { calculateManeuver(); - executeNextManeuver(); + 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 double calculateSafeLowOrbitAltitude() { - final double safeAltitude = 20000; - double bodyRadius = 0, atmosphereDepth = 0; + private Node biEllipticTransferToOrbit(double targetAltitude, double timeToStart) { + double[] totalDv = { 0, 0, 0 }; try { - bodyRadius = currentBody.getEquatorialRadius(); - System.out.println(bodyRadius); - atmosphereDepth = currentBody.getAtmosphereDepth(); - System.out.println(atmosphereDepth); - System.out.println(altitude.get()); - System.out.println(altitudeSup.get()); - System.out.println(apoastro.get()); - } catch (RPCException | StreamException ignored) { + 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 bodyRadius + (atmosphereDepth > 0 ? atmosphereDepth + safeAltitude : safeAltitude); + return createManeuver(timeToStart, totalDv); } public void calculateManeuver() { try { tuneAutoPilot(); - System.out.println(commands); + System.out.println(commands + " calculate maneuvers"); if (commands.get(Modulos.FUNCAO.get()).equals(Modulos.EXECUTAR.get())) { return; } @@ -77,12 +111,15 @@ public void calculateManeuver() { throw new InterruptedException(); } if (commands.get(Modulos.FUNCAO.get()).equals(Modulos.AJUSTAR.get())) { - this.alignPlanes(); + 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())) { - hohmannTransferToOrbit(lowOrbitAltitude, getNaveAtual().getOrbit().getTimeToPeriapsis()); - hohmannTransferToOrbit(lowOrbitAltitude, getNaveAtual().getOrbit().getTimeToPeriapsis()); + biEllipticTransferToOrbit(lowOrbitAltitude, getNaveAtual().getOrbit().getTimeToPeriapsis()); return; } double gravParameter = currentBody.getGravitationalParameter(); @@ -111,7 +148,7 @@ public void matchOrbitApoapsis() { try { Orbit targetOrbit = getTargetOrbit(); System.out.println(targetOrbit.getApoapsis() + "-- APO"); - Node maneuver = hohmannTransferToOrbit(targetOrbit.getApoapsis(), + Node maneuver = biEllipticTransferToOrbit(targetOrbit.getApoapsis(), getNaveAtual().getOrbit().getTimeToPeriapsis()); while (true) { if (Thread.interrupted()) { @@ -124,37 +161,16 @@ public void matchOrbitApoapsis() { break; } double dvPrograde = maneuver.getPrograde(); - double ctrlOutput = ctrlManeuver.calcPID(currentDeltaApo, 0); + double ctrlOutput = ctrlManeuver.calculate(currentDeltaApo, 0); maneuver.setPrograde(dvPrograde - (ctrlOutput)); - Thread.sleep(50); + Thread.sleep(25); } } catch (Exception e) { setCurrentStatus("Não foi possivel ajustar a inclinação"); } } - private Node hohmannTransferToOrbit(double targetAltitude, double timeToStart) { - double[] totalDv = { 0, 0, 0 }; - try { - double startingRadius = Math.max(getNaveAtual().getOrbit().getApoapsis(), - getNaveAtual().getOrbit().getPeriapsis()); - System.out.println(startingRadius + " --- " + targetAltitude); - double gravParameter = currentBody.getGravitationalParameter(); - // Delta-v required to leave the current orbit - double deltaV1 = Math.sqrt(2 * gravParameter / startingRadius) - Math.sqrt(gravParameter / startingRadius); - // Delta-v required to enter the target orbit - double deltaV2 = Math.sqrt(gravParameter / targetAltitude) - Math.sqrt(2 * gravParameter / targetAltitude); - System.out.println(deltaV1); - System.out.println(deltaV2); - - // Dv taken between the two points - totalDv[0] = deltaV2 + deltaV1; - } catch (RPCException e) { - } - return createManeuver(timeToStart, totalDv); - } - private Node createManeuverAtClosestIncNode(Orbit targetOrbit) { double uTatClosestNode = 1; double[] dv = { 0, 0, 0 }; @@ -173,36 +189,148 @@ private double[] getTimeToIncNodes(Orbit targetOrbit) throws RPCException { return new double[] { vesselOrbit.uTAtTrueAnomaly(ascendingNode), vesselOrbit.uTAtTrueAnomaly(descendingNode) }; } - public void alignPlanes() { + private void alignPlanesWithTargetVessel() { try { - Orbit targetOrbit = getTargetOrbit(); - Node maneuver = createManeuverAtClosestIncNode(targetOrbit); - double[] incNodesUt = getTimeToIncNodes(targetOrbit); + 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]; - double timeToExecute = 0; - while (timeToExecute < 5000) { - if (Thread.interrupted()) { - throw new InterruptedException(); - } - double currentDeltaInc = compareOrbitParameter(maneuver.getOrbit(), targetOrbit, Compare.INC); - String deltaIncFormatted = String.format("%.2f", currentDeltaInc); - System.out.println(deltaIncFormatted); - if (deltaIncFormatted.equals(String.format("%.2f", 10.00))) { - break; + 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); + } } - double dvNormal = maneuver.getNormal(); - double ctrlOutput = ctrlManeuver.calcPID(currentDeltaInc, 10.0);// * limitPIDOutput(Math.abs - // (currentDeltaInc)); - if ((closestIsAN ? currentDeltaInc : -currentDeltaInc) > 0.0) { - maneuver.setNormal(dvNormal + (ctrlOutput)); - } else { - maneuver.setNormal(dvNormal - (ctrlOutput)); + + 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); + } } - timeToExecute += 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); } - } catch (Exception e) { - setCurrentStatus("Não foi possivel ajustar a inclinação"); + // 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) { } } @@ -331,31 +459,33 @@ public void executeBurn(Node noDeManobra, double duracaoDaQueima) { Thread.sleep(100); } // Executar a manobra: - Stream> queimaRestante = getConnection().addStream(noDeManobra, + 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 (queimaRestante.get().getValue1() < (fineAdjustment ? 2 : 0.5)) { + if (burnDvLeft < (fineAdjustment ? 2 : 0.5)) { throttle(0.0f); break; } navigation.aimAtManeuver(noDeManobra); - throttle(ctrlManeuver.calcPID((noDeManobra.getDeltaV() - Math.floor(queimaRestante.get().getValue1())) / - noDeManobra.getDeltaV() * 1000, 1000)); - Thread.sleep(50); + 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(queimaRestante); + adjustManeuverWithRCS(remainingBurn); } ap.setReferenceFrame(surfaceReferenceFrame); ap.disengage(); getNaveAtual().getControl().setSAS(true); getNaveAtual().getControl().setRCS(false); - queimaRestante.remove(); + remainingBurn.remove(); noDeManobra.remove(); setCurrentStatus(Bundle.getString("status_ready")); } catch (StreamException | RPCException e) { @@ -372,7 +502,7 @@ private void adjustManeuverWithRCS(Stream> remai if (Thread.interrupted()) { throw new InterruptedException(); } - getNaveAtual().getControl().setForward((float) ctrlRCS.calcPID(-remainingDeltaV.get().getValue1() * 10, + getNaveAtual().getControl().setForward((float) ctrlRCS.calculate(-remainingDeltaV.get().getValue1() * 10, 0)); Thread.sleep(25); } @@ -397,8 +527,29 @@ private boolean canFineAdjust(String string) { return false; } + private double calculatePhaseAngle(Triplet startPos, Triplet endPos) + throws RPCException, InterruptedException { + double targetPhaseAngle = 10; + double angularDifference = 15; + Vector startPosition = new Vector(startPos); + Vector endPosition = new Vector(endPos); + + // Phase angle + double dot = endPosition.dotProduct(startPosition); + double det = endPosition.determinant(startPosition); + targetPhaseAngle = Math.atan2(det, dot); + + double targetOrbit = endPosition.magnitude(); + + double activeVesselSMA = getNaveAtual().getOrbit().getSemiMajorAxis(); + angularDifference = targetPhaseAngle + Math.PI + * (1 - (1 / (2 * Math.sqrt(2))) * Math.sqrt(Math.pow((activeVesselSMA / targetOrbit + 1), 3))); + + return Math.abs(angularDifference); + } + enum Compare { INC, AP, PE } -} \ No newline at end of file +} diff --git a/src/com/pesterenan/controllers/RoverController.java b/src/main/java/com/pesterenan/controllers/RoverController.java similarity index 98% rename from src/com/pesterenan/controllers/RoverController.java rename to src/main/java/com/pesterenan/controllers/RoverController.java index f094e68..aeab195 100644 --- a/src/com/pesterenan/controllers/RoverController.java +++ b/src/main/java/com/pesterenan/controllers/RoverController.java @@ -45,8 +45,8 @@ private void initializeParameters() { roverReferenceFrame = getNaveAtual().getReferenceFrame(); roverDirection = new Vector(getNaveAtual().direction(roverReferenceFrame)); pathFinding = new PathFinding(); - acelCtrl.adjustOutput(0, 1); - sterringCtrl.adjustOutput(-1, 1); + acelCtrl.setOutput(0, 1); + sterringCtrl.setOutput(-1, 1); isAutoRoverRunning = true; } catch (RPCException ignored) { } @@ -206,10 +206,10 @@ private void driveRover() throws RPCException, IOException, StreamException { double deltaAngle = Math.abs(targetAndRadarAngle - roverAngle); getNaveAtual().getControl().setSAS(deltaAngle < 1); // Control Rover Throttle - setRoverThrottle(acelCtrl.calcPID(velHorizontal.get() / maxSpeed * 50, 50)); + setRoverThrottle(acelCtrl.calculate(velHorizontal.get() / maxSpeed * 50, 50)); // Control Rover Steering if (deltaAngle > 1) { - setRoverSteering(sterringCtrl.calcPID(roverAngle / (targetAndRadarAngle) * 100, 100)); + setRoverSteering(sterringCtrl.calculate(roverAngle / (targetAndRadarAngle) * 100, 100)); } else { setRoverSteering(0.0f); } @@ -314,4 +314,4 @@ private void setRoverSteering(double steering) throws RPCException { private enum MODE { DRIVE, NEXT_POINT, CHARGING } -} \ No newline at end of file +} diff --git a/src/com/pesterenan/model/ActiveVessel.java b/src/main/java/com/pesterenan/model/ActiveVessel.java similarity index 95% rename from src/com/pesterenan/model/ActiveVessel.java rename to src/main/java/com/pesterenan/model/ActiveVessel.java index 2fd88d1..99efa65 100644 --- a/src/com/pesterenan/model/ActiveVessel.java +++ b/src/main/java/com/pesterenan/model/ActiveVessel.java @@ -6,6 +6,7 @@ import com.pesterenan.controllers.LiftoffController; import com.pesterenan.controllers.ManeuverController; import com.pesterenan.controllers.RoverController; +import com.pesterenan.controllers.DockingController; import com.pesterenan.resources.Bundle; import com.pesterenan.utils.Modulos; import com.pesterenan.utils.Telemetry; @@ -182,7 +183,7 @@ public void startModule(Map commands) { controller = new LandingController(commands); runningModule = true; } - if (currentFunction.equals(Modulos.MODULO_EXEC_MANOBRAS.get())) { + if (currentFunction.equals(Modulos.MODULE_MANEUVER.get())) { controller = new ManeuverController(commands); runningModule = true; } @@ -190,6 +191,11 @@ public void startModule(Map commands) { controller = new RoverController(commands); runningModule = true; } + if (currentFunction.equals(Modulos.MODULO_DOCKING.get())) { + controller = new DockingController(commands); + System.out.println("escolheu modulo docking"); + runningModule = true; + } controllerThread = new Thread(controller, currentVesselId + " - " + currentFunction); controllerThread.start(); } @@ -227,7 +233,7 @@ public void cancelControl() { } } - public boolean hasModuleRunning() { - return runningModule; - } + public boolean hasModuleRunning() { + return runningModule; + } } diff --git a/src/com/pesterenan/resources/Bundle.java b/src/main/java/com/pesterenan/resources/Bundle.java similarity index 73% rename from src/com/pesterenan/resources/Bundle.java rename to src/main/java/com/pesterenan/resources/Bundle.java index 5866198..3523229 100644 --- a/src/com/pesterenan/resources/Bundle.java +++ b/src/main/java/com/pesterenan/resources/Bundle.java @@ -1,12 +1,12 @@ package com.pesterenan.resources; +import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; public class Bundle { - public static final String BUNDLE_NAME = Bundle.class.getPackage().getName() + ".MechPesteBundle"; //$NON-NLS-1$ - - public static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME); + public static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle("MechPesteBundle", + Locale.getDefault()); private Bundle() { } diff --git a/src/com/pesterenan/updater/KrpcInstaller.java b/src/main/java/com/pesterenan/updater/KrpcInstaller.java similarity index 94% rename from src/com/pesterenan/updater/KrpcInstaller.java rename to src/main/java/com/pesterenan/updater/KrpcInstaller.java index 7d548c5..76e835f 100644 --- a/src/com/pesterenan/updater/KrpcInstaller.java +++ b/src/main/java/com/pesterenan/updater/KrpcInstaller.java @@ -16,8 +16,7 @@ public class KrpcInstaller { static final int BUFFER = 2048; - private static final String KRPC_GITHUB_LINK = - "https://github.com/krpc/krpc/releases/download/v0.5.1/krpc-0.5.1.zip"; + 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; public static String getKspFolder() { @@ -43,7 +42,7 @@ public static void downloadKrpc() { krpcLink = new URL(KRPC_GITHUB_LINK); ReadableByteChannel readableByteChannel = Channels.newChannel(krpcLink.openStream()); - FileOutputStream fos = new FileOutputStream(KSP_FOLDER + "\\krpc-0.5.1.zip"); + FileOutputStream fos = new FileOutputStream(KSP_FOLDER + "\\krpc-0.5.2.zip"); fos.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE); fos.close(); @@ -60,7 +59,7 @@ public static void unzipKrpc() { } BufferedOutputStream dest; // zipped input - FileInputStream fis = new FileInputStream(KSP_FOLDER + "\\krpc-0.5.1.zip"); + 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) { @@ -91,4 +90,4 @@ public static void unzipKrpc() { } } -} \ No newline at end of file +} diff --git a/src/main/java/com/pesterenan/utils/Attributes.java b/src/main/java/com/pesterenan/utils/Attributes.java new file mode 100644 index 0000000..1046b85 --- /dev/null +++ b/src/main/java/com/pesterenan/utils/Attributes.java @@ -0,0 +1,33 @@ +package com.pesterenan.utils; + +import java.util.HashMap; +import java.util.Map; + +public class Attributes { + + private static Map safeLowOrbitAltitudes = new HashMap(); + + public Attributes() { + safeLowOrbitAltitudes.put("Bop", 10_000.0); + safeLowOrbitAltitudes.put("Dres", 20_000.0); + safeLowOrbitAltitudes.put("Duna", 60_000.0); + safeLowOrbitAltitudes.put("Eeloo", 20_000.0); + safeLowOrbitAltitudes.put("Eve", 100_000.0); + safeLowOrbitAltitudes.put("Gilly", 10_000.0); + safeLowOrbitAltitudes.put("Ike", 20_000.0); + safeLowOrbitAltitudes.put("Jool", 220_000.0); + safeLowOrbitAltitudes.put("Kerbin", 80_000.0); + safeLowOrbitAltitudes.put("Laythe", 80_000.0); + safeLowOrbitAltitudes.put("Minmus", 10_000.0); + safeLowOrbitAltitudes.put("Moho", 35_000.0); + safeLowOrbitAltitudes.put("Mun", 10_000.0); + safeLowOrbitAltitudes.put("Pol", 10_000.0); + safeLowOrbitAltitudes.put("Sun", 350_000.0); + safeLowOrbitAltitudes.put("Tylo", 40_000.0); + safeLowOrbitAltitudes.put("Vall", 20_000.0); + } + + public double getLowOrbitAltitude(String celestialBody) { + return safeLowOrbitAltitudes.getOrDefault(celestialBody, 10_000.0); + }; +} diff --git a/src/main/java/com/pesterenan/utils/ControlePID.java b/src/main/java/com/pesterenan/utils/ControlePID.java new file mode 100644 index 0000000..51ea12f --- /dev/null +++ b/src/main/java/com/pesterenan/utils/ControlePID.java @@ -0,0 +1,104 @@ +package com.pesterenan.utils; + +import krpc.client.RPCException; +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(); + } + } + +} diff --git a/src/com/pesterenan/utils/Modulos.java b/src/main/java/com/pesterenan/utils/Modulos.java similarity index 87% rename from src/com/pesterenan/utils/Modulos.java rename to src/main/java/com/pesterenan/utils/Modulos.java index 85222ba..f31f409 100644 --- a/src/com/pesterenan/utils/Modulos.java +++ b/src/main/java/com/pesterenan/utils/Modulos.java @@ -18,21 +18,23 @@ public enum Modulos { MAX_TWR("Max_TWR"), MODULO_CRIAR_MANOBRAS("CRIAR_MANOBRAS"), MODULO_DECOLAGEM("LIFTOFF"), - MODULO_EXEC_MANOBRAS("MANEUVER"), + MODULE_MANEUVER("MANEUVER"), MODULO_POUSO_SOBREVOAR("HOVER"), MODULO_POUSO("LANDING"), MODULO_ROVER("ROVER"), + MODULO_DOCKING("DOCKING"), MODULO_TELEMETRIA("TELEMETRY"), MODULO("Módulo"), NAVE_ALVO("Nave alvo"), NOME_MARCADOR("Nome do marcador"), ORBITA_BAIXA("ÓRBITA BAIXA"), PERIASTRO("Periastro"), - POUSAR("Pousar nave"), + POUSAR("Pousar nave"), QUADRATICA("Quadrática"), + RENDEZVOUS("Rendezvous"), ROLAGEM("Rolagem"), SINUSOIDAL("Sinusoidal"), - SOBREVOO_POS_POUSO("SOBREVOO PÓS POUSO"), + SOBREVOO_POS_POUSO("SOBREVOO PÓS POUSO"), TIPO_ALVO_ROVER("Tipo de Alvo do Rover"), USAR_ESTAGIOS("Usar Estágios"), VELOCIDADE_MAX("Velocidade Máxima"); diff --git a/src/main/java/com/pesterenan/utils/Navigation.java b/src/main/java/com/pesterenan/utils/Navigation.java new file mode 100644 index 0000000..389b33e --- /dev/null +++ b/src/main/java/com/pesterenan/utils/Navigation.java @@ -0,0 +1,158 @@ +package com.pesterenan.utils; + +import krpc.client.RPCException; +import krpc.client.Stream; +import krpc.client.StreamException; +import org.javatuples.Triplet; + +import static com.pesterenan.MechPeste.getConnection; +import static com.pesterenan.MechPeste.getSpaceCenter; +import static krpc.client.services.SpaceCenter.*; + +public class Navigation { + + public static final Triplet RADIAL = new Triplet<>(1.0, 0.0, 0.0); + public static final Triplet ANTI_RADIAL = new Triplet<>(-1.0, 0.0, 0.0); + public static final Triplet PROGRADE = new Triplet<>(0.0, 1.0, 0.0); + public static final Triplet RETROGRADE = new Triplet<>(0.0, -1.0, 0.0); + public static final Triplet NORMAL = new Triplet<>(0.0, 0.0, 1.0); + public static final Triplet ANTI_NORMAL = new Triplet<>(0.0, 0.0, -1.0); + // private Drawing drawing; + private Vessel currentVessel; + private Flight flightParameters; + private Stream horizontalSpeed; + private ReferenceFrame orbitalReference; + + public Navigation(Vessel currentVessel) { + this.currentVessel = currentVessel; + initializeParameters(); + } + + 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 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 aimAtPrograde() throws RPCException { + aimAtDirection(getSpaceCenter().transformDirection(PROGRADE, currentVessel.getSurfaceVelocityReferenceFrame(), + 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 aimAtDirection(Triplet currentDirection) throws RPCException { + currentVessel.getAutoPilot().setReferenceFrame(orbitalReference); + currentVessel.getAutoPilot().setTargetDirection(currentDirection); + } + +} diff --git a/src/com/pesterenan/utils/PathFinding.java b/src/main/java/com/pesterenan/utils/PathFinding.java similarity index 74% rename from src/com/pesterenan/utils/PathFinding.java rename to src/main/java/com/pesterenan/utils/PathFinding.java index 56d2fcd..f5848e0 100644 --- a/src/com/pesterenan/utils/PathFinding.java +++ b/src/main/java/com/pesterenan/utils/PathFinding.java @@ -44,8 +44,8 @@ private void initializeParameters() { public void addWaypointsOnSameBody(String waypointName) throws RPCException { this.waypointName = waypointName; - this.waypointsToReach = - waypointManager.getWaypoints().stream().filter(this::hasSameName).collect(Collectors.toList()); + this.waypointsToReach = waypointManager.getWaypoints().stream().filter(this::hasSameName) + .collect(Collectors.toList()); } private boolean hasSameName(Waypoint waypoint) { @@ -63,26 +63,25 @@ public Vector findNearestWaypoint() throws RPCException, IOException, Interrupte double w2Distance = 0; try { w1Distance = Vector.distance(new Vector(getNaveAtual().position(orbitalReferenceFrame)), - waypointPosOnSurface(w1) - ); + waypointPosOnSurface(w1)); w2Distance = Vector.distance(new Vector(getNaveAtual().position(orbitalReferenceFrame)), - waypointPosOnSurface(w2) - ); + 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; -// } -// } + // 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); } @@ -125,7 +124,8 @@ public void removeWaypointFromList() throws RPCException { } /** - * Builds the path to the targetPosition, on the Celestial Body Reference ( Orbital Ref ) + * 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 @@ -133,10 +133,11 @@ public void removeWaypointFromList() 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: + // 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)); + 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 @@ -148,14 +149,12 @@ public void buildPathToTarget(Vector targetPosition) throws IOException, RPCExce throw new InterruptedException(); } Vector currentPoint = pathToTarget.get(index); - Vector targetDirection = - transformOrbToSurf(targetPosition).subtract(transformOrbToSurf(currentPoint)).normalize(); - Vector nextPoint = - transformSurfToOrb(calculateNextPoint(transformOrbToSurf(currentPoint), targetDirection)); + 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)); + double distanceBetweenPoints = Vector.distance(transformOrbToSurf(currentPoint), transformOrbToSurf(nextPoint)); distanceToTarget -= distanceBetweenPoints; } pathToTarget.add(getPosOnSurface(targetPosition)); @@ -163,12 +162,11 @@ public void buildPathToTarget(Vector targetPosition) throws IOException, RPCExce } private void drawPathToTarget(List path) throws RPCException { - Deque> drawablePath = - path.stream().map(Vector::toTriplet).collect(Collectors.toCollection(ArrayDeque::new)); + 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 = drawing.addPolygon(drawablePath.stream().collect(Collectors.toList()), orbitalReferenceFrame, true); polygonPath.setThickness(0.5f); polygonPath.setColor(new Triplet<>(1.0, 0.5, 0.0)); } @@ -184,25 +182,22 @@ private Vector calculateNextPoint(Vector currentPoint, Vector targetDirection) t // 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)))); + 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 { + double searchDistance) throws RPCException { return Math.min( getSpaceCenter().raycastDistance(currentPoint.toTriplet(), targetDirection.toTriplet(), reference), - searchDistance - ); + searchDistance); } private Vector getPosOnSurface(Vector vector) throws RPCException { return new Vector( currentBody.surfacePosition(currentBody.latitudeAtPosition(vector.toTriplet(), orbitalReferenceFrame), - currentBody.longitudeAtPosition(vector.toTriplet(), orbitalReferenceFrame), - orbitalReferenceFrame - )); + currentBody.longitudeAtPosition(vector.toTriplet(), orbitalReferenceFrame), + orbitalReferenceFrame)); } private Vector transformSurfToOrb(Vector vector) throws IOException, RPCException { diff --git a/src/com/pesterenan/utils/Telemetry.java b/src/main/java/com/pesterenan/utils/Telemetry.java similarity index 100% rename from src/com/pesterenan/utils/Telemetry.java rename to src/main/java/com/pesterenan/utils/Telemetry.java diff --git a/src/com/pesterenan/utils/Utilities.java b/src/main/java/com/pesterenan/utils/Utilities.java similarity index 96% rename from src/com/pesterenan/utils/Utilities.java rename to src/main/java/com/pesterenan/utils/Utilities.java index d3be012..86bdccc 100644 --- a/src/com/pesterenan/utils/Utilities.java +++ b/src/main/java/com/pesterenan/utils/Utilities.java @@ -27,7 +27,7 @@ public static Vector inverseLinearInterpolation(Vector start, Vector end, double } public static double remap(double inputMin, double inputMax, double outputMin, double outputMax, double value, - boolean clampOutput) { + boolean clampOutput) { double between = inverseLinearInterpolation(inputMin, inputMax, value); double remappedOutput = linearInterpolation(outputMin, outputMax, between); return clampOutput ? clamp(remappedOutput, outputMin, outputMax) : remappedOutput; @@ -78,7 +78,6 @@ public String formatElapsedTime(Double totalSeconds) { 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$ + seconds); // $NON-NLS-1$ } } diff --git a/src/com/pesterenan/utils/Vector.java b/src/main/java/com/pesterenan/utils/Vector.java similarity index 93% rename from src/com/pesterenan/utils/Vector.java rename to src/main/java/com/pesterenan/utils/Vector.java index c47661d..06c69e4 100644 --- a/src/com/pesterenan/utils/Vector.java +++ b/src/main/java/com/pesterenan/utils/Vector.java @@ -66,7 +66,7 @@ public static double distance(Vector start, Vector end) { * @param start - Vetor contendo os componentes da posição do ponto de origem. * @param end - Vetor contendo os componentes da posição do alvo. * @return - Vetor com a soma dos valores do ponto de origem com os valores do - * alvo. + * alvo. */ public static Vector targetDirection(Vector start, Vector end) { return end.subtract(start).normalize(); @@ -78,7 +78,7 @@ public static Vector targetDirection(Vector start, Vector end) { * @param start - Tupla contendo os componentes da posição do ponto de origem. * @param end - Tupla contendo os componentes da posição do alvo. * @return - Vetor inverso, com a soma dos valores do ponto de origem com o - * negativo dos valores do alvo. + * negativo dos valores do alvo. */ public static Vector targetOppositeDirection(Vector start, Vector end) { return end.subtract(start).multiply(-1).normalize(); @@ -151,12 +151,13 @@ public Vector normalize() { * @param otherVector - Vetor para somar os componentes * @return Novo vetor com a soma dos componentes dos dois */ - public double dotP(Vector otherVector) { + + public double dotProduct(Vector otherVector) { return (x * otherVector.x + y * otherVector.y + z * otherVector.z); } public double determinant(Vector otherVector) { - return (x * otherVector.y - y * otherVector.x - z * otherVector.z); + return (x * otherVector.z - y * otherVector.y - z * otherVector.x); } /** @@ -184,8 +185,8 @@ public Vector subtract(Vector otherVector) { * * @param scalar - Fator para multiplicar os componentes * @return Novo vetor com os componentes multiplicados pela escalar. Caso a - * escalar informada for 0, o Vetor retornado terá 0 como seus - * componentes. + * escalar informada for 0, o Vetor retornado terá 0 como seus + * componentes. */ public Vector multiply(double scalar) { if (scalar != 0) { @@ -199,7 +200,7 @@ public Vector multiply(double scalar) { * * @param scalar - Fator para dividir os componentes * @return Novo vetor com os componentes divididos pela escalar. Caso a escalar - * informada for 0, o Vetor retornado terá 0 como seus componentes. + * informada for 0, o Vetor retornado terá 0 como seus componentes. */ public Vector divide(double scalar) { if (scalar != 0) { diff --git a/src/main/java/com/pesterenan/utils/VersionUtil.java b/src/main/java/com/pesterenan/utils/VersionUtil.java new file mode 100644 index 0000000..a6084ca --- /dev/null +++ b/src/main/java/com/pesterenan/utils/VersionUtil.java @@ -0,0 +1,32 @@ +package com.pesterenan.utils; + +import java.io.File; +import java.io.FileReader; +import java.io.InputStreamReader; + +import org.apache.maven.model.Model; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; + +public class VersionUtil { + public static String getVersion() { + String version = "N/A"; + MavenXpp3Reader reader = new MavenXpp3Reader(); + Model model; + try { + if ((new File("pom.xml")).exists()) { + model = reader.read(new FileReader("pom.xml")); + } else { + model = reader.read( + new InputStreamReader( + VersionUtil.class.getResourceAsStream( + "/META-INF/maven/com.pesterenan/MechPeste/pom.xml"))); + } + version = model.getVersion(); + return version; + } catch (Exception e) { + e.printStackTrace(); + + } + return version; + } +} diff --git a/src/com/pesterenan/views/AboutJFrame.java b/src/main/java/com/pesterenan/views/AboutJFrame.java similarity index 95% rename from src/com/pesterenan/views/AboutJFrame.java rename to src/main/java/com/pesterenan/views/AboutJFrame.java index 7c3d2eb..e402033 100644 --- a/src/com/pesterenan/views/AboutJFrame.java +++ b/src/main/java/com/pesterenan/views/AboutJFrame.java @@ -9,6 +9,8 @@ import javax.swing.JLabel; import javax.swing.JPanel; +import com.pesterenan.utils.VersionUtil; + import static com.pesterenan.views.MainGui.BTN_DIMENSION; import static com.pesterenan.views.MainGui.centerDialogOnScreen; import static com.pesterenan.views.MainGui.createMarginComponent; @@ -28,7 +30,7 @@ public AboutJFrame() { @Override public void initComponents() { // Labels: - lblMechpeste = new JLabel("MechPeste - v.0.6.2"); + 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
" diff --git a/src/com/pesterenan/views/ChangeVesselDialog.java b/src/main/java/com/pesterenan/views/ChangeVesselDialog.java similarity index 99% rename from src/com/pesterenan/views/ChangeVesselDialog.java rename to src/main/java/com/pesterenan/views/ChangeVesselDialog.java index 527b9ab..3702480 100644 --- a/src/com/pesterenan/views/ChangeVesselDialog.java +++ b/src/main/java/com/pesterenan/views/ChangeVesselDialog.java @@ -99,7 +99,6 @@ public void layoutComponents() { pnlScroll.add(scrollPane); pnlScroll.add(Box.createHorizontalStrut(190)); - JPanel pnlOptionsAndList = new JPanel(); pnlOptionsAndList.setLayout(new BoxLayout(pnlOptionsAndList, BoxLayout.X_AXIS)); pnlOptions.setAlignmentY(TOP_ALIGNMENT); diff --git a/src/main/java/com/pesterenan/views/CreateManeuverJPanel.java b/src/main/java/com/pesterenan/views/CreateManeuverJPanel.java new file mode 100644 index 0000000..6c3a5ae --- /dev/null +++ b/src/main/java/com/pesterenan/views/CreateManeuverJPanel.java @@ -0,0 +1,442 @@ +package com.pesterenan.views; + +import com.pesterenan.MechPeste; +import com.pesterenan.resources.Bundle; +import com.pesterenan.utils.ControlePID; + +import krpc.client.RPCException; +import krpc.client.services.SpaceCenter.Node; +import krpc.client.services.SpaceCenter.Orbit; +import krpc.client.services.SpaceCenter.Vessel; +import krpc.client.services.SpaceCenter.VesselSituation; + +import javax.swing.*; +import javax.swing.border.TitledBorder; + +import org.javatuples.Pair; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Map; + +import static com.pesterenan.views.MainGui.PNL_DIMENSION; +import static com.pesterenan.views.MainGui.BTN_DIMENSION; + +public class CreateManeuverJPanel extends JPanel implements ActionListener, UIMethods { + + private static JLabel lblManeuverInfo; + private static JButton btnCreateManeuver, btnDeleteManeuver, btnBack, btnAp, btnPe, btnAN, btnDN; + private static JButton btnIncrease, btnDecrease, btnNextOrbit, btnPrevOrbit; + private static JSlider sldScale; + private static JList listCurrentManeuvers; + private static int selectedManeuverIndex = 0; + private static JRadioButton rbPrograde, rbNormal, rbRadial, rbTime; + private static ButtonGroup bgManeuverType; + private static Map sliderValues = new HashMap<>(); + private final ControlePID ctrlManeuver = new ControlePID(); + + public CreateManeuverJPanel() { + initComponents(); + setupComponents(); + layoutComponents(); + } + + @Override + public void initComponents() { + // Labels: + lblManeuverInfo = new JLabel(""); + + // Buttons: + btnCreateManeuver = new JButton("Criar"); + btnDeleteManeuver = new JButton("Apagar"); + btnAp = new JButton("AP"); + btnPe = new JButton("PE"); + btnAN = new JButton("NA"); + btnDN = new JButton("ND"); + btnBack = new JButton(Bundle.getString("pnl_mnv_btn_back")); + btnIncrease = new JButton("+"); + btnDecrease = new JButton("-"); + btnNextOrbit = new JButton(">"); + btnPrevOrbit = new JButton("<"); + + // Radio buttons: + rbPrograde = new JRadioButton("Pro"); + rbNormal = new JRadioButton("Nor"); + rbRadial = new JRadioButton("Rad"); + rbTime = new JRadioButton("Tmp"); + + // Misc: + listCurrentManeuvers = new JList<>(); + sldScale = new JSlider(JSlider.VERTICAL, 0, 5, 2); + bgManeuverType = new ButtonGroup(); + sliderValues.put(0, 0.01f); + sliderValues.put(1, 0.1f); + sliderValues.put(2, 1f); + sliderValues.put(3, 10f); + sliderValues.put(4, 100f); + sliderValues.put(5, 1000f); + + ctrlManeuver.setOutput(-100, 100); + } + + @Override + public void setupComponents() { + // Setting-up components: + btnCreateManeuver.addActionListener(this); + btnCreateManeuver.setMaximumSize(BTN_DIMENSION); + btnCreateManeuver.setPreferredSize(BTN_DIMENSION); + btnDeleteManeuver.addActionListener(this); + btnDeleteManeuver.setMaximumSize(BTN_DIMENSION); + btnDeleteManeuver.setPreferredSize(BTN_DIMENSION); + btnAp.addActionListener(this); + btnAp.setActionCommand("apoapsis"); + btnPe.addActionListener(this); + btnPe.setActionCommand("periapsis"); + btnAN.addActionListener(this); + btnAN.setActionCommand("ascending"); + btnDN.addActionListener(this); + btnDN.setActionCommand("descending"); + btnBack.addActionListener(this); + btnBack.setMaximumSize(BTN_DIMENSION); + btnBack.setPreferredSize(BTN_DIMENSION); + btnIncrease.setActionCommand("increase"); + btnIncrease.addActionListener(this); + btnIncrease.addMouseWheelListener(e -> { + int rotation = e.getWheelRotation(); + if (rotation > 0) { + changeManeuverDeltaV(btnDecrease.getActionCommand()); + } else { + changeManeuverDeltaV(btnIncrease.getActionCommand()); + } + }); + btnIncrease.setMaximumSize(new Dimension(70, 26)); + btnIncrease.setPreferredSize(new Dimension(70, 26)); + btnIncrease.setMargin(new Insets(0, 0, 0, 0)); + btnDecrease.setActionCommand("decrease"); + btnDecrease.addActionListener(this); + btnDecrease.addMouseWheelListener(e -> { + int rotation = e.getWheelRotation(); + if (rotation > 0) { + changeManeuverDeltaV(btnIncrease.getActionCommand()); + } else { + changeManeuverDeltaV(btnDecrease.getActionCommand()); + } + }); + btnDecrease.setMaximumSize(new Dimension(70, 26)); + btnDecrease.setPreferredSize(new Dimension(70, 26)); + btnDecrease.setMargin(new Insets(0, 0, 0, 0)); + btnNextOrbit.setActionCommand("next_orbit"); + btnNextOrbit.addActionListener(this); + btnNextOrbit.setMaximumSize(new Dimension(35, 26)); + btnNextOrbit.setPreferredSize(new Dimension(35, 26)); + btnNextOrbit.setMargin(new Insets(0, 0, 0, 0)); + btnPrevOrbit.setActionCommand("prev_orbit"); + btnPrevOrbit.addActionListener(this); + btnPrevOrbit.setMaximumSize(new Dimension(35, 26)); + btnPrevOrbit.setPreferredSize(new Dimension(35, 26)); + btnPrevOrbit.setMargin(new Insets(0, 0, 0, 0)); + + rbPrograde.setActionCommand("prograde"); + rbPrograde.addChangeListener(e -> handleChangeButtonText(sldScale.getValue())); + rbNormal.setActionCommand("normal"); + rbNormal.addChangeListener(e -> handleChangeButtonText(sldScale.getValue())); + rbRadial.setActionCommand("radial"); + rbRadial.addChangeListener(e -> handleChangeButtonText(sldScale.getValue())); + rbTime.setActionCommand("time"); + rbTime.addChangeListener(e -> handleChangeButtonText(sldScale.getValue())); + bgManeuverType.add(rbPrograde); + bgManeuverType.add(rbNormal); + bgManeuverType.add(rbRadial); + bgManeuverType.add(rbTime); + bgManeuverType.setSelected(rbPrograde.getModel(), true); + + listCurrentManeuvers.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + listCurrentManeuvers.addListSelectionListener(e -> selectedManeuverIndex = e.getFirstIndex()); + + sldScale.setSnapToTicks(true); + sldScale.setPaintTicks(true); + sldScale.setMajorTickSpacing(1); + sldScale.setMinorTickSpacing(1); + sldScale.setPaintLabels(false); + sldScale.addChangeListener(e -> handleChangeButtonText(sldScale.getValue())); + sldScale.addMouseWheelListener(e -> { + int rotation = e.getWheelRotation(); + if (rotation < 0) { + sldScale.setValue(sldScale.getValue() + sldScale.getMinorTickSpacing()); + } else { + sldScale.setValue(sldScale.getValue() - sldScale.getMinorTickSpacing()); + } + }); + } + + @Override + public void layoutComponents() { + // Main Panel layout: + setPreferredSize(PNL_DIMENSION); + setSize(PNL_DIMENSION); + setLayout(new BorderLayout()); + + JPanel pnlPositionManeuver = new JPanel(); + pnlPositionManeuver.setLayout(new BoxLayout(pnlPositionManeuver, BoxLayout.X_AXIS)); + pnlPositionManeuver.setBorder(new TitledBorder("Posicionar manobra no:")); + pnlPositionManeuver.add(Box.createHorizontalGlue()); + pnlPositionManeuver.add(btnAp); + pnlPositionManeuver.add(btnPe); + pnlPositionManeuver.add(btnAN); + pnlPositionManeuver.add(btnDN); + pnlPositionManeuver.add(Box.createHorizontalGlue()); + + JPanel pnlRadioButtons = new JPanel(new GridLayout(4, 1)); + pnlRadioButtons.setMaximumSize(new Dimension(50, 100)); + pnlRadioButtons.add(rbPrograde); + pnlRadioButtons.add(rbNormal); + pnlRadioButtons.add(rbRadial); + pnlRadioButtons.add(rbTime); + + JPanel pnlSlider = new JPanel(); + pnlSlider.setLayout(new BoxLayout(pnlSlider, BoxLayout.Y_AXIS)); + pnlSlider.setAlignmentX(Component.LEFT_ALIGNMENT); + pnlSlider.setBorder(new TitledBorder("Escala:")); + pnlSlider.add(sldScale); + pnlSlider.add(Box.createHorizontalStrut(40)); + + JPanel pnlOrbitControl = new JPanel(); + pnlOrbitControl.setLayout(new BoxLayout(pnlOrbitControl, BoxLayout.X_AXIS)); + pnlOrbitControl.setAlignmentX(Component.LEFT_ALIGNMENT); + pnlOrbitControl.add(btnPrevOrbit); + pnlOrbitControl.add(btnNextOrbit); + + JPanel pnlManeuverButtons = new JPanel(); + pnlManeuverButtons.setLayout(new BoxLayout(pnlManeuverButtons, BoxLayout.Y_AXIS)); + pnlManeuverButtons.setAlignmentX(Component.LEFT_ALIGNMENT); + pnlManeuverButtons.add(btnIncrease); + pnlManeuverButtons.add(pnlOrbitControl); + pnlManeuverButtons.add(btnDecrease); + + JPanel pnlManeuverController = new JPanel(); + pnlManeuverController.setLayout(new BoxLayout(pnlManeuverController, BoxLayout.X_AXIS)); + pnlManeuverController.setBorder(new TitledBorder("Controlador de Manobra:")); + pnlManeuverController.setMaximumSize(new Dimension(180, 300)); + pnlManeuverController.add(pnlRadioButtons); + pnlManeuverController.add(pnlSlider); + pnlManeuverController.add(pnlManeuverButtons); + + JPanel pnlManeuverInfo = new JPanel(); + pnlManeuverInfo.setLayout(new BoxLayout(pnlManeuverInfo, BoxLayout.Y_AXIS)); + pnlManeuverInfo.setBorder(new TitledBorder("Info. Manobra:")); + pnlManeuverInfo.setMaximumSize(new Dimension(300, 300)); + + JPanel pnlMCpnlAP = new JPanel(); + pnlMCpnlAP.setLayout(new BoxLayout(pnlMCpnlAP, BoxLayout.X_AXIS)); + pnlMCpnlAP.add(pnlManeuverController); + pnlMCpnlAP.add(pnlManeuverInfo); + + JPanel pnlControls = new JPanel(); + pnlControls.setLayout(new BoxLayout(pnlControls, BoxLayout.Y_AXIS)); + pnlControls.add(pnlPositionManeuver); + pnlControls.add(pnlMCpnlAP); + + JPanel pnlManeuverList = new JPanel(); + pnlManeuverList.setLayout(new BoxLayout(pnlManeuverList, BoxLayout.Y_AXIS)); + JScrollPane scrollPane = new JScrollPane(); + scrollPane.setViewportView(listCurrentManeuvers); + pnlManeuverList.add(scrollPane); + pnlManeuverList.add(btnCreateManeuver); + pnlManeuverList.add(btnDeleteManeuver); + + JPanel pnlOptions = new JPanel(); + pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS)); + pnlOptions.setBorder(new TitledBorder("Lista de Manobras:")); + pnlOptions.add(pnlManeuverList); + pnlOptions.setPreferredSize(new Dimension(110, 300)); + pnlOptions.setMaximumSize(new Dimension(110, 300)); + + JPanel pnlOptionsAndList = new JPanel(); + pnlOptionsAndList.setLayout(new BoxLayout(pnlOptionsAndList, BoxLayout.X_AXIS)); + pnlControls.setAlignmentY(TOP_ALIGNMENT); + pnlOptions.setAlignmentY(TOP_ALIGNMENT); + pnlOptionsAndList.add(pnlOptions); + pnlOptionsAndList.add(Box.createHorizontalStrut(5)); + pnlOptionsAndList.add(pnlControls); + + JPanel pnlBackButton = new JPanel(); + pnlBackButton.setLayout(new BoxLayout(pnlBackButton, BoxLayout.X_AXIS)); + pnlBackButton.add(lblManeuverInfo); + pnlBackButton.add(Box.createHorizontalGlue()); + pnlBackButton.add(btnBack); + + JPanel pnlMain = new JPanel(); + pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS)); + pnlMain.add(pnlOptionsAndList); + + add(pnlMain, BorderLayout.CENTER); + add(pnlBackButton, BorderLayout.SOUTH); + } + + public static void updatePanel(ListModel list) { + try { + boolean hasManeuverNodes = list.getSize() > 0; + boolean hasTargetVessel = MechPeste.getSpaceCenter().getTargetVessel() != null; + listCurrentManeuvers.setModel(list); + listCurrentManeuvers.setSelectedIndex(selectedManeuverIndex); + btnDeleteManeuver.setEnabled(hasManeuverNodes); + btnAp.setEnabled(hasManeuverNodes); + btnPe.setEnabled(hasManeuverNodes); + btnAN.setEnabled(hasManeuverNodes && hasTargetVessel); + btnDN.setEnabled(hasManeuverNodes && hasTargetVessel); + btnIncrease.setEnabled(hasManeuverNodes); + btnDecrease.setEnabled(hasManeuverNodes); + btnNextOrbit.setEnabled(hasManeuverNodes); + btnPrevOrbit.setEnabled(hasManeuverNodes); + lblManeuverInfo.setText(listCurrentManeuvers.getSelectedValue()); + } catch (RPCException ignored) { + } + } + + private static void handleChangeButtonText(int value) { + String decimalPlaces = value > 1 ? "%.0f" : "%.2f"; + String formattedValue = String.format(Locale.ENGLISH, decimalPlaces, sliderValues.get(value)); + String suffix = bgManeuverType.getSelection() == rbTime.getModel() ? " s" : "m/s"; + btnIncrease.setText("+ " + formattedValue + suffix); + btnDecrease.setText("- " + formattedValue + suffix); + } + + private void createManeuver() { + try { + createManeuver(MechPeste.getSpaceCenter().getUT() + 60); + } catch (RPCException e) { + } + } + + private void createManeuver(double atFutureTime) { + try { + MechPeste.newInstance(); + Vessel vessel = MechPeste.getSpaceCenter().getActiveVessel(); + + if (vessel.getSituation() != VesselSituation.ORBITING) { + StatusJPanel.setStatusMessage("Não é possível criar a manobra fora de órbita."); + return; + } + vessel.getControl().addNode(atFutureTime, 0, 0, 0); + } catch (Exception e) { + } + } + + private void deleteManeuver() { + try { + MechPeste.newInstance(); + Vessel vessel = MechPeste.getSpaceCenter().getActiveVessel(); + Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex); + currentManeuver.remove(); + } catch (Exception e) { + } + } + + private void positionManeuverAt(String node) { + try { + MechPeste.newInstance(); + Vessel vessel = MechPeste.getSpaceCenter().getActiveVessel(); + Orbit orbit = vessel.getOrbit(); + Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex); + double timeToNode = 0; + switch (node) { + case "apoapsis": + timeToNode = MechPeste.getSpaceCenter().getUT() + orbit.getTimeToApoapsis(); + break; + case "periapsis": + timeToNode = MechPeste.getSpaceCenter().getUT() + orbit.getTimeToPeriapsis(); + break; + case "ascending": + double ascendingAnomaly = orbit + .trueAnomalyAtAN(MechPeste.getSpaceCenter().getTargetVessel().getOrbit()); + timeToNode = orbit.uTAtTrueAnomaly(ascendingAnomaly); + break; + case "descending": + double descendingAnomaly = orbit + .trueAnomalyAtDN(MechPeste.getSpaceCenter().getTargetVessel().getOrbit()); + timeToNode = orbit.uTAtTrueAnomaly(descendingAnomaly); + break; + } + currentManeuver.setUT(timeToNode); + // Print the maneuver node information + System.out.println("Maneuver Node updated:"); + System.out.println(" Time to node: " + currentManeuver.getTimeTo() + " s"); + } catch (Exception e) { + } + } + + private void changeManeuverDeltaV(String command) { + try { + MechPeste.newInstance(); + Vessel vessel = MechPeste.getSpaceCenter().getActiveVessel(); + Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex); + String maneuverType = bgManeuverType.getSelection().getActionCommand(); + float currentSliderValue = sliderValues.get(sldScale.getValue()); + currentSliderValue = command == "decrease" ? -currentSliderValue : currentSliderValue; + + switch (maneuverType) { + case "prograde": + currentManeuver.setPrograde(currentManeuver.getPrograde() + currentSliderValue); + break; + case "normal": + currentManeuver.setNormal(currentManeuver.getNormal() + currentSliderValue); + break; + case "radial": + currentManeuver.setRadial(currentManeuver.getRadial() + currentSliderValue); + break; + case "time": + currentManeuver.setUT(currentManeuver.getUT() + currentSliderValue); + break; + } + } catch (RPCException e) { + System.err.println("Erro RPC ao mudar o delta-V da manobra: " + e.getMessage()); + } catch (Exception e) { + System.err.println("Erro ao mudar o delta-V da manobra: " + e.getMessage()); + } + + } + + private void changeOrbit(String command) { + try { + MechPeste.newInstance(); + Vessel vessel; + vessel = MechPeste.getSpaceCenter().getActiveVessel(); + Node currentManeuver = vessel.getControl().getNodes().get(selectedManeuverIndex); + double currentOrbitPeriod = vessel.getOrbit().getPeriod(); + if (command == "next_orbit") { + currentManeuver.setUT(currentManeuver.getUT() + currentOrbitPeriod); + } else { + double newUT = currentManeuver.getUT() - currentOrbitPeriod; + newUT = newUT < MechPeste.getSpaceCenter().getUT() ? MechPeste.getSpaceCenter().getUT() + 60 : newUT; + currentManeuver.setUT(newUT); + } + } catch (RPCException ignored) { + } + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == btnCreateManeuver) { + createManeuver(); + } + if (e.getSource() == btnDeleteManeuver) { + deleteManeuver(); + } + if (e.getSource() == btnIncrease || e.getSource() == btnDecrease) { + changeManeuverDeltaV(e.getActionCommand()); + } + if (e.getSource() == btnNextOrbit || e.getSource() == btnPrevOrbit) { + changeOrbit(e.getActionCommand()); + } + if (e.getSource() == btnAp || e.getSource() == btnPe || e.getSource() == btnAN || e.getSource() == btnDN) { + positionManeuverAt(e.getActionCommand()); + } + if (e.getSource() == btnBack) { + MainGui.backToTelemetry(e); + } + } +} diff --git a/src/main/java/com/pesterenan/views/DockingJPanel.java b/src/main/java/com/pesterenan/views/DockingJPanel.java new file mode 100644 index 0000000..26edbb3 --- /dev/null +++ b/src/main/java/com/pesterenan/views/DockingJPanel.java @@ -0,0 +1,122 @@ +package com.pesterenan.views; + +import com.pesterenan.MechPeste; +import com.pesterenan.resources.Bundle; +import com.pesterenan.utils.Modulos; + +import javax.swing.*; +import javax.swing.border.TitledBorder; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.util.HashMap; +import java.util.Map; + +import static com.pesterenan.views.MainGui.BTN_DIMENSION; +import static com.pesterenan.views.MainGui.MARGIN_BORDER_10_PX_LR; +import static com.pesterenan.views.MainGui.PNL_DIMENSION; + +public class DockingJPanel extends JPanel implements UIMethods { + + private static final long serialVersionUID = 0L; + + private JLabel lblMaxSpeed; + private JTextField txfMaxSpeed; + private JButton btnBack, btnStartDocking; + + public DockingJPanel() { + initComponents(); + setupComponents(); + layoutComponents(); + } + + @Override + public void initComponents() { + // Labels: + lblMaxSpeed = new JLabel(Bundle.getString("pnl_rover_lbl_max_speed")); + + // Textfields: + txfMaxSpeed = new JTextField("3"); + + // Buttons: + btnBack = new JButton(Bundle.getString("pnl_rover_btn_back")); + btnStartDocking = new JButton(Bundle.getString("pnl_rover_btn_docking")); + } + + @Override + public void setupComponents() { + // Main Panel setup: + setBorder(new TitledBorder(null, Bundle.getString("btn_func_docking"))); + + // Setting-up components: + txfMaxSpeed.setHorizontalAlignment(SwingConstants.RIGHT); + txfMaxSpeed.setMaximumSize(BTN_DIMENSION); + txfMaxSpeed.setPreferredSize(BTN_DIMENSION); + + btnBack.addActionListener(MainGui::backToTelemetry); + btnBack.setMaximumSize(BTN_DIMENSION); + btnBack.setPreferredSize(BTN_DIMENSION); + btnStartDocking.addActionListener(this::handleStartDocking); + btnStartDocking.setMaximumSize(BTN_DIMENSION); + btnStartDocking.setPreferredSize(BTN_DIMENSION); + } + + @Override + public void layoutComponents() { + // Main Panel layout: + setPreferredSize(PNL_DIMENSION); + setSize(PNL_DIMENSION); + setLayout(new BorderLayout()); + + // Layout components: + JPanel pnlMaxSpeed = new JPanel(); + pnlMaxSpeed.setLayout(new BoxLayout(pnlMaxSpeed, BoxLayout.X_AXIS)); + pnlMaxSpeed.add(lblMaxSpeed); + pnlMaxSpeed.add(Box.createHorizontalGlue()); + pnlMaxSpeed.add(txfMaxSpeed); + + JPanel pnlRoverControls = new JPanel(); + pnlRoverControls.setLayout(new BoxLayout(pnlRoverControls, BoxLayout.Y_AXIS)); + pnlRoverControls.setBorder(MARGIN_BORDER_10_PX_LR); + pnlRoverControls.add(MainGui.createMarginComponent(0, 6)); + pnlRoverControls.add(pnlMaxSpeed); + pnlRoverControls.add(Box.createVerticalGlue()); + + JPanel pnlButtons = new JPanel(); + pnlButtons.setLayout(new BoxLayout(pnlButtons, BoxLayout.X_AXIS)); + pnlButtons.add(btnStartDocking); + pnlButtons.add(Box.createHorizontalGlue()); + pnlButtons.add(btnBack); + + JPanel pnlMain = new JPanel(); + pnlMain.setLayout(new BoxLayout(pnlMain, BoxLayout.X_AXIS)); + pnlRoverControls.setAlignmentY(TOP_ALIGNMENT); + pnlMain.add(pnlRoverControls); + + setLayout(new BorderLayout()); + add(pnlMain, BorderLayout.CENTER); + add(pnlButtons, BorderLayout.SOUTH); + } + + private void handleStartDocking(ActionEvent e) { + System.out.println("chamou startdocking"); + Map commands = new HashMap<>(); + commands.put(Modulos.MODULO.get(), Modulos.MODULO_DOCKING.get()); + commands.put(Modulos.VELOCIDADE_MAX.get(), txfMaxSpeed.getText()); + MechPeste.newInstance().startModule(commands); + } + + private boolean validateTextFields() { + try { + if (Float.parseFloat(txfMaxSpeed.getText()) > 10) { + throw new NumberFormatException(); + } + } catch (NumberFormatException e) { + StatusJPanel.setStatusMessage(Bundle.getString("pnl_rover_max_speed_above_3")); + return false; + } catch (IllegalArgumentException e) { + StatusJPanel.setStatusMessage(Bundle.getString("pnl_rover_waypoint_name_not_empty")); + return false; + } + return true; + } +} diff --git a/src/com/pesterenan/views/FunctionsAndTelemetryJPanel.java b/src/main/java/com/pesterenan/views/FunctionsAndTelemetryJPanel.java similarity index 88% rename from src/com/pesterenan/views/FunctionsAndTelemetryJPanel.java rename to src/main/java/com/pesterenan/views/FunctionsAndTelemetryJPanel.java index aadcb06..5a6dc03 100644 --- a/src/com/pesterenan/views/FunctionsAndTelemetryJPanel.java +++ b/src/main/java/com/pesterenan/views/FunctionsAndTelemetryJPanel.java @@ -21,7 +21,7 @@ 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, btnExecManeuver, btnRover, btnCancel, btnCreateManeuver; + 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; @@ -51,9 +51,9 @@ public void initComponents() { // Buttons: btnLiftoff = new JButton(Bundle.getString("btn_func_liftoff")); btnLanding = new JButton(Bundle.getString("btn_func_landing")); - btnCreateManeuver = new JButton(Bundle.getString("btn_func_create_maneuver")); - btnExecManeuver = new JButton(Bundle.getString("btn_func_exec_maneuver")); + 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")); } @@ -76,19 +76,18 @@ public void setupComponents() { btnLiftoff.setActionCommand(Modulos.MODULO_DECOLAGEM.get()); btnLiftoff.setMaximumSize(btnFuncDimension); btnLiftoff.setPreferredSize(btnFuncDimension); - btnCreateManeuver.addActionListener(this::changeFunctionPanel); - btnCreateManeuver.setActionCommand(Modulos.MODULO_CRIAR_MANOBRAS.get()); - btnCreateManeuver.setMaximumSize(btnFuncDimension); - btnCreateManeuver.setPreferredSize(btnFuncDimension); - btnCreateManeuver.setEnabled(false); - btnExecManeuver.addActionListener(this::changeFunctionPanel); - btnExecManeuver.setActionCommand(Modulos.MODULO_EXEC_MANOBRAS.get()); - btnExecManeuver.setMaximumSize(btnFuncDimension); - btnExecManeuver.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 @@ -100,9 +99,8 @@ public void layoutComponents() { pnlFunctionControls.add(btnLiftoff); pnlFunctionControls.add(btnLanding); pnlFunctionControls.add(btnRover); - pnlFunctionControls.add(MainGui.createMarginComponent(0, 20)); - pnlFunctionControls.add(btnCreateManeuver); - pnlFunctionControls.add(btnExecManeuver); + pnlFunctionControls.add(btnDocking); + pnlFunctionControls.add(btnManeuvers); pnlFunctionControls.add(Box.createVerticalGlue()); JPanel pnlLeftPanel = new JPanel(); diff --git a/src/main/java/com/pesterenan/views/InstallKrpcDialog.java b/src/main/java/com/pesterenan/views/InstallKrpcDialog.java new file mode 100644 index 0000000..a9b0164 --- /dev/null +++ b/src/main/java/com/pesterenan/views/InstallKrpcDialog.java @@ -0,0 +1,200 @@ +package com.pesterenan.views; + +import com.pesterenan.resources.Bundle; +import com.pesterenan.updater.KrpcInstaller; + +import javax.swing.*; +import javax.swing.GroupLayout.Alignment; +import javax.swing.LayoutStyle.ComponentPlacement; +import javax.swing.border.BevelBorder; +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); + } +} diff --git a/src/com/pesterenan/views/LandingJPanel.java b/src/main/java/com/pesterenan/views/LandingJPanel.java similarity index 100% rename from src/com/pesterenan/views/LandingJPanel.java rename to src/main/java/com/pesterenan/views/LandingJPanel.java diff --git a/src/com/pesterenan/views/LiftoffJPanel.java b/src/main/java/com/pesterenan/views/LiftoffJPanel.java similarity index 100% rename from src/com/pesterenan/views/LiftoffJPanel.java rename to src/main/java/com/pesterenan/views/LiftoffJPanel.java diff --git a/src/com/pesterenan/views/MainGui.java b/src/main/java/com/pesterenan/views/MainGui.java similarity index 89% rename from src/com/pesterenan/views/MainGui.java rename to src/main/java/com/pesterenan/views/MainGui.java index 04c903a..f824d7f 100644 --- a/src/com/pesterenan/views/MainGui.java +++ b/src/main/java/com/pesterenan/views/MainGui.java @@ -9,13 +9,11 @@ import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; 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); @@ -28,12 +26,14 @@ public class MainGui extends JFrame implements ActionListener, UIMethods { 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 ManeuverJPanel pnlManeuver; + private CreateManeuverJPanel pnlCreateManeuvers; + private RunManeuverJPanel pnlRunManeuvers; private RoverJPanel pnlRover; + private DockingJPanel pnlDocking; private MainGui() { initComponents(); @@ -54,7 +54,7 @@ public void initComponents() { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception ignored) { } - + // Menu bar menuBar = new JMenuBar(); @@ -62,7 +62,7 @@ public void initComponents() { 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")); @@ -73,8 +73,10 @@ public void initComponents() { pnlFunctionsAndTelemetry = new FunctionsAndTelemetryJPanel(); pnlLiftoff = new LiftoffJPanel(); pnlLanding = new LandingJPanel(); - pnlManeuver = new ManeuverJPanel(); + pnlCreateManeuvers = new CreateManeuverJPanel(); + pnlRunManeuvers = new RunManeuverJPanel(); pnlRover = new RoverJPanel(); + pnlDocking = new DockingJPanel(); pnlStatus = new StatusJPanel(); } @@ -88,7 +90,7 @@ public void setupComponents() { setLocation(100, 100); setContentPane(ctpMainGui); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - + // Setting-up components: mntmAbout.addActionListener(this); mntmChangeVessels.addActionListener(this); @@ -98,7 +100,7 @@ public void setupComponents() { cardJPanels.setPreferredSize(PNL_DIMENSION); cardJPanels.setSize(PNL_DIMENSION); } - + @Override public void layoutComponents() { // Main Panel layout: @@ -120,12 +122,17 @@ public void layoutComponents() { 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(pnlManeuver, Modulos.MODULO_EXEC_MANOBRAS.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) { @@ -172,7 +179,7 @@ public static JPanel getCardJPanels() { public static void changeToPage(ActionEvent e) { cardLayout.show(cardJPanels, e.getActionCommand()); } - + public static void backToTelemetry(ActionEvent e) { cardLayout.show(cardJPanels, Modulos.MODULO_TELEMETRIA.get()); } diff --git a/src/com/pesterenan/views/RoverJPanel.java b/src/main/java/com/pesterenan/views/RoverJPanel.java similarity index 99% rename from src/com/pesterenan/views/RoverJPanel.java rename to src/main/java/com/pesterenan/views/RoverJPanel.java index d9b4d20..8590f82 100644 --- a/src/com/pesterenan/views/RoverJPanel.java +++ b/src/main/java/com/pesterenan/views/RoverJPanel.java @@ -169,4 +169,4 @@ private boolean validateTextFields() { } return true; } -} \ No newline at end of file +} diff --git a/src/com/pesterenan/views/ManeuverJPanel.java b/src/main/java/com/pesterenan/views/RunManeuverJPanel.java similarity index 59% rename from src/com/pesterenan/views/ManeuverJPanel.java rename to src/main/java/com/pesterenan/views/RunManeuverJPanel.java index c0b80e9..037ecd8 100644 --- a/src/com/pesterenan/views/ManeuverJPanel.java +++ b/src/main/java/com/pesterenan/views/RunManeuverJPanel.java @@ -2,8 +2,15 @@ import com.pesterenan.MechPeste; import com.pesterenan.resources.Bundle; +import com.pesterenan.utils.ControlePID; import com.pesterenan.utils.Modulos; +import krpc.client.RPCException; +import krpc.client.services.SpaceCenter.Node; +import krpc.client.services.SpaceCenter.Orbit; +import krpc.client.services.SpaceCenter.Vessel; +import krpc.client.services.SpaceCenter.VesselSituation; + import javax.swing.*; import javax.swing.border.CompoundBorder; import javax.swing.border.TitledBorder; @@ -18,14 +25,15 @@ import static com.pesterenan.views.MainGui.MARGIN_BORDER_10_PX_LR; import static com.pesterenan.views.MainGui.PNL_DIMENSION; -public class ManeuverJPanel extends JPanel implements ActionListener, UIMethods { +public class RunManeuverJPanel extends JPanel implements ActionListener, UIMethods { private static final long serialVersionUID = 1L; - private JLabel lblExecute, lblAdjustInc; - private JButton btnLowerOrbit, btnApoapsis, btnPeriapsis, btnExecute, btnAdjustInc, btnBack; + private JLabel lblExecute; + private JButton btnLowerOrbit, btnApoapsis, btnPeriapsis, btnExecute, btnBack, btnAlignPlanes, btnRendezvous; private JCheckBox chkFineAdjusment; + private final ControlePID ctrlManeuver = new ControlePID(); - public ManeuverJPanel() { + public RunManeuverJPanel() { initComponents(); setupComponents(); layoutComponents(); @@ -33,35 +41,89 @@ public ManeuverJPanel() { public void initComponents() { // Labels: - lblAdjustInc = new JLabel(Bundle.getString("pnl_mnv_lbl_adj_inc")); lblExecute = new JLabel(Bundle.getString("pnl_mnv_lbl_exec_mnv")); // Buttons: - btnAdjustInc = new JButton(Bundle.getString("pnl_mnv_btn_adj_inc")); btnApoapsis = new JButton(Bundle.getString("pnl_mnv_btn_apoapsis")); btnBack = new JButton(Bundle.getString("pnl_mnv_btn_back")); btnExecute = new JButton(Bundle.getString("pnl_mnv_btn_exec_mnv")); btnLowerOrbit = new JButton(Bundle.getString("pnl_mnv_btn_lower_orbit")); btnPeriapsis = new JButton(Bundle.getString("pnl_mnv_btn_periapsis")); + btnAlignPlanes = new JButton("Alinhar planos"); + btnRendezvous = new JButton("Rendezvous"); // Misc: chkFineAdjusment = new JCheckBox(Bundle.getString("pnl_mnv_chk_adj_mnv_rcs")); } - public void setupComponents() { - // Main Panel setup: - setBorder(new TitledBorder(null, Bundle.getString("pnl_mnv_border"), TitledBorder.LEADING, TitledBorder.TOP, - null, null)); + 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: - btnAdjustInc.addActionListener(this); - btnAdjustInc.setActionCommand(Modulos.AJUSTAR.get()); - btnAdjustInc.setEnabled(false); - btnAdjustInc.setMaximumSize(BTN_DIMENSION); - btnAdjustInc.setPreferredSize(BTN_DIMENSION); + 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.setActionCommand(Modulos.APOASTRO.get()); btnApoapsis.setMaximumSize(BTN_DIMENSION); btnApoapsis.setPreferredSize(BTN_DIMENSION); @@ -70,17 +132,14 @@ public void setupComponents() { btnBack.setPreferredSize(BTN_DIMENSION); btnExecute.addActionListener(this); - btnExecute.setActionCommand(Modulos.EXECUTAR.get()); btnExecute.setMaximumSize(BTN_DIMENSION); btnExecute.setPreferredSize(BTN_DIMENSION); btnLowerOrbit.addActionListener(this); - btnLowerOrbit.setActionCommand(Modulos.ORBITA_BAIXA.get()); btnLowerOrbit.setMaximumSize(BTN_DIMENSION); btnLowerOrbit.setPreferredSize(BTN_DIMENSION); btnPeriapsis.addActionListener(this); - btnPeriapsis.setActionCommand(Modulos.PERIASTRO.get()); btnPeriapsis.setMaximumSize(BTN_DIMENSION); btnPeriapsis.setPreferredSize(BTN_DIMENSION); } @@ -98,12 +157,11 @@ public void layoutComponents() { pnlExecuteManeuver.add(MainGui.createMarginComponent(10, 0)); pnlExecuteManeuver.add(btnExecute); - JPanel pnlAdjustInclination = new JPanel(); - pnlAdjustInclination.setLayout(new BoxLayout(pnlAdjustInclination, BoxLayout.X_AXIS)); - pnlAdjustInclination.setBorder(MARGIN_BORDER_10_PX_LR); - pnlAdjustInclination.add(lblAdjustInc); - pnlAdjustInclination.add(Box.createHorizontalGlue()); - pnlAdjustInclination.add(btnAdjustInc); + 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)); @@ -119,7 +177,7 @@ public void layoutComponents() { JPanel pnlSetup = new JPanel(); pnlSetup.setLayout(new BoxLayout(pnlSetup, BoxLayout.Y_AXIS)); pnlSetup.add(pnlExecuteManeuver); - pnlSetup.add(pnlAdjustInclination); + pnlSetup.add(pnlAutoPosition); JPanel pnlOptions = new JPanel(); pnlOptions.setLayout(new BoxLayout(pnlOptions, BoxLayout.Y_AXIS)); @@ -161,9 +219,12 @@ public void actionPerformed(ActionEvent e) { if (e.getSource() == btnPeriapsis) { handleManeuverFunction(Modulos.PERIASTRO.get()); } - if (e.getSource() == btnAdjustInc) { + if (e.getSource() == btnAlignPlanes) { handleManeuverFunction(Modulos.AJUSTAR.get()); } + if (e.getSource() == btnRendezvous) { + handleManeuverFunction(Modulos.RENDEZVOUS.get()); + } if (e.getSource() == btnBack) { MainGui.backToTelemetry(e); } @@ -171,8 +232,8 @@ public void actionPerformed(ActionEvent e) { protected void handleManeuverFunction(String maneuverFunction) { Map commands = new HashMap<>(); - commands.put(Modulos.MODULO.get(), Modulos.MODULO_EXEC_MANOBRAS.get()); - commands.put(Modulos.FUNCAO.get(), maneuverFunction); + 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); } diff --git a/src/com/pesterenan/views/StatusJPanel.java b/src/main/java/com/pesterenan/views/StatusJPanel.java similarity index 100% rename from src/com/pesterenan/views/StatusJPanel.java rename to src/main/java/com/pesterenan/views/StatusJPanel.java diff --git a/src/main/java/com/pesterenan/views/UIMethods.java b/src/main/java/com/pesterenan/views/UIMethods.java new file mode 100644 index 0000000..5338fd0 --- /dev/null +++ b/src/main/java/com/pesterenan/views/UIMethods.java @@ -0,0 +1,10 @@ +package com.pesterenan.views; + +public interface UIMethods { + + public void initComponents(); + + public void setupComponents(); + + public void layoutComponents(); +} diff --git a/src/com/pesterenan/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF similarity index 100% rename from src/com/pesterenan/resources/META-INF/MANIFEST.MF rename to src/main/resources/META-INF/MANIFEST.MF diff --git a/src/com/pesterenan/resources/MechPesteBundle.properties b/src/main/resources/MechPesteBundle.properties similarity index 94% rename from src/com/pesterenan/resources/MechPesteBundle.properties rename to src/main/resources/MechPesteBundle.properties index ee168f7..03fcb5a 100644 --- a/src/com/pesterenan/resources/MechPesteBundle.properties +++ b/src/main/resources/MechPesteBundle.properties @@ -1,15 +1,16 @@ btn_func_landing = Auto Landing btn_func_liftoff = Orbital Liftoff btn_func_create_maneuver = Create Maneuvers -btn_func_exec_maneuver = Exec. Maneuvers +btn_func_maneuver = Maneuvers btn_func_rover = Drive Rover +btn_func_docking = Docking btn_stat_connect = Connect installer_dialog_btn_browse = Browse... installer_dialog_btn_cancel = Cancel 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.1 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.2 version from the original KRPC's Github. lbl_stat_ready = Ready. main_mn_file = File main_mn_help = Help @@ -34,8 +35,8 @@ pnl_land_pnl_hover_border = Hover the area\: pnl_lift_btn_back = Back pnl_lift_btn_liftoff = Lift-off pnl_lift_cb_gravity_curve_tooltip = Choose the type of gravity curve to be performed. Goes from the softest (Sinosoidal) to the most exaggerated (Exponencial). -pnl_lift_chk_open_panels = Open solar panels/radiators after getting to orbit -pnl_lift_chk_open_panels_tooltip = After the circularizing maneuver, opens the solar panels and radiators. +pnl_lift_chk_open_panels = Open solar panels/radiators/antennas after getting to orbit +pnl_lift_chk_open_panels_tooltip = After the circularizing maneuver, opens the solar panels, radiators and deployable antennas. pnl_lift_chk_options = Options\: pnl_lift_chk_staging = Drop stages during liftoff pnl_lift_chk_staging_tooltip = When the ship is going to orbit, if the stage doesn't have any more fuel, it will be staged. @@ -62,6 +63,7 @@ pnl_mnv_lbl_exec_mnv = Execute next maneuver\: pnl_rover_border = Drive Rover\: pnl_rover_btn_back = Back pnl_rover_btn_drive = Drive +pnl_rover_btn_docking = Start Docking pnl_rover_default_name = Target pnl_rover_lbl_max_speed = Max Speed\: pnl_rover_max_speed_above_3 = Max speed must be over 3m/s\u00B2 diff --git a/src/com/pesterenan/resources/MechPesteBundle_pt.properties b/src/main/resources/MechPesteBundle_pt.properties similarity index 94% rename from src/com/pesterenan/resources/MechPesteBundle_pt.properties rename to src/main/resources/MechPesteBundle_pt.properties index 9f3ffd3..36cb87a 100644 --- a/src/com/pesterenan/resources/MechPesteBundle_pt.properties +++ b/src/main/resources/MechPesteBundle_pt.properties @@ -1,15 +1,16 @@ btn_func_landing = Pouso Autom\u00E1tico btn_func_liftoff = Decolagem Orbital btn_func_create_maneuver = Criar Manobras -btn_func_exec_maneuver = Exec. Manobras +btn_func_maneuver = Manobras btn_func_rover = Pilotar Rover +btn_func_docking = Acoplagem btn_stat_connect = Conectar installer_dialog_btn_browse = Escolher... installer_dialog_btn_cancel = Cancelar 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.1 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.2 do Github original do KRPC. lbl_stat_ready = Pronto. main_mn_file = Arquivo main_mn_help = Ajuda @@ -34,8 +35,8 @@ pnl_land_pnl_hover_border = Sobrevoar a \u00E1rea\: pnl_lift_btn_back = Voltar pnl_lift_btn_liftoff = Decolagem pnl_lift_cb_gravity_curve_tooltip = Escolha o modelo da curva gravitacional a ser realizada.\rVai da mais leve (Sinusoidal) at\u00E9 a mais exagerada (Exponencial). -pnl_lift_chk_open_panels = Abrir pain\u00E9is/radiadores
ap\u00F3s entrar em \u00F3rbita -pnl_lift_chk_open_panels_tooltip = Ap\u00F3s a manobra de circulariza\u00E7\u00E3o, abre os pain\u00E9is e radiadores da nave. +pnl_lift_chk_open_panels = Abrir pain\u00E9is/radiadores/antenas
ap\u00F3s entrar em \u00F3rbita +pnl_lift_chk_open_panels_tooltip = Ap\u00F3s a manobra de circulariza\u00E7\u00E3o, abre os pain\u00E9is, radiadores e antenas dobr\u00e1veis da nave. pnl_lift_chk_options = Op\u00e7\u00f5es\: pnl_lift_chk_staging = Soltar est\u00E1gios e escudos
durante a decolagem pnl_lift_chk_staging_tooltip = Enquanto a nave sobe pra \u00F3rbita, se o est\u00E1gio ficar sem combust\u00EDvel, ele ser\u00E1 descartado. @@ -61,6 +62,7 @@ pnl_mnv_lbl_exec_mnv = Executar pr\u00F3xima
manobra\: pnl_rover_border = Pilotar Rover\: pnl_rover_btn_back = Voltar pnl_rover_btn_drive = Pilotar +pnl_rover_btn_docking = Iniciar Acoplagem pnl_rover_default_name = Alvo pnl_rover_lbl_max_speed = Velocidade m\u00E1xima: pnl_rover_max_speed_above_3 = A velocidade m\u00E1xima tem que ser acima de 3m/s\u00b2 diff --git a/src/main/resources/krpc-java-0.5.2.jar b/src/main/resources/krpc-java-0.5.2.jar new file mode 100644 index 0000000..a645a94 Binary files /dev/null and b/src/main/resources/krpc-java-0.5.2.jar differ