Architecture¶
This chapter describes XCSoar’s internal code architecture.
Source Organisation¶
XCSoar’s source code is stored in the src
directory. This
section tries to give a rough overview where you can find what.
util/
: generic C++ utilities that do not depend on external libraries, such as data structures, string operationsMath/
: math data types (fixed-point math, angles) and generic formulasGeo/
: geographic data structures and formulasFormatter/
: code that formats internal values to stringsUnits/
: conversion from SI units (“System” units) to configured user unitsNMEA/
: data structures for values parsed from NMEAProfile/
: user profiles, loading from and saving toIGC/
: support for the IGC file formatLogger/
: all loggers (NMEA, IGC, flights)thread/
: multi-threading support (OS specific)ui/
: base library for the graphical user interfaceRenderer/
: various graphical renderers, for map and analysisMapWindow/
: the mapForm/
: modal dialogs and their controls (based on the screen library)Dialogs/
: modal dialogs implementations (based on the form library)net/
: networking code (OS specific)Operation/
: generic code to support cancellable long-running operationsAndroid/
: code specific to Android (the native part only; Java code is inandroid/src/
Engine/PathSolvers/
: an implementation of Dijkstra’s path finding algorithm, for task and contest optimisationEngine/Airspace/
: airspace data structures and airspace warningsEngine/Waypoint/
: waypoint data structuresEngine/GlideSolvers/
: a MacCready implementationEngine/Task/
: task data structures and calculationsEngine/Contest/
: contest optimisationEngine/Route/
: the route planner (airspace and terrain)
Threads and Locking¶
Threads¶
XCSoar runs on multiple threads, to make the UI responsive but still allow expensive background calculations.
This is how it looks like on Windows and Linux/SDL (software rendering):
The UI thread is the main thread. It starts the other threads and is
responsible for the UI event loop. No other thread is allowed to
manipulate windows. The UI thread has a timer which does regular house
keeping twice per second (ProcessTimer.cpp
).
The calculation thread (CalculationThread.cpp
,
GlideComputer*.cpp
) does all the expensive calculations in
background. It gets data from the devices (through MergeThread
) and
forwards it together with calculation results to the drawing thread and
the main thread.
Each device has its own thread (SerialPort.cpp
). This is
needed because Windows CE does not support asynchronous COMM port
I/O. The thread is stopped during task declaration (which happens in
the UI thread).
When new data arrives on the serial port, the MergeThread
gets
notified, which will merge all sensor values into one data structure. It
will then run cheap calculations, and forwards everything to the
CalculationThread
.
With OpenGL, the map is rendered live without a buffer. There is no DrawThread.
On Android, the UI thread is not the main thread - the main thread is
implemented in Java, managed by Android itself. The UI thread listens
for events which the Java part drops into the event queue
(NativeView.java
and others). The internal GPS does not need a
thread, it is implemented with Java callbacks. For Bluetooth I/O, there
are two threads implemented in Java (InputThread.java
and
OutputThread.java
, managed by BluetoothHelper.java
).
Locking¶
Some data structures are rarely modified. There is no lock for them. For a modifications, all threads must be suspended. Example: waypoints, airspaces.
Other data structures are modified so often that correct locking would
be too much overhead. Each thread and each instance has its own copy.
The lock needs to be obtained only for making the private copy. The
private copy can be used without locking. Example: NMEA_INFO
,
DERIVED_INFO
.
There are objects which are too expensive to copy. Normal locking
applies to them. We have a template class called Guard
to enforce
proper read/write locking. Example: the task.
Accessing Sensor Data¶
Much of XCSoar deals with obtaining sensor data and visualising it.
Suppose you want to write a dialog that needs the current GPS location,
where do you get it? The short and simple answer is: from
CommonInterface::Basic()
(the InterfaceBlackboard
). Example:
#include "Interface.hpp"
...
const auto &basic = CommonInterface::Basic();
if (basic.location_available)
current_location = basic.location;
This is true for the main thread (aka the “user interface thread”).
Other threads must not use the Interface.hpp
library, because the
InterfaceBlackboard
is not protected in any way. It contains copies
of various data structures just for the main thread.
This is how sensor data moves inside XCSoar:
The device driver parses input received from its device into its own
NMEAInfo
instance inside DeviceBlackboard
(i.e.
per_device_data
). Then it wakes up the MergeThread
to merge the
new data into the central NMEAInfo
instance. The MergeThread
hosts the BasicComputer
which attempts to calculate missing data
(for example, derives vario from GPS altitude).
The CalculationThread
wakes up and receives the MoreData
object
from DeviceBlackboard
. Here, expensive calculations are performed
(GlideComputer
: task engine, airspace warnings, …), resulting in a
DerivedInfo
object. The CalculationThread
runs no more than
twice per second.
Finally, the UI thread wakes up and receives MoreData
and
DerivedInfo
via DeviceBlackboard
. This updates InfoBoxes and
other UI elements. On Windows, the map is drawn in a separate thread, so
there’s another layer.
Let’s get back to the question: where do I get sensor data? That depends on who you are:
you are the user interface: (InfoBoxes, dialogs, any Window callback):
InterfaceBlackboard
(see above). To get notified on changes, register aBlackboardListener
(and don’t forget to unregister it).you are the MapWindow: depends! If you’re being called from
OnPaintBuffer
(i.e. inside theDrawThread
), you must use theMapWindowBlackboard
, all others must use theInterfaceBlackboard
.you are a “computer” library: you will get the values as a parameter. Don’t try to use the
GlideComputerBlackboard
directly.you are a device driver: implement the method
OnSensorUpdate
orOnCalculatedUpdate
if you need to know values from other devices or calculation results.everybody else may use the
DeviceBlackboard
, but be sure to lock it while using its data.
Debugging XCSoar¶
The XCSoar source repository contains a module for the GNU debugger
(gdb
). It contains pretty-printers for various XCSoar types,
including Angle
, GeoPoint
and others. These are helpful when you
print values in the debugger. To use it, start the debugging session and
load the module:
$ gdb -ex "source tools/gdb.py" output/UNIX/bin/xcsoar
(gdb) run
The module will automatically convert fixed-point to floating point, radian angles to degrees and more. You can now do fancy stuff like:
(gdb) p basic.location
$1 = GeoPoint(7.93911242887 51.1470221074)
(gdb) p basic.date_time_utc
$2 = DateTime(2012/12/23 21:41:57)
(gdb) p basic.track
$3 = 55.2254197961
(gdb) p basic.external_wind
$4 = GeoVector::ZERO
(gdb) p current_leg.vector_remaining
$5 = GeoVector(267.899420345 107957.109724)
General¶
Minimise the number of colours, and re-use colour groups already defined.
Too much use of colour where it is not required serves only to reduce the effectiveness of bright colours for important items.
High colour saturation elements should be reserved for high importance items
High contrast against background should be reserved for high importance items
Attempt to adopt colours that are intuitive based the function of the item
Minimise the clutter where possible — readibility is essential for use in flight
Use colours defined in
Graphics
according to functional name, not their actual colour.Try to maintain consistent use of colours in all uses of that function, such as dialogue graphics as well as map overlays and infoboxes.
Text should always be monochrome.
Use aviation conventions or adopt best aviation human factors standards where possible, in particular:
ICAO Internation Standards and Recommended Practices, Annex 4 to the Convention on International Civil Aviation (Aeronautical Charts).
- `NASA Colour Usage recommendations and design guidelines
- `DOT/FAA/AR-03/67 Human Factors Considerations in the Design and
Evaluation of Electronic Flight Bags (EFBs) <http://www.volpe.dot.gov/hf/aviation/efb/docs/efb_version2.pdf>`__
DOT/FAA/AM-01/17 Human Factors Design Guidelines for Multifunction Displays
Check for performance with respect to colour blindness. This site has a useful tool that can be used to convert screenshots to how they would look to a person with common color blindness: http://www.etre.com/tools/colourcheck/
For safety purposes, avoid use of elements that may encourage or require the user to stare at the screen continuously.
For safety purposes, avoid user controls that have significant risk of producing unsafe results if misconfigured by the pilot.
General colour conventions¶
Colour conventions generally in use throughout the program:
Red for indicator of warning
Orange for indicator of caution
Green for positive indicator of safety
Blue for neutral indicator of safety
Displayed data¶
Where data is invalid, indicate this by not presenting the data or showing dashes.
Present data in user-defined units.
Display numerical data with significant digits appropriate to the accuracy of the calculations, or its functional use by the pilot, whichever is lower.
Main graphics¶
Colors¶
Colour conventions in use, in order of priority, are:
Aircraft black and white, for neutrality but clear identification
Traffic (FLARM) use alarm green, orange, and red.
Lift is vibrant green, sink is copper orange.
Aircraft navigation (route, best cruise track) is (ICAO) dark purple-blue
Task navigation lines and areas are (ICAO) magenta.
Updraft sources and other updraft derived data is sky blue.
(Todo) airspace alert colours
Map culture (topography) and terrain rendering should conform to ICAO Annex 4 where appropriate. Note that some modifications are reasonable for electronic use given that Annex 4 deals with paper charts. Nevertheless, the colour conventions are useful to adopt as they are likely to be intuitive and are designed for aviation use.
Pen styles¶
Map culture should be rendered with a thin pen
Thicker pens used for important (e.g. task, navigational, airspace) lines
Dashed lines are used to increase perceptual priority
Map overlays¶
Elements on the map that are not part of the map layer, such as additional informational widgets (final glide bar, wind, north arrow) should be rendered so as to help those elements be visually separated from the map:
Generally adopt higher contrast (higher colour saturation or darker shade) than the background map layer elements.
For elements covering an area (non line), draw the entire element or a border with a luminosity contrasting pen, of width
IBLSCALE(1)
.Consider whether the widget is required in all flying states and display modes. if it does not serve a direct functional purpose in some states/modes, do not render it.
Avoid locating widgets at the aircraft symbol (ownship symbol). It is important to keep this area clear so the aircraft symbol can be easily found.
Elements that may be rendered over each other should be organised in order of priority, particularly with alert warning items above caution items above non-alert items.
Terminology¶
Glide Ratio¶
’Glide ratio’ is a non-specific term which can refer to the ratio of horizontal to vertical motion with reference to either the surrounding airmass or the ground.
To reduce confusion, ground-referenced glide ratios (eg distance travelled over ground vs altitude lost) should be referred to by the term ’glide ratio over ground’ when space allows, or ’glide ratio’ / ’GR’.
Air-referenced glide ratios (eg airspeed vs sink rate) should be specified as ’lift/drag ratio’ / ’L/D ratio’ / ’LD’. The lift/drag ratio is numerically equal to the air-referenced glide ratio when flying at constant speed.
If usage spans both air-referenced and ground-referenced glide ratios, the non-specific term ’glide ratio’ / ’GR’ should be used. ’Lift/drag ratio’ should never be used to refer to ground-referenced glide ratios.