Garmin GPSMap 196

From FlightGear wiki
Jump to navigation Jump to search
This article is a stub. You can help the wiki by expanding it.

This article describes content/features that may not yet be available in the latest stable version of FlightGear (2020.3).
You may need to install some extra components, use the latest development (Git) version or even rebuild FlightGear from source, possibly from a custom topic branch using special build settings: .

This feature is scheduled for FlightGear 4.0. 20}% completed

If you'd like to learn more about getting your own ideas into FlightGear, check out Implementing new features for FlightGear.

GPSMap196 instrument (Canvas)
Started in 06/2014 (scheduled for FlightGear 4.x)
Description Canvas and MapStructure based GPS device (see: Canvas Animation Framework/Canvas MFD Framework)
Maintainer(s) F-JJTH, flyingfisch[3] (Vector Graphics)
Contributor(s) F-JJTH, jeep
Status Under active development as of 05/2014
Folders $FG_ROOT/Aircraft/Instruments-3d/GPSmap196
Topic branches:
fgdata gitorious/fg/canvas-hackers-fgdata/topics/gpsmap196-canvas/Aircraft/Instruments-3d/GPSmap196


This instrument is currently in the process of being ported to Canvas and MapStructure by F-JJTH. For the latest updates, check out the thread on the forum: Garmin GPSmap196

MFD = multi-function display, which means that the display and buttons may have different functions, depending on the active mode/page. Garmin themselves, and most shops still selling the device, refer to it as a "multi-function" device, too [4].

While this device is not a MFD in the sense of MFDs found on Boeing/Airbus airliners, the underlying design concepts remain valid - it is an instrument that deals with things like 1) a screen, 2) buttons/switches, 3) pages, 4) modes and 5) page elements - that is, why an MFD framework can be used to express such a device, while the opposite would not be the case.

In other words: someone who knows how to fly an airliner also knows how to fly a SEL airplane, but the opposite is not the case - just because someone can fly a single-engine airplane doesn't make them qualified to fly airliners or bizjets - and the same applies to coding and framework designs: we need to find a common denominator and make the framework design sufficiently generic, so that most needs can be addressed, and most instruments modeled.

Imagine designing an "airplane" class: a single-engine class will not be sufficient to model more complex airplanes, while a multi-engine class would also allow less complex aircraft to be modeled. And that's exactly what we're doing here.

If you'd like to help in one way or another (no programming skills needed, Inkscape artists also needed!), please get in touch with F-JJTH or Hooray on the forum. You can also easily help us by keeping track of ongoing development (e.g. using the commit logs) and adding screen-shots to the wiki, e.g. to update this article and the newsletter.

Note  Contributors wanting to check out the topics/gpsmap196-canvas branch, need to follow these 3 steps:
  • git remote add canvas-hackers
  • git fetch canvas-hackers
  • git checkout --track -b topics/gpsmap196-canvas canvas-hackers/topics/gpsmap196-canvas

This will give you a local branch named topics/gpsmap196-canvas, so that you can easily pull/push changes. When pulling, it makes sense to pull with --rebase

Please never push directly to the master/next branches, and please don't push force (-f) either.

Cquote1.png The GPSMap196 changes have never been committed by F-JJTH, so I would not look at the code in fgdata for the time being, because it is very much inferior to your own code frankly.

The wiki article provides a link to a canvas-hackers clone where we added a basic prototype for "page" handling - but even that is fairly simple and crude.
The Avidyne Entegra R9 approach is more proper, but unfortunately much less aircraft/instrument agnostic, i.e. highly use-case specific - but the way the classes are structured is basically correct design still, even though they fail to provide proper encapsulation for modes & switch-handling IIRC.

— Hooray (Wed Jul 23). Re: Garmin gns530.
(powered by Instant-Cquotes)


Cquote1.png I would like to convert the current garmin196 (real name is Garmin GPSmap196) to canvas. I know the garmin196 is used in multiple aircrafts and seems to be appreciated in most of general aviation aircraft.
— F-JJTH (Mon May 12). Garmin GPSmap196.
Cquote1.png I have 2 mains requirement:
1) The screen of the GPSmap196 must be rendered with Canvas (map, settings, text...)
2) The GPSmap196 must be available as a "Canvas Widget"
— F-JJTH (Mon May 12). Garmin GPSmap196.
Cquote1.png As you can see, the 3D model and the widget are now working and they share the same canvas texture.
All buttons on the widget and 3D model are triggering the correct properties.
— F-JJTH (Wed May 14). Re: Garmin GPSmap196.


Note  Also see Howto:Coding a simple Nasal Framework and Canvas Glass Cockpit Efforts.
  • use separate Nasal file and io.include Done Done
  • use maketimer() instead of settimer() and add a destructor for cleanup/release Done Done
  • prototype some helpers for page management 20}% completed
  • make the constructor accept arguments for placement naming Done Done
  • also initialize properties in a foreach loop Done Done
  • split up things and modularize them into 1) animation handling, 2) MFD stuff and 3) device specific Done Done
  • come up with a switch/button (mode) handling helper, that supports secondary modes (buttons held for several seconds) Not done Not done
  • introduce simple helper classes for pages and a simple page manager 70}% completed
  • get rid of timer-based update loop that runs at framerate Done Done
  • introduce a helper for SVG based MFD pages ? 60}% completed
  • re-implement event-handling for dialog mode using Canvas instead of XML animations, so that the whole thing can support multiple instances and not depend on the instrument being included in the -set.xml file Not done Not done
  • add tooltips to the buttons (3D model & unit) via Nasal tooltip.nas Not done Not done
  • both, the G196 and the Avidyne/Entegra support custom GUI widgets (tabs, lists, buttons, checkboxes), those should be based on Canvas Widgets that we can reuse & customize (style) for our device GUI Not done Not done
  • get rid of hard-coded MapStructure assumptions (canvas dimensions etc) Not done Not done
  • handle reset & reinit Not done Not done
  • prototype MapStructure integration for map layers 20}% completed [5]
  • use relative property paths, to prepare support for multiple instances Not done Not done
  • more comments Not done Not done
  • decouple the Nasal code from the instrument, so that this can also be used without any aircraft/instrument (faster testing/prototyping) Not done Not done
  • look at the extra500/Avidyne Entegra for ideas on supporting MFDs with Pages, Modes, Buttons & Switches 10}% completed, also see Canvas MFD Framework
  • come up with vector images for required instruments[6] (existing textures[7] or SVGs) 70}% completed see:


Cquote1.png You can directly load them via parsesvg, and then use the findElemetbyID() call to look up an element and animate/transform it - but watch the console, our svg parser is still fairly basic and may be missing some features
— Hooray (Wed May 14). Re: Garmin GPSmap196.
Cquote1.png So now it's time to draw the structure of each pages, it seems that 1 SVG file per page was the appropriate solution, let's go !
— F-JJTH (Wed May 14). Re: Garmin GPSmap196.
Cquote1.png to get this started we need a SVG file representing the device (screen,keypad/buttons) - each functional element should be addressable by having an SVG id. Textures can be implemented using png images - we only need to extend svg.nas to display those by mapping them to canvas raster images. Then, we would assign event handlers for each key. Someone could then come up with a few pages, as well instrument sets. Ideally, using separate files for better maintainability. Personally, I would probably start with the mapping page, because that's what we can support right now using MapStructure, without too much extra work
— Hooray (Mon May 12). Re: Garmin GPSmap196.
Cquote1.png Such stuff would be best represented as animated SVGs (I'd prefer having one file per instrument, for better reuse)
— Hooray (Tue May 13). Re: Garmin GPSmap196.

Cquote1.png Regarding your SVG panel work, as previously mentioned, for better code reuse/maintainability, it would be good to move those instruments to separate files. That would allow people to reuse such SVG instruments in other places, including other instruments, but also GUI dialogs and/or HUDs.

I think our svg.nas parser could also be extended to support external SVGs directly, i.e. using the <use> and <image> tags. The other concern here is performance - once instruments are self-contained and can be treated as such, we can also update them more selectively, i.e. we don't necessarily have to use timers for each individual element, but can instead update instruments in a holistic fashion.

Overall, that is something that would be very worthwhile to pursue, because we do have plans to re-implement the existing 2D panels C++ code using Canvas and Nasal, so any work even remotely related to this would help pave the way for this and establish the underlying structure and framework. Conceptually, it wouldn't matter if a "steam gauge" is a raster image (2D panels) or a SVG image, the required animations would be fairly similar.
— Hooray (Tue Jun 03). Re: Garmin GPSmap196.

If you are a little familiar with Inkscape, and interested in helping with working on any of the GPSMap 196 pages, it would be helpful to download the GPSMap196 manual from the garmin website and then coordinate things with F-JJTH, we really only have the "panels" page so far - and even that is only very basic, so feel free to pick a page that you are interested in, we'd just ask you to talk to F-JJTH first and then "block" those pages/images by adding a short note to this wiki article, so that others are aware of your work & progress. The Map page can be made functional relatively easily because it can be largely driven by the MapStructure framework.

If something is used by multiple pages, it should normally be a separate SVG file, so that it can be easily used in all places - that would for example apply to shared layouts, common screen elements etc.

Things like GUI widgets (tabs, buttons, checkboxes etc) should probably be kept separate, so that we can come up with a collection of widgets and then simply re-style them appropriately.

Note  Here's some guidelines for people wanting to help with SVG images specifically for Canvas to avoid unnecessary work:
  • please use transparent backgrounds
  • no need to provide different labels/translations (can be done by Nasal/Canvas)
  • no need to provide different scales of symbols (can be done by Nasal/Canvas!)
  • no need to provide differently colored symbols (can be done by patching svg.nas to allow elements to be looked up !)
  • no need to provide different combinations of overlaid symbols (can be done by Nasal/Canvas via z-index!)
  • only use standard text elements, FlowText etc are not supported at the moment.
  • don't use the image tag (i.e. for referencing raster images or other SVG files), it's currently unsupported

Whenever something is "repeated" in an image, it should not be added, a placeholder will do, and we also don't need separate colors - these things can be done with two lines of Nasal code, so are quicker to do that way than having someone spend even just a minute on adding such details. So better to think in "building blocks": if we need to show a certain symbol/image in different places, just provide it once as a SVG element with its own lookup ID (using a good name will surely help).

The same goes for different sizes, colors or fonts obviously - and fonts in general (text) should probably not be added, because we would do that using Canvas, too - to keep it dynamic.

However, if you want something to be configurable, one important thing is having an element ID that we can refer to, in order to look up the key and modify the symbol via Nasal. Preferably, something that makes sense, i.e. is intuitive. Without having an element id (e.g. for labels) we cannot easily modify such SVG images procedurally.

If you are not familiar with git/gitorious, just get in touch with F-JJTH so that your SVG files can be committed. If you are familiar with git/gitorious, just get in touch via the GPSMap196 forum thread, so that we can provide commit access to the Canvas-hackers team clone.

Position Page

Panel Page

Note  This page is being worked on by F-JJTH

Route Page

Map Page

Cquote1.png I've been talking with psadro_gm regarding scenery & charts - and it seems that mapping stuff that we don't currently support (borders, coast lines, roads, railways) would be best implemented through ESRI shapefiles, i.e. 2-3 additional MapStructure layers
— Hooray (Tue May 13). Re: Garmin GPSmap196.
Cquote1.png Otherwise, I am thinking of supporting ESRI through canvas directly. Supporting essential GIS file formats simply makes sense here, even though we can probably do quite a bit of prototyping without it.

And this will require some clipping/sub-screen support in MapStructure.nas or canvas
— Hooray (Tue May 13). Re: Garmin GPSmap196.


The basic idea is to use concepts from the Avidyne/Entegra (extra500) code to encapsulate the most important common MFD components, such as having a single MFDisplay class that contains helpers for registering buttons, mapping those to modes, and mapping modes to Pages, where each page may contain an arbitrary number of PageElements. Instruments (animated SVGs) would then be registered as PageElements and animated through properties and transformations.

var MFDisplay = {};
var MFDButton = {}
var MFDMode = {}
var MFDPage = {};
var MFDPageElement = {};

var GPSMap196 =;


GPSMap196 Instrument page (SVG driven), via Canvas and Nasal
F-JJTH has updated the SVG file implementing the panel page for the Garmin GPSMap 196
Protoyping the G196 instrument display using wikimedia/commons SVG images and the unmodified Canvas SVG parser as per [1]

It would make sense to look up each element ID and animate those by associating a Nasal timer with a callback.

var SVGElement = {};
var SVGInstrument = {};

# look up by ID
# set up animation callback via timer/listener
# in a foreach loop

Testing & Patches

F-JJTH's GPSMap196 in the process of being ported to Canvas using Philosopher's MapStructure framework for mapping (LOD/scaling not applied here, but available) - see [2]
MapStructure layers integrated in GPSMap196 with some custom styling applied
GPSMap196 with MapStructure layers (currently exhibiting some scaling/LOD issues due to hard-coded assumptions in some of the layers)

and here's the diff for testing the modified instrument, use "git apply" to apply the patch (in $FG_ROOT) and then start fgfs with --aircraft=DR400-dauphin

diff --git a/Aircraft/DR400-dauphin/Models/Interior/panel.xml b/Aircraft/DR400-dauphin/Models/Interior/panel.xml
index b9d9551..4b5e42d 100644
--- a/Aircraft/DR400-dauphin/Models/Interior/panel.xml
+++ b/Aircraft/DR400-dauphin/Models/Interior/panel.xml
@@ -10,6 +10,18 @@
+  <model>
+    <path>Aircraft/Instruments-3d/GPSmap196/gpsmap196.xml</path>
+    <offsets>
+      <x-m>  0.60 </x-m>
+      <y-m> -0.202 </y-m>
+      <z-m>  0.28 </z-m>
+      <roll-deg>    0.0 </roll-deg>
+      <pitch-deg> -5.0 </pitch-deg>
+      <heading-deg> 0.0 </heading-deg>
+    </offsets>
+  </model>
   <!-- Based on -->
   <!-- ################################################################-->
diff --git a/Aircraft/DR400-dauphin/dr400-dauphin-set.xml b/Aircraft/DR400-dauphin/dr400-dauphin-set.xml
index 66494b9..5641243 100644
--- a/Aircraft/DR400-dauphin/dr400-dauphin-set.xml
+++ b/Aircraft/DR400-dauphin/dr400-dauphin-set.xml
@@ -390,6 +390,9 @@
+    <gpsmap196>
+      <file>Aircraft/Instruments-3d/GPSmap196/gpsmap196.nas</file>
+    </gpsmap196>

Related content

Forum topics

Source code

External links