Developer's Guide

From OpenRocket wiki
Revision as of 14:46, 13 September 2021 by SiboVG (talk | contribs) (Hyperlink to specific part of website)
Jump to navigation Jump to search


This page contains information on the inner workings of OpenRocket and is meant primarily for developers interested in developing OpenRocket.

In addition to this page, information can be found in the Technical documentation chapter 5.

Obtaining the source code

OpenRocket is primarily developed using Eclipse, and it's the recommended IDE for compatibility. Developers are free to use other IDE's, but everything may not work out-of-the-box.

The source code is hosted on GitHub. You need either to install the EGit plugin to Eclipse, or use some other Git client (for example the command-line client).

Using the command-line, the OpenRocket code can be retrieved by:

$ git clone git://github.com/openrocket/openrocket.git

This sourcespy dashboard provides a high level overview of architecture, build process and dependencies of the project. It describes Ant tasks and dependencies, structure of UI classes, and other components of the system.

Note: The source packages available on the OpenRocket web site (*.zip) are meant for building the application from source code, NOT for development purposes. They do not contain all the project files etc

Running OpenRocket from Eclipse (tested with Eclipse Luna and OpenRocket v15.03, September, 2015)

The following steps should get you up and running with OpenRocket source code:

1) After downloading the source code, start Eclipse.
2) From the Eclipse main menu, select File -> Import.
3) In the Import window that opens, select General -> Existing Projects into Workspace, then click Next.
4) In the Select root directory field, browse to the location of the OpenRocket source code that you downloaded.
5) In the file browser that appears, click on the openrocket root project directory. A list of projects should then appear in the Projects pane on the import window.
6) Select only these three projects from the list: OpenRocket Core, OpenRocket Swing and OpenRocket Test Libraries. (Note: As of v15.03 you no longer need to load the other projects to build OpenRocket on the desktop.)
7) Once those three projects have been selected, click Finish. Eclipse should start with those three projects shown in the Package Explorer.

NOTE: You might see errors in some source files, reporting that various Java classes cannot be found. If that happens, you might try these steps to resolve these issues:

8) In the Project Explorer pane in Eclipse, right-click on the project reporting the errors. Select Properties.
9) In the properties window that opens, select Java Build Path -> Libraries.
10) Make sure that the JRE System Library for your version of Java is seen in the list of libraries.
11) If it is NOT included in the list, click the Add Library button in the menu to the right.
12) From the Add Library window that appears, select JRE System Library from the list. Then click Next.
13) Make sure that the correct Workspace is selected in the next window that appears, and then click Finish. Once the Add Library window closes, you should then see the JRE System Library added to the list of libraries in the project properties window.
14) Click OK. Once the project properties window closes you will be returned to Eclipse, and hopefully the errors reported by the IDE will then resolve.
15) If there are still errors, you'll need to revert to Google for additional help. Googling the exact error string reported by Eclipse will most likely help you resolve any outstanding dependency issues.

*** Also note that the main entry point for OpenRocket is in the OpenRocket Swing project, in the net.sf.openrocket.startup.SwingStartup.java file. With that file active OpenRocket should build and start.

Finally, remember that help is available either in the OpenRocket forums or in the main developers list. Good Luck!

Marking TODO's

Often when writing code you know that something could be done better, but at the moment is either impossible or unreasonable. These are commonly marked with a TODO comment. The following convension is used to mark the importance of different TODO's:

  • // TODO: CRITICAL: Some comment
    A bug or something that is not yet implemented, and must be corrected before any release is made. The Ant build script checks for these and prevents building if such a comment is found.
  • // TODO: HIGH: Some comment
    An important issue that should be looked into within this or the next major release.
  • // TODO: MEDIUM: Some comment
    Something that would make the software better, but does not represent a problem as such.
  • // TODO: LOW: Some comment
    Something that would be nice to do better in the future

Debugging

LogBack

As of version 13.05, OpenRocket uses LogBack for logging.

If you want to change the default logging that OpenRocket uses, you can create or reuse a LogBack configuration file stored in openrocket/core/config. For example, you can use the logback-stdout-level-error.xml there which tells logback to log everything to stdout with logging level of Error (serious errors only).

To enable use of a LogBack configuration file, pass the JVM the following option during startup:

-Dlogback.configurationFile=config/logback-stdout-level-error.xml 
-Dopenrocket.log.stdout=debug
-Dopenrocket.debug

See the LogBack configuration page for more details.

Probably Obsolete Debugging Info

Log messages in openrocket are specified by one of six levels. You can specify which level of errors you want reported to standard out with a system property which you can add to your VM argument, e.g:

-Dopenrocket.log.stdout=debug

The error levels available are:

ERROR - Level for indicating a bug or error condition noticed in the software or JRE. No ERROR level events _should_ occur while running the program.
WARN - Level for indicating error conditions or atypical events that can occur during normal operation (errors while loading files, weird computation results etc).
USER - Level for logging user actions (adding and modifying components, running simulations etc). A user action should be logged as soon as possible on this level. The level is separate so that additional INFO messages won't purge user actions from a bounded log buffer.
INFO - Level for indicating general level actions the software is performing and other notable events during execution (dialogs shown, simulations run etc)
DEBUG - Level for indicating mid-results, outcomes of methods and other debugging information. The data logged should be of value when analyzing error conditions and what has caused them. Places that are called repeatedly during e.g. flight simulation should use the VBOSE level instead.
VBOSE - Level of verbose debug logging to be used in areas which are called repeatedly, such as computational methods used in simulations. This level is separated to allow filtering out the verbose logs generated during simulations, DnD etc. from the normal debug logs.

In the code, the standard way to log errors is with

log.verbose("Error message");

where log is defined in each class as :

private static final LogHelper log = Application.getLogger();

Units used in OpenRocket

OpenRocket always uses internally pure SI units. For example all rocket dimensions and flight distances are in meters, all masses are in kilograms, density is in kg/m³, temperature is in Kelvin etc. This convention is also used when storing the design in the OpenRocket format.

The only exception to this rule is angles:

  • Angles are represented as radians internally, but in the file format they are converted to degrees. This is to make the file format more human-readable and to avoid rounding errors.
  • Latitude and longitude of the launch site are represented in degrees both internally and externally.

When displaying measures to the user, the values are converted into the preferred units of the user. This is performed using classes in the package net.sf.openrocket.unit. The Unit class represents a single unit and it includes methods for converting between that unit and SI units in addition to creating a string representation with a suitable amount of decimals. A UnitGroup describes a measurable quantity such as temperature and contains the units available for that quantity, such as Celcius, Fahrenheit and Kelvin.

Rocket design loading and saving

(This section is based on email correspondence)


All file reading/writing is performed in the package net.sf.openrocket.file and subpackages. To implement a new document loader it is necessary to extend the class RocketLoader and implement the abstract method loadFromStream(InputStream). This method simply loads the document and returns an OpenRocketDocument object.

An OpenRocketDocument contains all the information about an opened document, primarily the rocket structure and the simulations. The rocket structure is a simple tree-like structure of RocketComponents. All of the components are in the package .rocketcomponent. A diagram of their hierarchy and a short explanation of each class is available in my thesis section 5.1 (http://openrocket.sourceforge.net/documentation.html)

I've implemented a simple XML reading framework (based on SAX), which simplifies reading by assuming that XML elements can contain only other elements or text content, but not both. Both the OpenRocket and Rocksim format abide with this restriction.

The framework is in the package .file.simplesax. The primary class that will be extended is ElementHandler, which contains three methods. openElement() is called when a new subelement is found, and it returns a new ElementHandler to handle that element (which can be the object itself), or null in order to ignore that element and all of its contents (for example for unknown elements). closeElement() is called when the subelement ends, and endHandler() is called when the element of the current handler ends. The JavaDoc should provide the necessary details.

There are a few ready handlers, the most useful of which will probably be PlainTextHandler. This handler accepts only text content and ignores all subelements. If the XML file contains <element>value</element>, then the handler can return a PlainTextHandler and handle the content within the closeElement() method, removing the need to write a specialized handler for that element.

The XML reading is initiated by calling SimpleSAX.readXML() with the input source and the initial ElementHandler.

The OpenRocket document loading is implemented in .file.openrocket.OpenRocketLoader. Here I've used a bit more boilerplate code to be able to define most of the rocket structure preferences without needing separate handlers for them.


The OpenRocket format (*.ork)

The OpenRocket native format uses the file extension *.ork. It is an XML format, which can optionally be compressed using GZIP. (The extension *.ork.gz is also accepted by the dialogs, though plain .ork is recommended.)

Currently the file format is not documented other than as the reference implementation, and no XML schema exists. This will hopefully change in the future. See #Units used in OpenRocket for details on units.

Every time the XML format changes, the file version number is increased. This version number is not linked to the version of OpenRocket that created the file, but instead describes the file format. Later versions of OpenRocket should attempt to store files in the oldest format that supports all the necessary features. The changes in the format are described in the fileformat.txt file in SVN.