]> git.mxchange.org Git - flightgear.git/commitdiff
Add support for IGC logging protocol.
authorThorstenB <brehmt@gmail.com>
Mon, 14 Oct 2013 20:13:31 +0000 (22:13 +0200)
committerThorstenB <brehmt@gmail.com>
Mon, 14 Oct 2013 20:13:31 +0000 (22:13 +0200)
Many light aircraft include GPS loggers capable of recording the flight
path using IGC records. Lots of third party utilities are available to
analyze, process and convert igc files.
Usage: "fgfs --igc=file,out,1,OutputFile.igc"

src/Main/fg_io.cxx
src/Main/options.cxx
src/Network/CMakeLists.txt
src/Network/igc.cxx [new file with mode: 0644]
src/Network/igc.hxx [new file with mode: 0644]

index cd66cf0c6447a7b689067f5446cc57a286c4f13e..0aa1fa377d3fc2aa372937441b56ca7c35335eda 100644 (file)
@@ -49,6 +49,7 @@
 #include <Network/AV400WSim.hxx>
 #include <Network/garmin.hxx>
 #include <Network/httpd.hxx>
+#include <Network/igc.hxx>
 #ifdef FG_JPEG_SERVER
 #  include <Network/jpg-httpd.hxx>
 #endif
@@ -147,6 +148,9 @@ FGIO::parse_port_config( const string& config )
         } else if ( protocol == "garmin" ) {
             FGGarmin *garmin = new FGGarmin;
             io = garmin;
+        } else if ( protocol == "igc" ) {
+            IGCProtocol *igc = new IGCProtocol;
+            io = igc;
         } else if ( protocol == "httpd" ) {
             // determine port
             string port = tokens[1];
index b5230d4e75b969d3beaa2b6fb2cbb76945953d72..5ec12cdecd833d5008e84c052ba42ccf071c90d1 100644 (file)
@@ -1458,6 +1458,7 @@ struct OptionDesc {
     {"AV400WSimA",                   true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"AV400WSimB",                   true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"garmin",                       true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
+    {"igc",                          true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"nmea",                         true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"generic",                      true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
     {"props",                        true,  OPTION_CHANNEL | OPTION_MULTI, "", false, "", 0 },
index 27d2e1b074f8ea85a15bbdee3a129b82a7d10313..b4cc36ec86fd888c7881ac7744720e69c18f15cf 100644 (file)
@@ -12,6 +12,7 @@ set(SOURCES
        generic.cxx
        httpd.cxx
        HTTPClient.cxx
+       igc.cxx
        joyclient.cxx
        jsclient.cxx
        lfsglass.cxx
@@ -40,6 +41,7 @@ set(HEADERS
        generic.hxx
        httpd.hxx
        HTTPClient.hxx
+       igc.hxx
        joyclient.hxx
        jsclient.hxx
        lfsglass.hxx
diff --git a/src/Network/igc.cxx b/src/Network/igc.cxx
new file mode 100644 (file)
index 0000000..9e74f49
--- /dev/null
@@ -0,0 +1,243 @@
+// igc.cxx -- International Glider Commission (IGC) protocol class
+//
+// Written by Thorsten Brehm, started October 2013.
+//
+// Copyright (C) 2013 Thorsten Brehm - brehmt (at) gmail com
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+/* Usage:
+ *  "fgfs --igc=file,out,1,OutputFile.igc"
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#if defined( HAVE_VERSION_H ) && HAVE_VERSION_H
+#  include <Include/version.h>
+#else
+#  include <Include/no_version.h>
+#endif
+
+#include <stdio.h>  // sprintf
+#include <simgear/debug/logstream.hxx>
+#include <simgear/math/sg_geodesy.hxx>
+#include <simgear/io/iochannel.hxx>
+#include <simgear/timing/sg_time.hxx>
+
+#include <Main/fg_props.hxx>
+#include <Main/globals.hxx>
+
+#include "igc.hxx"
+
+IGCProtocol::IGCProtocol() :
+    length(0)
+{
+}
+
+IGCProtocol::~IGCProtocol()
+{
+}
+
+// generate IGC header records
+bool IGCProtocol::gen_Hrecords()
+{
+    const char* AircraftType = fgGetString("/sim/aircraft", "unknown");;
+    const char* Callsign     = fgGetString("/sim/multiplay/callsign", "");
+
+    SGTime *t = globals->get_time_params();
+    int Day   = t->getGmt()->tm_mday;
+    int Month = t->getGmt()->tm_mon+1;
+    int Year  = t->getGmt()->tm_year % 100;
+
+#ifdef FLIGHTGEAR_VERSION
+    const char* Version = FLIGHTGEAR_VERSION;
+#else
+    const char* Version = "unknown version";
+#endif
+
+    length = snprintf(buf, FG_MAX_MSG_SIZE,
+                    "HFDTE%02d%02d%02d\r\n"         // date: DDMMYY
+                    "HFFXA001\r\n"                  // fix accuracy (1 meter)
+                    "HFGTYGliderType:%s\r\n"        // aircraft type
+                    "HFGIDGliderID:%s\r\n"          // callsign
+                    "HFDTM100GPSDatum:WGS84\r\n"    // GPS datum type
+                    "HFRFWFirmwareVersion:FlightGear %s\r\n" // "firmware" version
+                    "HFRHWHardwareVersion:FlightGear Flight Simulator\r\n" // "hardware" version
+                    "HFFTYFRType:Flight Simulator\r\n", // logger type
+                    Day, Month, Year,
+                    AircraftType,
+                    Callsign,
+                    Version);
+    SGIOChannel *io = get_io_channel();
+    io->write(buf, length);
+
+    return true;
+}
+
+// generate igc B record message
+bool IGCProtocol::gen_message()
+{
+
+    /* IGC B-record spec:
+     *  B H H M M S S D D M MM MM N D D D M MM MM E V P P P P P G G G G G CR LF
+     *
+     *  Description     Size    Element     Remarks
+     *  ------------------------------------------------------------------------------------------------------------------------------------------------
+     *  Time UTC        6 bytes HHMMSS      Valid characters 0-9. When a valid GNSS fix is received, the UTC time
+     *                                      in a B-record line must be obtained directly from the same GNSS data
+     *                                      package that was the source of the Lat/long and GNSS altitude that is
+     *                                      recorded in the same B-record line. Other sources for the time in a
+     *                                      B-record line (such as the Real-Time Clock in the recorder) must only
+     *                                      be used to provide time-continuity where GNSS fixes are not available.
+     *  Latitude        8 bytes DDMMmmmN/S  Valid characters N, S, 0-9. Obtained directly from the same GPS data
+     *                                      package that was the source of the UTC time that is recorded in the
+     *                                      same B-record line. If no latitude is obtained from satellite data,
+     *                                      pressure altitude fixing must continue, using times from the RTC.
+     *                                      In this case, in B record lines must repeat the last latitude that was
+     *                                      obtained from satellite data, until GPS fixing is regained.
+     *  Longitude       9 bytes DDDMMmmmE/W Valid characters E,W, 0-9. Obtained directly from the same GPS data
+     *                                      package that was the source of UTC time that is recorded in the same
+     *                                      B-record line. If no longitude is obtained from satellite data,
+     *                                      pressure altitude fixing must continue, using times from the RTC.
+     *                                      In this case, in B record lines must repeat the last longitude
+     *                                      that was obtained from satellite data, until GPS fixing is regained.
+     *  Fix validity    1 byte. A or V      Use A for a 3D fix and V for a 2D fix (no GPS altitude) or for no
+     *                                      GPS data (pressure altitude data must continue to be recorded using
+     *                                      times from the RTC).
+     *  Press Alt.      5 bytes PPPPP       Altitude to the ICAO ISA above the 1013.25 hPa sea level datum, valid
+     *                                      characters 0-9 and negative sign "-". Negative values to have negative
+     *                                      sign instead of leading zero.
+     *  GNSS Alt.       5 bytes GGGGG       Altitude above the WGS84 ellipsoid, valid characters 0-9.
+     */
+
+     char lonDir = 'E', latDir = 'N';
+     int lonDeg, latDeg, lonMin, latMin;
+
+     SGTime *t = globals->get_time_params();
+
+     double deg = fdm.get_Latitude() * SGD_RADIANS_TO_DEGREES;
+     if (deg < 0.0)
+     {
+         deg = -deg;
+         latDir = 'S';
+     }
+
+     latDeg = (int)(deg);
+     latMin = (int)((deg - (double)latDeg) * 60.0 * 1000.0);
+
+     deg = fdm.get_Longitude() * SGD_RADIANS_TO_DEGREES;
+     if (deg < 0.0)
+     {
+         deg = -deg;
+         lonDir = 'W';
+     }
+
+     lonDeg = (int)(deg);
+     lonMin = (int)((deg - (double)lonDeg) * 60.0 * 1000.0);
+
+     int Altitude = fdm.get_Altitude() * SG_FEET_TO_METER;
+     if (Altitude < 0)
+         Altitude = 0;
+
+     int h = t->getGmt()->tm_hour;
+     int m = t->getGmt()->tm_min;
+     int s = t->getGmt()->tm_sec;
+
+     // write the B record
+     length = snprintf(buf,FG_MAX_MSG_SIZE,
+                  "B"
+                  "%02d%02d%02d" // UTC time:           HHMMSS
+                  "%02d%05d%c"   // Latitude:           DDMMmmmN (or ..S)
+                  "%03d%05d%c"   // Longitude:          DDDMMmmmE (or ..W)
+                  "A"            // Fix validity:       A for a 3D fix, V for 2D fix
+                  "%05d"         // Pressure Altitude:  PPPPP (above 1013.2 hPa)
+                  "%05d"         // GNSS Altitude:      AAAAA
+                  "\r\n",        // Line feed:          CR LF
+                  h, m, s,
+                  latDeg, latMin, latDir,
+                  lonDeg, lonMin, lonDir,
+                  Altitude, // This should be standard pressure altitude instead. Hm, well :).
+                  Altitude  // GPS altitude
+             );
+
+     return (length > 0);
+}
+
+// reading IGC files is not supported
+bool IGCProtocol::parse_message()
+{
+    return false;
+}
+
+// write header data
+bool IGCProtocol::open()
+{
+    if ( is_enabled() )
+    {
+        SG_LOG( SG_IO, SG_ALERT, "This shouldn't happen, but the channel "
+                << "is already in use, ignoring" );
+        return false;
+    }
+
+    SGIOChannel *io = get_io_channel();
+
+    if (!io->open( get_direction() ))
+    {
+        SG_LOG( SG_IO, SG_ALERT, "Error opening channel communication layer." );
+        return false;
+    }
+
+    set_enabled( true );
+
+    gen_Hrecords();
+
+    return true;
+}
+
+// process work
+bool IGCProtocol::process()
+{
+    SGIOChannel *io = get_io_channel();
+    if ( get_direction() == SG_IO_OUT )
+    {
+        gen_message();
+        if (!io->write( buf, length ))
+        {
+            SG_LOG( SG_IO, SG_WARN, "Error writing data." );
+            return false;
+        }
+    } else
+    if ( get_direction() == SG_IO_IN )
+    {
+        SG_LOG( SG_IO, SG_ALERT, "Error: IGC input is not supported.");
+        return false;
+    }
+
+    return true;
+}
+
+// close the channel
+bool IGCProtocol::close()
+{
+    SGIOChannel *io = get_io_channel();
+
+    set_enabled(false);
+
+    return io->close();
+}
diff --git a/src/Network/igc.hxx b/src/Network/igc.hxx
new file mode 100644 (file)
index 0000000..9cf76e0
--- /dev/null
@@ -0,0 +1,56 @@
+// igc.hxx -- International Glider Commission (IGC) protocol class
+//
+// Written by Thorsten Brehm, started October 2013.
+//
+// Copyright (C) 2013 Thorsten Brehm - brehmt (at) gmail com
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _FG_IGC_HXX
+#define _FG_IGC_HXX
+
+#include <simgear/compiler.h>
+#include <FDM/flightProperties.hxx>
+#include "protocol.hxx"
+
+class IGCProtocol : public FGProtocol
+{
+    char buf[FG_MAX_MSG_SIZE];
+    int length;
+
+    bool gen_Hrecords();
+
+public:
+    IGCProtocol();
+    ~IGCProtocol();
+
+    bool gen_message();
+    bool parse_message();
+
+    // open hailing frequencies
+    bool open();
+
+    // process work for this port
+    bool process();
+
+    // close the channel
+    bool close();
+
+    FlightProperties fdm;
+};
+
+#endif // _FG_IGC_HXX