Merge branch 'unstable' into issue-1621
BIN
.github/OpenRocket_home.png
vendored
|
Before Width: | Height: | Size: 1.1 MiB |
BIN
.github/OpenRocket_home_2D.png
vendored
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
.github/OpenRocket_home_3D.png
vendored
Normal file
|
After Width: | Height: | Size: 598 KiB |
BIN
.github/OpenRocket_sim.png
vendored
Normal file
|
After Width: | Height: | Size: 838 KiB |
@ -8,7 +8,9 @@ Overview
|
|||||||
|
|
||||||
OpenRocket is a free, fully featured model rocket simulator that allows you to design and simulate your rockets before actually building and flying them.
|
OpenRocket is a free, fully featured model rocket simulator that allows you to design and simulate your rockets before actually building and flying them.
|
||||||
|
|
||||||

|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
The main features include:
|
The main features include:
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,71 @@
|
|||||||
Release Notes
|
Release Notes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
OpenRocket 22.02.beta.05 (2022-09-28)
|
||||||
|
------------------------
|
||||||
|
(through PR1688)
|
||||||
|
|
||||||
|
## New Features
|
||||||
|
* **C_D Override for subassemblies now implemented. Please test!** [See this wiki help page](http://wiki.openrocket.info/Overrides_and_Surface_Finish#How_and_Why_to_Use_Surface_Finish_Settings_and_Coefficient_of_Drag_.28CD.29_Overrides) for important instructions (fixes #1171)
|
||||||
|
* Simulations now properly account for disabled stages (fixes #1477 and #1460)
|
||||||
|
* Rail Button improvements:
|
||||||
|
* Additional parameters for rail buttons (fixes #1537)
|
||||||
|
* Added rail buttons to preset parts database
|
||||||
|
* Scaling now supported for rail buttons (fixes #1661)
|
||||||
|
* Don't include inactive stages in calculations. Disabling stages using the stage selector buttons now also affects the simulation results. (fixes #1477 and #1460)
|
||||||
|
* Mass objects maintain fixed volume when container diameter changes in auto mode (fixes #1315)
|
||||||
|
* Inner tubes can have custom inner/outer appearance (fixes #1509)
|
||||||
|
|
||||||
|
## UI Improvements
|
||||||
|
* Visually select child components of assembly components when selecting the parent (fixes #1489). Try selecting a pod, stage, or booster and see.
|
||||||
|
* Significant improvements to preset selection window (fixes #1481)
|
||||||
|
* Added sliders to Photo Studio settings (fixes #1524)
|
||||||
|
* Show markers for pods and boosters in rocket side view (fixes #1146)
|
||||||
|
* Major improvements to focus behavior. Keyboard navigation in the Component Config dialog is now _much_ more convenient.
|
||||||
|
* When setting focus to a spinner field, select the entire field by default (fixes #1506)
|
||||||
|
* After selecting a preset, automatically highlight most commonly edited parameter (fixes #1488). So, for example, after selecting a body tube preset the Length parameter will be selected by default.
|
||||||
|
* Restore focus to motors, recovery, stage and simulation tables after table action and others (fixes #1558). Simply put, you shouldn't need to click in the table areas just to enable keyboard shortcuts to work.
|
||||||
|
* Use tab and arrow keys to traverse sim table (fixes #1552)
|
||||||
|
* Added and/or improved hover texts on a bunch of different buttons and controls
|
||||||
|
* Apply preset after double-clicking (fixes #1539)
|
||||||
|
* Pre-check diameter filters in preset chooser (fixes #1480)
|
||||||
|
* Preset selection window opens larger, and remembers column widths (fixes #1305). Separate column widths are remembered for each component type.
|
||||||
|
* Ctrl/Cmd+A (select all) keyboard shortcut in component tree, simulation and motor configuration tables (fixes #1549)
|
||||||
|
|
||||||
|
## Notable Bug Fixes
|
||||||
|
* **Scripting now works again. Please test!** (fixes #308, #826, #1108, and #1270)
|
||||||
|
* Don't re-run simulations when new sim is created with same motor (fixes #1510)
|
||||||
|
* Ensure simulations finish when running from scripts (fixes #1575)
|
||||||
|
* Fixed Cd reporting for fin sets (fixes #1440)
|
||||||
|
* Move component config window back to same monitor as main app window first time it is opened. No more lost config windows! (fixes #1470)
|
||||||
|
* Rocket side view updates
|
||||||
|
* Don't recenter rocket when zooming (fixes #1464)
|
||||||
|
* Ensure full rocket is always visible and positioned correctly in rocket side view (fixes #1465)
|
||||||
|
* Fixed root edge display in 3D view and fin templates (fixes #1227). This matters when you are attaching fins to a nose cone or transition.
|
||||||
|
* Numerous bug fixes in component scaling (fixes #1649, #1651, #1653, #1661, #1662, and #1663)
|
||||||
|
* Better register of double-clicks in 3D view (fixes #1054)
|
||||||
|
* Increased component analysis drag precision to three decimal digits (fixes #1476)
|
||||||
|
* Select recovery device/stage after config panel select (fixes #1490)
|
||||||
|
* Fixed an exception when scaling freeform fins (fixes #1520)
|
||||||
|
* Improved performance of freeform fin shape editor (fixes #1533)
|
||||||
|
* Better automatic calculation of fin tab sizes (fixes #1600)
|
||||||
|
* Fixed simulation errors when there were empty stages in the design (fixes #1617)
|
||||||
|
* Fixed stage activeness not updating when moving, deleting, or copying stages (fixes #1680)
|
||||||
|
* Fixed exception for zero-length transitions and nose cones (fixes #1677)
|
||||||
|
|
||||||
|
## Other
|
||||||
|
* Don't open motor selection dialog when duplicating motor configurations (fixes #1555)
|
||||||
|
* A bunch of updated component icons
|
||||||
|
* Added icons to most buttons
|
||||||
|
* Improvements to Undo behavior when adding new components (fixes #1513)
|
||||||
|
* Improvements to scale dialog (fixes #411)
|
||||||
|
* Component tree now set to reasonable minimum width (fixes #1648)
|
||||||
|
* Removed "show all compatible" option in preset chooser (fixes #1405)
|
||||||
|
* Cleaned up several of the example rockets
|
||||||
|
* Added warning to launch preferences that changes only affect new sims (fixes #1497)
|
||||||
|
* Fixed overlapping labels in motor selection diameter filter slider (fixes #1643)
|
||||||
|
* More Russian translation updates
|
||||||
|
|
||||||
OpenRocket 22.02.beta.04 (2022-06-17)
|
OpenRocket 22.02.beta.04 (2022-06-17)
|
||||||
------------------------
|
------------------------
|
||||||
(through PR1456)
|
(through PR1456)
|
||||||
|
|||||||
BIN
core/resources-src/pix/splashscreen-2.png
Normal file
|
After Width: | Height: | Size: 871 KiB |
BIN
core/resources-src/pix/splashscreen-2.xcf
Normal file
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
# The OpenRocket build version
|
# The OpenRocket build version
|
||||||
build.version=22.02.beta.04
|
build.version=22.02.beta.05
|
||||||
|
|
||||||
# The copyright year for the build. Displayed in the about dialog.
|
# The copyright year for the build. Displayed in the about dialog.
|
||||||
# Will show as Copyright 2013-${build.copyright}
|
# Will show as Copyright 2013-${build.copyright}
|
||||||
|
|||||||
@ -64,6 +64,8 @@ RocketPanel.lbl.Stability = Stability:
|
|||||||
RocketPanel.checkbox.ShowCGCP = Show CG/CP
|
RocketPanel.checkbox.ShowCGCP = Show CG/CP
|
||||||
RocketPanel.checkbox.ShowCGCP.ttip = Disabling this checkbox hides the CG and CP markings in the rocket view.
|
RocketPanel.checkbox.ShowCGCP.ttip = Disabling this checkbox hides the CG and CP markings in the rocket view.
|
||||||
RocketPanel.lbl.Stages = Stages:
|
RocketPanel.lbl.Stages = Stages:
|
||||||
|
RocketPanel.btn.Stages.Toggle.ttip = Toggle this button to activate or deactivate the corresponding stage in your design.
|
||||||
|
RocketPanel.btn.Stages.NoChildren.ttip = <html>This stages does not have any child components and is therefore marked as inactive.<br>Add components to the stage to activate it.</html>
|
||||||
RocketPanel.ttip.Rotation = Change the rocket's roll rotation (only affects the rocket view)
|
RocketPanel.ttip.Rotation = Change the rocket's roll rotation (only affects the rocket view)
|
||||||
|
|
||||||
! BasicFrame
|
! BasicFrame
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 185 KiB After Width: | Height: | Size: 871 KiB |
@ -1,8 +1,5 @@
|
|||||||
package net.sf.openrocket.rocketcomponent;
|
package net.sf.openrocket.rocketcomponent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
@ -11,7 +8,6 @@ import net.sf.openrocket.util.Coordinate;
|
|||||||
public class AxialStage extends ComponentAssembly implements FlightConfigurableComponent {
|
public class AxialStage extends ComponentAssembly implements FlightConfigurableComponent {
|
||||||
|
|
||||||
private static final Translator trans = Application.getTranslator();
|
private static final Translator trans = Application.getTranslator();
|
||||||
//private static final Logger log = LoggerFactory.getLogger(AxialStage.class);
|
|
||||||
|
|
||||||
/** list of separations to be happening*/
|
/** list of separations to be happening*/
|
||||||
protected FlightConfigurableParameterSet<StageSeparationConfiguration> separations;
|
protected FlightConfigurableParameterSet<StageSeparationConfiguration> separations;
|
||||||
@ -97,7 +93,6 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
|
|||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stages may be positioned relative to other stages. In that case, this will set the stage number
|
* Stages may be positioned relative to other stages. In that case, this will set the stage number
|
||||||
* against which this stage is positioned.
|
* against which this stage is positioned.
|
||||||
|
|||||||
@ -46,22 +46,23 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
|
|
||||||
private class StageFlags implements Cloneable {
|
private class StageFlags implements Cloneable {
|
||||||
public boolean active = true;
|
public boolean active = true;
|
||||||
//public int prev = -1;
|
|
||||||
public int stageNumber = -1;
|
public int stageNumber = -1;
|
||||||
|
public String stageId;
|
||||||
|
|
||||||
public StageFlags( int _num, boolean _active) {
|
public StageFlags(int _num, String stageId, boolean _active) {
|
||||||
this.stageNumber = _num;
|
this.stageNumber = _num;
|
||||||
|
this.stageId = stageId;
|
||||||
this.active = _active;
|
this.active = _active;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StageFlags clone(){
|
public StageFlags clone(){
|
||||||
return new StageFlags( this.stageNumber, true);
|
return new StageFlags(this.stageNumber, this.stageId, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cached data */
|
/* Cached data */
|
||||||
final protected Map<Integer, StageFlags> stages = new HashMap<Integer, StageFlags>(); // Map of stage number to StageFlags of the corresponding stage
|
final protected Map<Integer, StageFlags> stages = new HashMap<>(); // Map of stage number to StageFlags of the corresponding stage
|
||||||
final protected Map<MotorConfigurationId, MotorConfiguration> motors = new HashMap<MotorConfigurationId, MotorConfiguration>();
|
final protected Map<MotorConfigurationId, MotorConfiguration> motors = new HashMap<MotorConfigurationId, MotorConfiguration>();
|
||||||
final private Collection<MotorConfiguration> activeMotors = new ConcurrentLinkedQueue<MotorConfiguration>();
|
final private Collection<MotorConfiguration> activeMotors = new ConcurrentLinkedQueue<MotorConfiguration>();
|
||||||
final private InstanceMap activeInstances = new InstanceMap();
|
final private InstanceMap activeInstances = new InstanceMap();
|
||||||
@ -130,7 +131,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
|
|
||||||
public void copyStages(FlightConfiguration other) {
|
public void copyStages(FlightConfiguration other) {
|
||||||
for (StageFlags cur : other.stages.values())
|
for (StageFlags cur : other.stages.values())
|
||||||
stages.put(cur.stageNumber, new StageFlags(cur.stageNumber, cur.active));
|
stages.put(cur.stageNumber, new StageFlags(cur.stageNumber, cur.stageId, cur.active));
|
||||||
updateMotors();
|
updateMotors();
|
||||||
updateActiveInstances();
|
updateActiveInstances();
|
||||||
}
|
}
|
||||||
@ -242,7 +243,9 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return stages.get(stageNumber) != null && stages.get(stageNumber).active;
|
AxialStage stage = rocket.getStage(stageNumber);
|
||||||
|
return stage != null && stage.getChildCount() > 0 &&
|
||||||
|
stages.get(stageNumber) != null && stages.get(stageNumber).active;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<RocketComponent> getAllComponents() {
|
public Collection<RocketComponent> getAllComponents() {
|
||||||
@ -370,7 +373,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
public List<AxialStage> getAllStages() {
|
public List<AxialStage> getAllStages() {
|
||||||
List<AxialStage> stages = new ArrayList<>();
|
List<AxialStage> stages = new ArrayList<>();
|
||||||
for (StageFlags flags : this.stages.values()) {
|
for (StageFlags flags : this.stages.values()) {
|
||||||
stages.add( rocket.getStage(flags.stageNumber));
|
stages.add( rocket.getStage(flags.stageId));
|
||||||
}
|
}
|
||||||
return stages;
|
return stages;
|
||||||
}
|
}
|
||||||
@ -379,8 +382,8 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
List<AxialStage> activeStages = new ArrayList<>();
|
List<AxialStage> activeStages = new ArrayList<>();
|
||||||
|
|
||||||
for (StageFlags flags : this.stages.values()) {
|
for (StageFlags flags : this.stages.values()) {
|
||||||
if (flags.active) {
|
if (isStageActive(flags.stageNumber)) {
|
||||||
AxialStage stage = rocket.getStage(flags.stageNumber);
|
AxialStage stage = rocket.getStage(flags.stageId);
|
||||||
if (stage == null) {
|
if (stage == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -392,13 +395,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getActiveStageCount() {
|
public int getActiveStageCount() {
|
||||||
int activeCount = 0;
|
return getActiveStages().size();
|
||||||
for (StageFlags cur : this.stages.values()) {
|
|
||||||
if (cur.active) {
|
|
||||||
activeCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return activeCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -407,7 +404,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
public AxialStage getBottomStage() {
|
public AxialStage getBottomStage() {
|
||||||
AxialStage bottomStage = null;
|
AxialStage bottomStage = null;
|
||||||
for (StageFlags curFlags : this.stages.values()) {
|
for (StageFlags curFlags : this.stages.values()) {
|
||||||
if (curFlags.active) {
|
if (isStageActive(curFlags.stageNumber)) {
|
||||||
bottomStage = rocket.getStage( curFlags.stageNumber);
|
bottomStage = rocket.getStage( curFlags.stageNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -458,14 +455,18 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateStages() {
|
private void updateStages() {
|
||||||
if (this.rocket.getStageCount() == this.stages.size()) {
|
Map<Integer, FlightConfiguration.StageFlags> stagesBackup = new HashMap<>(this.stages);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.stages.clear();
|
this.stages.clear();
|
||||||
for (AxialStage curStage : this.rocket.getStageList()) {
|
for (AxialStage curStage : this.rocket.getStageList()) {
|
||||||
if (curStage == null) continue;
|
if (curStage == null) continue;
|
||||||
StageFlags flagsToAdd = new StageFlags( curStage.getStageNumber(), true);
|
boolean active = true;
|
||||||
|
for (FlightConfiguration.StageFlags flag : stagesBackup.values()) {
|
||||||
|
if (flag.stageId.equals(curStage.getID())) {
|
||||||
|
active = flag.active;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StageFlags flagsToAdd = new StageFlags(curStage.getStageNumber(), curStage.getID(), active);
|
||||||
this.stages.put(curStage.getStageNumber(), flagsToAdd);
|
this.stages.put(curStage.getStageNumber(), flagsToAdd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -850,8 +851,8 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
final String fmt = " [%-2s][%4s]: %6s \n";
|
final String fmt = " [%-2s][%4s]: %6s \n";
|
||||||
buf.append(String.format(fmt, "#", "?actv", "Name"));
|
buf.append(String.format(fmt, "#", "?actv", "Name"));
|
||||||
for (StageFlags flags : stages.values()) {
|
for (StageFlags flags : stages.values()) {
|
||||||
final int stageNumber = flags.stageNumber;
|
final String stageId = flags.stageId;
|
||||||
buf.append(String.format(fmt, stageNumber, (flags.active?" on": "off"), rocket.getStage( stageNumber).getName()));
|
buf.append(String.format(fmt, stageId, (flags.active?" on": "off"), rocket.getStage(stageId).getName()));
|
||||||
}
|
}
|
||||||
buf.append("\n");
|
buf.append("\n");
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
|
|||||||
@ -198,6 +198,15 @@ public class Rocket extends ComponentAssembly {
|
|||||||
return this.stageMap.get( stageNumber);
|
return this.stageMap.get( stageNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AxialStage getStage(final String stageId) {
|
||||||
|
for (AxialStage stage : getStageList()) {
|
||||||
|
if (stage.getID().equals(stageId)) {
|
||||||
|
return stage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the topmost stage, only taking into account active stages from the flight configuration.
|
* Get the topmost stage, only taking into account active stages from the flight configuration.
|
||||||
* @param config flight configuration dictating which stages are active
|
* @param config flight configuration dictating which stages are active
|
||||||
@ -537,21 +546,17 @@ public class Rocket extends ComponentAssembly {
|
|||||||
* Update all the stage numbers based on their position in the component tree
|
* Update all the stage numbers based on their position in the component tree
|
||||||
*/
|
*/
|
||||||
private void updateStageNumbers() {
|
private void updateStageNumbers() {
|
||||||
for (RocketComponent component : getChildren()) {
|
int stageNr = 0;
|
||||||
if (component instanceof AxialStage) {
|
for (AxialStage stage : getSubStages()) {
|
||||||
AxialStage stage = (AxialStage) component;
|
forgetStage(stage);
|
||||||
forgetStage(stage);
|
stage.setStageNumber(stageNr);
|
||||||
stage.setStageNumber(getChildPosition(stage));
|
stageNr++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStageMap(){
|
private void updateStageMap(){
|
||||||
for( RocketComponent component : getChildren() ){
|
for (AxialStage stage : getSubStages() ){
|
||||||
if (component instanceof AxialStage) {
|
trackStage(stage);
|
||||||
AxialStage stage = (AxialStage) component;
|
|
||||||
trackStage(stage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,26 @@ public class BarrowmanCalculatorTest {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test a completely empty rocket.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testEmptyRocket() {
|
||||||
|
// First test completely empty rocket
|
||||||
|
Rocket rocket = new Rocket();
|
||||||
|
FlightConfiguration config = rocket.getSelectedConfiguration();
|
||||||
|
BarrowmanCalculator calc = new BarrowmanCalculator();
|
||||||
|
FlightConditions conditions = new FlightConditions(config);
|
||||||
|
WarningSet warnings = new WarningSet();
|
||||||
|
|
||||||
|
Coordinate cp_calc = calc.getCP(config, conditions, warnings);
|
||||||
|
|
||||||
|
assertEquals(" Empty rocket CNa value is incorrect:", 0.0, cp_calc.weight , 0.0);
|
||||||
|
assertEquals(" Empty rocket cp x value is incorrect:", 0.0, cp_calc.x , 0.0);
|
||||||
|
assertEquals(" Empty rocket cp y value is incorrect:", 0.0, cp_calc.y , 0.0);
|
||||||
|
assertEquals(" Empty rocket cp z value is incorrect:", 0.0, cp_calc.z , 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCPSimpleDry() {
|
public void testCPSimpleDry() {
|
||||||
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||||
@ -351,4 +371,67 @@ public class BarrowmanCalculatorTest {
|
|||||||
assertEquals(" Alpha III With Pods rocket cp z value is incorrect:", cpNoPods.z, cpPods.z, EPSILON);
|
assertEquals(" Alpha III With Pods rocket cp z value is incorrect:", cpNoPods.z, cpPods.z, EPSILON);
|
||||||
assertEquals(" Alpha III With Pods rocket CNa value is incorrect:", cpPods.weight, cpNoPods.weight - 3.91572, EPSILON);
|
assertEquals(" Alpha III With Pods rocket CNa value is incorrect:", cpPods.weight, cpNoPods.weight - 3.91572, EPSILON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether adding extra empty stages has an effect.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testEmptyStages() {
|
||||||
|
// Reference rocket
|
||||||
|
Rocket rocketRef = TestRockets.makeEstesAlphaIII();
|
||||||
|
FlightConfiguration configRef = rocketRef.getSelectedConfiguration();
|
||||||
|
BarrowmanCalculator calcRef = new BarrowmanCalculator();
|
||||||
|
FlightConditions conditionsRef = new FlightConditions(configRef);
|
||||||
|
WarningSet warnings = new WarningSet();
|
||||||
|
|
||||||
|
Coordinate cp_calcRef = calcRef.getCP(configRef, conditionsRef, warnings);
|
||||||
|
|
||||||
|
// First test with adding an empty stage in the front of the design
|
||||||
|
Rocket rocketFront = TestRockets.makeEstesAlphaIII();
|
||||||
|
AxialStage stage1 = new AxialStage(); // To be placed in front of the design
|
||||||
|
rocketFront.addChild(stage1, 0);
|
||||||
|
FlightConfiguration configFront = rocketFront.getSelectedConfiguration();
|
||||||
|
BarrowmanCalculator calcFront = new BarrowmanCalculator();
|
||||||
|
FlightConditions conditionsFront = new FlightConditions(configFront);
|
||||||
|
warnings = new WarningSet();
|
||||||
|
|
||||||
|
Coordinate cp_calcFront = calcFront.getCP(configFront, conditionsFront, warnings);
|
||||||
|
|
||||||
|
assertEquals(" Estes Alpha III with front empty stage CNa value is incorrect:", cp_calcRef.weight, cp_calcFront.weight , EPSILON);
|
||||||
|
assertEquals(" Estes Alpha III with front empty stage cp x value is incorrect:", cp_calcRef.x, cp_calcFront.x , EPSILON);
|
||||||
|
assertEquals(" Estes Alpha III with front empty stage cp y value is incorrect:", cp_calcRef.y, cp_calcFront.y , EPSILON);
|
||||||
|
assertEquals(" Estes Alpha III with front empty stage cp z value is incorrect:", cp_calcRef.z, cp_calcFront.z , EPSILON);
|
||||||
|
|
||||||
|
// Now test with adding an empty stage in the rear of the design
|
||||||
|
Rocket rocketRear = TestRockets.makeEstesAlphaIII();
|
||||||
|
AxialStage stage2 = new AxialStage(); // To be placed in the rear of the design
|
||||||
|
rocketRear.addChild(stage2);
|
||||||
|
FlightConfiguration configRear = rocketRear.getSelectedConfiguration();
|
||||||
|
BarrowmanCalculator calcRear = new BarrowmanCalculator();
|
||||||
|
FlightConditions conditionsRear = new FlightConditions(configRear);
|
||||||
|
warnings = new WarningSet();
|
||||||
|
|
||||||
|
Coordinate cp_calcRear = calcRear.getCP(configRear, conditionsRear, warnings);
|
||||||
|
|
||||||
|
assertEquals(" Estes Alpha III with rear empty stage CNa value is incorrect:", cp_calcRef.weight, cp_calcRear.weight , EPSILON);
|
||||||
|
assertEquals(" Estes Alpha III with rear empty stage cp x value is incorrect:", cp_calcRef.x, cp_calcRear.x , EPSILON);
|
||||||
|
assertEquals(" Estes Alpha III with rear empty stage cp y value is incorrect:", cp_calcRef.y, cp_calcRear.y , EPSILON);
|
||||||
|
assertEquals(" Estes Alpha III with rear empty stage cp z value is incorrect:", cp_calcRef.z, cp_calcRear.z , EPSILON);
|
||||||
|
|
||||||
|
// Test with multiple empty stages
|
||||||
|
Rocket rocketMulti = rocketFront;
|
||||||
|
AxialStage stage3 = new AxialStage(); // To be placed in the rear of the design
|
||||||
|
rocketMulti.addChild(stage3);
|
||||||
|
FlightConfiguration configMulti = rocketMulti.getSelectedConfiguration();
|
||||||
|
BarrowmanCalculator calcMulti = new BarrowmanCalculator();
|
||||||
|
FlightConditions conditionsMulti = new FlightConditions(configMulti);
|
||||||
|
warnings = new WarningSet();
|
||||||
|
|
||||||
|
Coordinate cp_calcMulti = calcMulti.getCP(configMulti, conditionsMulti, warnings);
|
||||||
|
|
||||||
|
assertEquals(" Estes Alpha III with multiple empty stages CNa value is incorrect:", cp_calcRef.weight, cp_calcMulti.weight , EPSILON);
|
||||||
|
assertEquals(" Estes Alpha III with multiple empty stages cp x value is incorrect:", cp_calcRef.x, cp_calcMulti.x , EPSILON);
|
||||||
|
assertEquals(" Estes Alpha III with multiple empty stages cp y value is incorrect:", cp_calcRef.y, cp_calcMulti.y , EPSILON);
|
||||||
|
assertEquals(" Estes Alpha III with multiple empty stages cp z value is incorrect:", cp_calcRef.z, cp_calcMulti.z , EPSILON);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,29 @@ public class MassCalculatorTest extends BaseTestCase {
|
|||||||
// tolerance for compared double test results
|
// tolerance for compared double test results
|
||||||
private static final double EPSILON = 0.00000001; // note: this precision matches MathUtil.java
|
private static final double EPSILON = 0.00000001; // note: this precision matches MathUtil.java
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmptyRocket() {
|
||||||
|
Rocket rocket = new Rocket();
|
||||||
|
FlightConfiguration config = rocket.getEmptyConfiguration();
|
||||||
|
|
||||||
|
final RigidBody actualStructure = MassCalculator.calculateStructure(config);
|
||||||
|
final double actualRocketDryMass = actualStructure.cm.weight;
|
||||||
|
final Coordinate actualRocketDryCM = actualStructure.cm;
|
||||||
|
|
||||||
|
assertEquals(" Empty Rocket Empty Mass is incorrect: ", 0, actualRocketDryMass, 0);
|
||||||
|
|
||||||
|
Coordinate expCM = new Coordinate(0, 0, 0, 0);
|
||||||
|
assertEquals("Empty Rocket CM.x is incorrect: ", expCM.x, actualRocketDryCM.x, 0);
|
||||||
|
assertEquals("Empty Rocket CM.y is incorrect: ", expCM.y, actualRocketDryCM.y, 0);
|
||||||
|
assertEquals("Empty Rocket CM.z is incorrect: ", expCM.z, actualRocketDryCM.z, 0);
|
||||||
|
assertEquals("Empty Rocket CM is incorrect: ", expCM, actualRocketDryCM);
|
||||||
|
|
||||||
|
double actualMOIrot = actualStructure.getRotationalInertia();
|
||||||
|
double actualMOIlong = actualStructure.getLongitudinalInertia();
|
||||||
|
assertEquals("Empty Rocket Rotational MOI calculated incorrectly: ", 0, actualMOIrot, 0);
|
||||||
|
assertEquals("Empty Rocket Longitudinal MOI calculated incorrectly: ", 0, actualMOIlong, 0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAlphaIIIStructure() {
|
public void testAlphaIIIStructure() {
|
||||||
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||||
@ -1145,4 +1168,68 @@ public class MassCalculatorTest extends BaseTestCase {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEmptyStages() {
|
||||||
|
Rocket rocketRef = TestRockets.makeEstesAlphaIII(); // Reference rocket
|
||||||
|
FlightConfiguration configRef = rocketRef.getEmptyConfiguration();
|
||||||
|
configRef.setAllStages();
|
||||||
|
|
||||||
|
final RigidBody structureRef = MassCalculator.calculateStructure(configRef);
|
||||||
|
final double rocketDryMassRef = structureRef.cm.weight;
|
||||||
|
final Coordinate rocketDryCMRef = structureRef.cm;
|
||||||
|
|
||||||
|
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||||
|
AxialStage stage1 = new AxialStage(); // To be added to the front of the rocket
|
||||||
|
AxialStage stage2 = new AxialStage(); // To be added to the rear of the rocket
|
||||||
|
rocket.addChild(stage1, 0);
|
||||||
|
rocket.addChild(stage2);
|
||||||
|
FlightConfiguration config = rocket.getEmptyConfiguration();
|
||||||
|
config.setAllStages();
|
||||||
|
|
||||||
|
final RigidBody structure = MassCalculator.calculateStructure(config);
|
||||||
|
final double rocketDryMass = structure.cm.weight;
|
||||||
|
final Coordinate rocketDryCM = structure.cm;
|
||||||
|
|
||||||
|
assertEquals(" Empty Stages Rocket Empty Mass is incorrect: ", rocketDryMassRef, rocketDryMass, EPSILON);
|
||||||
|
|
||||||
|
assertEquals("Empty Stages Rocket CM.x is incorrect: ", rocketDryCMRef.x, rocketDryCM.x, EPSILON);
|
||||||
|
assertEquals("Empty Stages Rocket CM.y is incorrect: ", rocketDryCMRef.y, rocketDryCM.y, EPSILON);
|
||||||
|
assertEquals("Empty Stages Rocket CM.z is incorrect: ", rocketDryCMRef.z, rocketDryCM.z, EPSILON);
|
||||||
|
assertEquals("Empty Stages Rocket CM is incorrect: ", rocketDryCMRef, rocketDryCM);
|
||||||
|
|
||||||
|
double MOIrotRef = structureRef.getRotationalInertia();
|
||||||
|
double MOIlongRef = structureRef.getLongitudinalInertia();
|
||||||
|
|
||||||
|
double MOIrot = structure.getRotationalInertia();
|
||||||
|
double MOIlong = structure.getLongitudinalInertia();
|
||||||
|
assertEquals("Empty Stages Rocket Rotational MOI calculated incorrectly: ", MOIrotRef, MOIrot, EPSILON);
|
||||||
|
assertEquals("Empty Stages Rocket Longitudinal MOI calculated incorrectly: ", MOIlongRef, MOIlong, EPSILON);
|
||||||
|
|
||||||
|
// if we use a mass override, setting to same mass, we should get same result
|
||||||
|
AxialStage sustainerRef = (AxialStage) rocketRef.getChild(0);
|
||||||
|
sustainerRef.setSubcomponentsOverridden(true);
|
||||||
|
sustainerRef.setMassOverridden(true);
|
||||||
|
sustainerRef.setOverrideMass(rocketDryMassRef);
|
||||||
|
|
||||||
|
AxialStage sustainer = (AxialStage) rocket.getChild(0);
|
||||||
|
sustainer.setSubcomponentsOverridden(true);
|
||||||
|
sustainer.setMassOverridden(true);
|
||||||
|
sustainer.setOverrideMass(rocketDryMass);
|
||||||
|
|
||||||
|
final RigidBody overrideStructureRef = MassCalculator.calculateStructure(configRef);
|
||||||
|
final Coordinate overrideRocketDryCMRef = overrideStructureRef.cm;
|
||||||
|
|
||||||
|
final RigidBody overrideStructure = MassCalculator.calculateStructure(config);
|
||||||
|
final Coordinate overrideRocketDryCM = overrideStructure.cm;
|
||||||
|
|
||||||
|
assertEquals("Empty Stages Rocket Override CM is incorrect: ", overrideRocketDryCMRef, overrideRocketDryCM);
|
||||||
|
|
||||||
|
double overrideMOIrotRef = overrideStructureRef.getRotationalInertia();
|
||||||
|
double overrideMOIlongRef = overrideStructureRef.getLongitudinalInertia();
|
||||||
|
double overrideMOIrot = overrideStructure.getRotationalInertia();
|
||||||
|
double overrideMOIlong = overrideStructure.getLongitudinalInertia();
|
||||||
|
assertEquals("Empty Stages Rocket Rotational MOI calculated incorrectly: ", overrideMOIrotRef, overrideMOIrot, EPSILON);
|
||||||
|
assertEquals("Empty Stages Rocket Longitudinal MOI calculated incorrectly: ", overrideMOIlongRef, overrideMOIlong, EPSILON);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
225
core/test/net/sf/openrocket/rocketcomponent/AxialStageTest.java
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
package net.sf.openrocket.rocketcomponent;
|
||||||
|
|
||||||
|
import net.sf.openrocket.util.BaseTestCase.BaseTestCase;
|
||||||
|
import net.sf.openrocket.util.TestRockets;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
public class AxialStageTest extends BaseTestCase {
|
||||||
|
/**
|
||||||
|
* Test whether we can disable a stage, and that it is registered only in the target flight configuration and not
|
||||||
|
* in the others.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDisableStage() {
|
||||||
|
final Rocket rocket = TestRockets.makeFalcon9Heavy();
|
||||||
|
final FlightConfiguration config = rocket.getSelectedConfiguration();
|
||||||
|
final FlightConfigurationId fcid = rocket.createFlightConfiguration(new FlightConfigurationId());
|
||||||
|
final FlightConfiguration config2 = rocket.getFlightConfiguration(fcid);
|
||||||
|
|
||||||
|
// Disable the payload stage
|
||||||
|
config._setStageActive(0, false);
|
||||||
|
assertFalse(" Payload stage in selected configuration should be disabled", config.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in selected configuration should be enabled", config.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in selected configuration should be enabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
|
||||||
|
// Enable the payload stage
|
||||||
|
config._setStageActive(0, true);
|
||||||
|
assertTrue(" Payload stage in selected configuration should be enabled", config.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in selected configuration should be enabled", config.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in selected configuration should be enabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
|
||||||
|
// Toggle the payload stage to False
|
||||||
|
config.toggleStage(0);
|
||||||
|
assertFalse(" Payload stage in selected configuration should be disabled", config.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in selected configuration should be enabled", config.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in selected configuration should be enabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
|
||||||
|
// Toggle the payload stage to True
|
||||||
|
config.toggleStage(0);
|
||||||
|
assertTrue(" Payload stage in selected configuration should be enabled", config.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in selected configuration should be enabled", config.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in selected configuration should be enabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
|
||||||
|
// Set only stage
|
||||||
|
config.setOnlyStage(1);
|
||||||
|
assertFalse(" Payload stage in selected configuration should be disabled", config.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in selected configuration should be enabled", config.isStageActive(1));
|
||||||
|
assertFalse(" Booster stage in selected configuration should be disabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
|
||||||
|
// Change stage activeness in other configuration
|
||||||
|
config2.toggleStage(1);
|
||||||
|
assertFalse(" Payload stage in selected configuration should be disabled", config.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in selected configuration should be enabled", config.isStageActive(1));
|
||||||
|
assertFalse(" Booster stage in selected configuration should be disabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertFalse(" Core stage in other configuration should be disabled", config2.isStageActive(1));
|
||||||
|
assertFalse(" Booster stage in other configuration should be disabled", config2.isStageActive(2));
|
||||||
|
config.setAllStages();
|
||||||
|
assertTrue(" Payload stage in selected configuration should be enabled", config.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in selected configuration should be enabled", config.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in selected configuration should be enabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertFalse(" Core stage in other configuration should be disabled", config2.isStageActive(1));
|
||||||
|
assertFalse(" Booster stage in other configuration should be disabled", config2.isStageActive(2));
|
||||||
|
|
||||||
|
// Toggle stage with activateSubStages edited
|
||||||
|
config.setAllStages();
|
||||||
|
config2.setAllStages();
|
||||||
|
config._setStageActive(1, false, true);
|
||||||
|
assertTrue(" Payload stage in selected configuration should be enabled", config.isStageActive(0));
|
||||||
|
assertFalse(" Core stage in selected configuration should be disabled", config.isStageActive(1));
|
||||||
|
assertFalse(" Booster stage in selected configuration should be disabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
config._setStageActive(1, true, false);
|
||||||
|
assertTrue(" Payload stage in selected configuration should be enabled", config.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in selected configuration should be enabled", config.isStageActive(1));
|
||||||
|
assertFalse(" Booster stage in selected configuration should be disabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test disabling a stage and then moving the stage in the component tree.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDisableStageAndMove() {
|
||||||
|
final Rocket rocket = TestRockets.makeFalcon9Heavy();
|
||||||
|
final FlightConfiguration config = rocket.getSelectedConfiguration();
|
||||||
|
final FlightConfigurationId fcid = rocket.createFlightConfiguration(new FlightConfigurationId());
|
||||||
|
final FlightConfiguration config2 = rocket.getFlightConfiguration(fcid);
|
||||||
|
|
||||||
|
// Disable the payload stage
|
||||||
|
config.setAllStages();
|
||||||
|
config._setStageActive(0, false);
|
||||||
|
AxialStage payloadStage = rocket.getStage(0);
|
||||||
|
|
||||||
|
// Move the payload stage to the back of the rocket
|
||||||
|
try {
|
||||||
|
rocket.freeze();
|
||||||
|
rocket.removeChild(payloadStage);
|
||||||
|
rocket.addChild(payloadStage); // Moves to the back
|
||||||
|
} finally {
|
||||||
|
rocket.thaw(); // Unfreeze
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(" Core stage in selected configuration should be enabled", config.isStageActive(0));
|
||||||
|
assertTrue(" Booster stage in selected configuration should be enabled", config.isStageActive(1));
|
||||||
|
assertFalse(" Payload stage in selected configuration should be disabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
|
||||||
|
// Re-enable the payload stage
|
||||||
|
config._setStageActive(payloadStage.getStageNumber(), true);
|
||||||
|
assertTrue(" Core stage in selected configuration should be enabled", config.isStageActive(0));
|
||||||
|
assertTrue(" Booster stage in selected configuration should be enabled", config.isStageActive(1));
|
||||||
|
assertTrue(" Payload stage in selected configuration should be enabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
|
||||||
|
// Disable the core stage (and booster stage)
|
||||||
|
config._setStageActive(0, false);
|
||||||
|
assertFalse(" Core stage in selected configuration should be disabled", config.isStageActive(0));
|
||||||
|
assertFalse(" Booster stage in selected configuration should be disabled ", config.isStageActive(1));
|
||||||
|
assertTrue(" Payload stage in selected configuration should be enabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
|
||||||
|
// Move the core stage to the back of the rocket
|
||||||
|
AxialStage coreStage = rocket.getStage(0);
|
||||||
|
try {
|
||||||
|
rocket.freeze();
|
||||||
|
rocket.removeChild(coreStage);
|
||||||
|
rocket.addChild(coreStage); // Moves to the back
|
||||||
|
} finally {
|
||||||
|
rocket.thaw(); // Unfreeze
|
||||||
|
}
|
||||||
|
|
||||||
|
assertTrue(" Payload stage in selected configuration should be enabled", config.isStageActive(0));
|
||||||
|
assertFalse(" Core stage in selected configuration should be disabled", config.isStageActive(1));
|
||||||
|
assertFalse(" Booster stage in selected configuration should be disabled ", config.isStageActive(2));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test disabling a stage and then copying that stage.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testDisableStageAndCopy() {
|
||||||
|
final Rocket rocket = TestRockets.makeFalcon9Heavy();
|
||||||
|
final FlightConfiguration config = rocket.getSelectedConfiguration();
|
||||||
|
final FlightConfigurationId fcid = rocket.createFlightConfiguration(new FlightConfigurationId());
|
||||||
|
final FlightConfiguration config2 = rocket.getFlightConfiguration(fcid);
|
||||||
|
|
||||||
|
// Disable the core stage
|
||||||
|
config.setAllStages();
|
||||||
|
config._setStageActive(1, false);
|
||||||
|
AxialStage coreStage = rocket.getStage(1);
|
||||||
|
|
||||||
|
// Copy the core stage to the back of the rocket
|
||||||
|
AxialStage coreStageCopy = (AxialStage) coreStage.copy();
|
||||||
|
rocket.addChild(coreStageCopy);
|
||||||
|
|
||||||
|
assertTrue(" Payload stage in selected configuration should be enabled", config.isStageActive(0));
|
||||||
|
assertFalse(" Core stage in selected configuration should be disabled", config.isStageActive(1));
|
||||||
|
assertFalse(" Booster stage in selected configuration should be disabled", config.isStageActive(2));
|
||||||
|
assertTrue(" Core copy stage in selected configuration should be enabled", config.isStageActive(3));
|
||||||
|
assertTrue(" Booster copy stage in selected configuration should be enabled", config.isStageActive(4));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
assertTrue(" Core copy stage in selected configuration should be enabled", config2.isStageActive(3));
|
||||||
|
assertTrue(" Booster copy stage in selected configuration should be enabled", config2.isStageActive(4));
|
||||||
|
|
||||||
|
// Disable the copied core stage (not the booster copy stage)
|
||||||
|
config._setStageActive(3, false, false);
|
||||||
|
assertTrue(" Payload stage in selected configuration should be enabled", config.isStageActive(0));
|
||||||
|
assertFalse(" Core stage in selected configuration should be disabled", config.isStageActive(1));
|
||||||
|
assertFalse(" Booster stage in selected configuration should be disabled", config.isStageActive(2));
|
||||||
|
assertFalse(" Core copy stage in selected configuration should be disabled", config.isStageActive(3));
|
||||||
|
assertTrue(" Booster copy stage in selected configuration should be enabled", config.isStageActive(4));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
assertTrue(" Core copy stage in selected configuration should be enabled", config2.isStageActive(3));
|
||||||
|
assertTrue(" Booster copy stage in selected configuration should be enabled", config2.isStageActive(4));
|
||||||
|
|
||||||
|
// Toggle the original core stage back
|
||||||
|
config.toggleStage(1);
|
||||||
|
assertTrue(" Payload stage in selected configuration should be enabled", config.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in selected configuration should be enabled", config.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in selected configuration should be enabled", config.isStageActive(2));
|
||||||
|
assertFalse(" Core copy stage in selected configuration should be disabled", config.isStageActive(3));
|
||||||
|
assertTrue(" Booster copy stage in selected configuration should be enabled", config.isStageActive(4));
|
||||||
|
assertTrue(" Payload stage in other configuration should be enabled", config2.isStageActive(0));
|
||||||
|
assertTrue(" Core stage in other configuration should be enabled", config2.isStageActive(1));
|
||||||
|
assertTrue(" Booster stage in other configuration should be enabled", config2.isStageActive(2));
|
||||||
|
assertTrue(" Core copy stage in selected configuration should be enabled", config2.isStageActive(3));
|
||||||
|
assertTrue(" Booster copy stage in selected configuration should be enabled", config2.isStageActive(4));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -644,15 +644,15 @@ public class ParallelStageTest extends BaseTestCase {
|
|||||||
|
|
||||||
expectedStageNumber = 2;
|
expectedStageNumber = 2;
|
||||||
actualStageNumber = boosterA.getStageNumber();
|
actualStageNumber = boosterA.getStageNumber();
|
||||||
assertEquals(" init order error: core: resultant positions: ", expectedStageNumber, actualStageNumber);
|
assertEquals(" init order error: Booster A: resultant positions: ", expectedStageNumber, actualStageNumber);
|
||||||
|
|
||||||
expectedStageNumber = 3;
|
expectedStageNumber = 3;
|
||||||
actualStageNumber = boosterB.getStageNumber();
|
actualStageNumber = boosterB.getStageNumber();
|
||||||
assertEquals(" init order error: Booster A: resultant positions: ", expectedStageNumber, actualStageNumber);
|
assertEquals(" init order error: Booster B: resultant positions: ", expectedStageNumber, actualStageNumber);
|
||||||
|
|
||||||
expectedStageNumber = 4;
|
expectedStageNumber = 4;
|
||||||
actualStageNumber = boosterC.getStageNumber();
|
actualStageNumber = boosterC.getStageNumber();
|
||||||
assertEquals(" init order error: Booster B: resultant positions: ", expectedStageNumber, actualStageNumber);
|
assertEquals(" init order error: Booster C: resultant positions: ", expectedStageNumber, actualStageNumber);
|
||||||
|
|
||||||
// remove Booster B
|
// remove Booster B
|
||||||
coreBody.removeChild(1);
|
coreBody.removeChild(1);
|
||||||
@ -666,11 +666,11 @@ public class ParallelStageTest extends BaseTestCase {
|
|||||||
assertEquals(" Stage tracking error: removed booster A, but configuration not updated: " + treedump, expectedStageCount, actualStageCount);
|
assertEquals(" Stage tracking error: removed booster A, but configuration not updated: " + treedump, expectedStageCount, actualStageCount);
|
||||||
|
|
||||||
ParallelStage boosterD = createExtraBooster();
|
ParallelStage boosterD = createExtraBooster();
|
||||||
boosterC.setName("Booster D Stage");
|
boosterD.setName("Booster D Stage");
|
||||||
coreBody.addChild(boosterD);
|
coreBody.addChild(boosterD);
|
||||||
boosterC.setAxialOffset(AxialMethod.BOTTOM, 0);
|
boosterD.setAxialOffset(AxialMethod.BOTTOM, 0);
|
||||||
|
|
||||||
expectedStageNumber = 3;
|
expectedStageNumber = 4;
|
||||||
actualStageNumber = boosterD.getStageNumber();
|
actualStageNumber = boosterD.getStageNumber();
|
||||||
assertEquals(" init order error: Booster D: resultant positions: ", expectedStageNumber, actualStageNumber);
|
assertEquals(" init order error: Booster D: resultant positions: ", expectedStageNumber, actualStageNumber);
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<install4j version="9.0.6" transformSequenceNumber="9">
|
<install4j version="9.0.6" transformSequenceNumber="9">
|
||||||
<directoryPresets config="../../core/resources-src/pix/icon" />
|
<directoryPresets config="../../core/resources-src/pix/icon" />
|
||||||
<application name="OpenRocket 22.02.beta.04" applicationId="8434-9327-1469-6373" mediaDir="media" mediaFilePattern="${compiler:sys.shortName}_${compiler:sys.version}_${compiler:sys.platform}" shortName="OpenRocket" publisher="OpenRocket" publisherWeb="http://openrocket.info" version="22.02.beta.04" allPathsRelative="true" convertDotsToUnderscores="false" macVolumeId="5f58a2be20d8e22f" javaMinVersion="11" javaMaxVersion="11" jdkMode="jdk" jdkName="JDK 11.0">
|
<application name="OpenRocket 22.02.beta.05" applicationId="8434-9327-1469-6373" mediaDir="media" mediaFilePattern="${compiler:sys.shortName}_${compiler:sys.version}_${compiler:sys.platform}" shortName="OpenRocket" publisher="OpenRocket" publisherWeb="http://openrocket.info" version="22.02.beta.05" allPathsRelative="true" convertDotsToUnderscores="false" macVolumeId="5f58a2be20d8e22f" javaMinVersion="11" javaMaxVersion="11" jdkMode="jdk" jdkName="JDK 11.0">
|
||||||
<jreBundles jdkProviderId="Liberica" release="11/11.0.15+10">
|
<jreBundles jdkProviderId="Liberica" release="11/11.0.15+10">
|
||||||
<modules>
|
<modules>
|
||||||
<defaultModules set="jre" />
|
<defaultModules set="jre" />
|
||||||
@ -18,7 +18,7 @@
|
|||||||
</entries>
|
</entries>
|
||||||
</files>
|
</files>
|
||||||
<launchers>
|
<launchers>
|
||||||
<launcher name="OpenRocket 22.02.beta.04" id="59" icnsFile="OpenRocket.icns">
|
<launcher name="OpenRocket 22.02.beta.05" id="59" icnsFile="OpenRocket.icns">
|
||||||
<executable name="OpenRocket" iconSet="true" iconFile="../../core/resources-src/pix/icon/icon-windows.ico" executableDir="." executableMode="gui">
|
<executable name="OpenRocket" iconSet="true" iconFile="../../core/resources-src/pix/icon/icon-windows.ico" executableDir="." executableMode="gui">
|
||||||
<versionInfo legalCopyright="Copyright 2007-2022 Sampo Niskanen and Others" />
|
<versionInfo legalCopyright="Copyright 2007-2022 Sampo Niskanen and Others" />
|
||||||
</executable>
|
</executable>
|
||||||
|
|||||||
@ -17,12 +17,12 @@ to publish installers for the following platforms.
|
|||||||
|
|
||||||
# Instructions on updating the macOS drag-and-drop installer
|
# Instructions on updating the macOS drag-and-drop installer
|
||||||
This is an example of updating the installer from 22.02.beta.01 to 22.02.beta.02:
|
This is an example of updating the installer from 22.02.beta.01 to 22.02.beta.02:
|
||||||
1. Download the 22.02.beta.01.dmg file
|
1. Download the OpenRocket-22.02.beta.01-macOS.dmg file
|
||||||
2. Make a read/write .dmg file using the terminal command `hdiutil convert OpenRocket_macos_22_02_beta_01.dmg -format UDRW -o 22.02.beta.01_rw.dmg`
|
2. Make a read/write .dmg file using the terminal command `hdiutil convert OpenRocket-22.02.beta.01-macOS.dmg -format UDRW -o 22.02.beta.01_rw.dmg`
|
||||||
3. Enlarge the writable DMG, by first checking the current size: `hdiutil resize OpenRocket_macos_22_02_beta_01_rw.dmg`, e.g. you get 370000 in the 'cur' column, then just resize it to e.g. 400000: `hdiutil resize -sectors 400000 OpenRocket_macos_22_02_beta_01_rw.dmg`
|
3. Enlarge the writable DMG, by first checking the current size: `hdiutil resize 22.02.beta.01_rw.dmg`, e.g. you get 370000 in the 'cur' column, then just resize it to e.g. 400000: `hdiutil resize -sectors 400000 22.02.beta.01_rw.dmg`
|
||||||
4. Mount the DMG: `hdiutil attach OpenRocket_macos_22_02_beta_01_rw.dmg`
|
4. Mount the DMG: `hdiutil attach 22.02.beta.01_rw.dmg`
|
||||||
5. Open the OpenRocket-disk from your desktop and change the app name from 22.02.beta.01 to 22.02.beta.02
|
5. Open the OpenRocket-disk from your desktop and change the app name from 22.02.beta.01 to 22.02.beta.02
|
||||||
6. Copy the .DS_Store to `openrocket/install4j/22.xx/macOS_resources` by running the command `cp /Volumes/OpenRocket/.DS_Store openrocket/install4j/22.xx/macOS_resources/DS_Store`
|
6. Copy the .DS_Store to `openrocket/install4j/22.xx/macOS_resources` by running the command `cp /Volumes/OpenRocket/.DS_Store openrocket/install4j/22.xx/macOS_resources/DS_Store`
|
||||||
7. Eject the OpenRocket DMG disk from your desktop (important step)
|
7. Eject the OpenRocket DMG disk from your desktop (important step)
|
||||||
8. Delete `OpenRocket_macos_22_02_beta_01_rw.dmg`
|
8. Delete `22.02.beta.01_rw.dmg`
|
||||||
9. You're all done!
|
9. You're all done!
|
||||||
|
|||||||
@ -11,18 +11,21 @@ import javax.swing.JToggleButton;
|
|||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
import net.sf.openrocket.gui.widgets.SelectColorToggleButton;
|
import net.sf.openrocket.gui.widgets.SelectColorToggleButton;
|
||||||
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.rocketcomponent.AxialStage;
|
import net.sf.openrocket.rocketcomponent.AxialStage;
|
||||||
import net.sf.openrocket.rocketcomponent.BodyTube;
|
import net.sf.openrocket.rocketcomponent.BodyTube;
|
||||||
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
|
||||||
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
|
||||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.StateChangeListener;
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class StageSelector extends JPanel implements StateChangeListener {
|
public class StageSelector extends JPanel implements StateChangeListener {
|
||||||
|
|
||||||
|
private static final Translator trans = Application.getTranslator();
|
||||||
private final Rocket rocket;
|
private final Rocket rocket;
|
||||||
|
|
||||||
private List<JToggleButton> buttons = new ArrayList<JToggleButton>();
|
private List<JToggleButton> buttons = new ArrayList<JToggleButton>();
|
||||||
@ -64,6 +67,13 @@ public class StageSelector extends JPanel implements StateChangeListener {
|
|||||||
|
|
||||||
public StageAction(final AxialStage stage) {
|
public StageAction(final AxialStage stage) {
|
||||||
this.stage = stage;
|
this.stage = stage;
|
||||||
|
if (this.stage.getChildCount() == 0) {
|
||||||
|
putValue(SHORT_DESCRIPTION, trans.get("RocketPanel.btn.Stages.NoChildren.ttip"));
|
||||||
|
setEnabled(false);
|
||||||
|
} else {
|
||||||
|
putValue(SHORT_DESCRIPTION, trans.get("RocketPanel.btn.Stages.Toggle.ttip"));
|
||||||
|
}
|
||||||
|
updateUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -77,6 +87,15 @@ public class StageSelector extends JPanel implements StateChangeListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
// Don't toggle the state if the stage has no children (and is therefore inactive)
|
||||||
|
if (stage.getChildCount() == 0) {
|
||||||
|
putValue(SHORT_DESCRIPTION, trans.get("RocketPanel.btn.Stages.NoChildren.ttip"));
|
||||||
|
setEnabled(false);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
setEnabled(true);
|
||||||
|
putValue(SHORT_DESCRIPTION, trans.get("RocketPanel.btn.Stages.Toggle.ttip"));
|
||||||
|
}
|
||||||
rocket.getSelectedConfiguration().toggleStage(stage.getStageNumber());
|
rocket.getSelectedConfiguration().toggleStage(stage.getStageNumber());
|
||||||
rocket.fireComponentChangeEvent(ComponentChangeEvent.AEROMASS_CHANGE | ComponentChangeEvent.MOTOR_CHANGE );
|
rocket.fireComponentChangeEvent(ComponentChangeEvent.AEROMASS_CHANGE | ComponentChangeEvent.MOTOR_CHANGE );
|
||||||
}
|
}
|
||||||
|
|||||||