Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop igc options #1180

Merged
merged 11 commits into from
Oct 28, 2023
95 changes: 70 additions & 25 deletions igc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,12 @@ void IgcFormat::read()
char trk_desc[kMaxDescLen + 1];
TaskRecordReader task_record_reader;
int current_line = 1; // For error reporting. Line numbering is off by one for some reason.
QList<std::tuple<QString, igc_ext_type_t, int, int, double>> ext_types_list;
QList<std::tuple<QString, igc_ext_type_t, int, int, double, char**>> ext_types_list;
QList<QString> unsupported_extensions; // For determining how often unspported extensions exist
QList<QString> supported_extensions; // For debug output, determining how often supported extensions exist
QList<QString> excluded_extensions; // Extensions that would be included but were specifically excluded
QList<QString> present_extensions; // List of all extensions present in IGC file
QList<QString> included_extensions; // List of extensions present in IGC file which will be ingested

strcpy(trk_desc, HDRMAGIC HDRDELIM);

Expand Down Expand Up @@ -372,12 +377,15 @@ void IgcFormat::read()
if (global_opts.debug_level >= 6) {
printf(MYNAME ": Adding extension data:");
}
for (const auto& [name, ext, start, len, factor] : ext_types_list) {
double ext_data = ibuf_q.mid(start,len).toInt() / factor;

fsdata->set_value(ext, ext_data, pres_wpt);
if (global_opts.debug_level >= 6) {
printf(" %s:%f", qPrintable(name), ext_data);
for (const auto& [name, ext, start, len, factor, opt] : ext_types_list) {
bool ext_enabled = (0 == strcmp("1", *opt));
if (ext_enabled) {
double ext_data = ibuf_q.mid(start,len).toInt() / factor;

fsdata->set_value(ext, ext_data, pres_wpt);
if (global_opts.debug_level >= 6) {
printf(" %s:%f", qPrintable(name), ext_data);
}
}
}
if (global_opts.debug_level >= 6) {
Expand Down Expand Up @@ -425,7 +433,7 @@ void IgcFormat::read()
// Create a route for each post-flight declaration
task_record_reader.igc_task_rec(ibuf + 4);
break;
} else if (global_opts.debug_level >= 4) {
} else if (global_opts.debug_level >= 5) {
if (strcmp(tmp_str, "OOI") == 0) {
printf(MYNAME ": Observer Input> %s\n", ibuf + 4);
} else if (strcmp(tmp_str, "PLT") == 0) {
Expand All @@ -450,54 +458,91 @@ void IgcFormat::read()
* producing debug output, but this case: is only done once per file.
*/

QList<QString> unsupported_extensions; // For determining how often unspported extensions exist
QList<QString> supported_extensions; // For debug output, determining how often supported extensions exist
if (global_opts.debug_level >= 1) {
printf(MYNAME ": I record: %s\n" MYNAME ": ", qPrintable(ibuf_q));
}
// If the EVERY or NONE options were used, set the corresponding flags.
// I still need a way to override NONE or EVERY if options are explicitly set.

for (int i=3; i < ibuf_q.length(); i+=7) {
QString ext_type = ibuf_q.mid(i+4, 3);
QString extension_definition = ibuf_q.mid(i,7);
if (global_opts.debug_level >= 1) {
printf(" %s;",qPrintable(ext_type));
}
present_extensions.append(ext_type);
// -1 because IGC records are one-initialized and QStrings are zero-initialized
int begin = extension_definition.mid(0,2).toInt() - 1;
int end = extension_definition.mid(2,2).toInt() - 1;
int len = end - begin + 1;
QString name = extension_definition.mid(4,3);
igc_ext_type_t ext = get_ext_type(ext_type);
if (ext != igc_ext_type_t::ext_rec_unknown) {
int factor = get_ext_factor(ext);
ext_types_list.append(std::make_tuple(name, ext, begin, len, factor));
if (ext != IgcFormat::igc_ext_type_t::ext_rec_unknown) {
supported_extensions.append(name);
if (global_opts.debug_level >= 4) {
printf(MYNAME ": Adding %s to list of supported extensions\n", qPrintable(name));
}
int factor = get_ext_factor(ext);
ext_types_list.append(std::make_tuple(name, ext, begin, len, factor, ext_option_map[ext]));
for (auto& arg : igc_args) {
bool opt = (*arg.argval != nullptr && **arg.argval == '1');
if (global_opts.debug_level >= 4) {
printf(MYNAME ": Evaluating option %s against extension %s\n", qPrintable(arg.argstring), qPrintable(name));
}
if (arg.argstring == name) {
if (opt) {
included_extensions.append(name);
if (global_opts.debug_level >= 4) {
printf(MYNAME ": Adding %s to list of included extensions\n", qPrintable(name));
}
break;
} else {
excluded_extensions.append(name);
if (global_opts.debug_level >= 4) {
printf(MYNAME ": Adding %s to list of excluded extensions\n", qPrintable(name));
}
}
}
}
} else {
unsupported_extensions.append(name);
if (global_opts.debug_level >= 4) {
printf(MYNAME ": Adding %s to list of unsupported extensions\n", qPrintable(name));
}
}
}
if (global_opts.debug_level >= 1) {
printf(MYNAME ": I record: %s\n" MYNAME ": Extensions present: ", qPrintable(ibuf_q));
foreach(QString ext, present_extensions) {
printf("%s ", qPrintable(ext));
}
printf("\n");
}
if (global_opts.debug_level >= 2) {
printf(MYNAME ": Extensions defined in I record:\n");
printf(MYNAME ": Non-excluded extensions defined in I record:\n");
printf(MYNAME ": (Note: IGC records are one-initialized. QStrings are zero-initialized.)\n");
for (const auto& [name, ext, begin, len, factor] : ext_types_list) {
for (const auto& [name, ext, begin, len, factor, opt] : ext_types_list) {
printf(MYNAME ": Extension %s (%i): Begin: %i; Length: %i\n", qPrintable(name), int(ext), begin, len);
}
if (global_opts.debug_level >= 3) {
printf("\n" MYNAME "Supported extensions:");
foreach (QString ext, supported_extensions) {
printf("\n" MYNAME ": Present extensions (These extensions are defined in the IGC file I record):\t");
foreach (QString ext, present_extensions) {
printf(" %s", qPrintable(ext));
}
printf("\nUnsupported extensions:");
printf("\n" MYNAME ": Unsupported extensions (I will not ingest these, they are unsupported):\t");
foreach (QString ext, unsupported_extensions) {
printf(" %s", qPrintable(ext));
}
printf("\n" MYNAME ": Supported extensions (These are present in the I record and supported):\t");
foreach (QString ext, supported_extensions) {
printf(" %s", qPrintable(ext));
}
printf("\n" MYNAME ": Excluded etensions (You told me not to ingest these, or they are excluded by default):\t");
foreach (QString ext, excluded_extensions) {
printf(" %s", qPrintable(ext));
}
printf("\n" MYNAME ": Included extensions (I will ingest these):\t");
foreach (QString ext, included_extensions) {
printf(" %s", qPrintable(ext));
}
printf("\n");
}
}
}

// These record types are discarded
case rec_diff_gps:
case rec_event:
Expand Down
81 changes: 79 additions & 2 deletions igc.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <QString> // for QString, operator+, QStringLiteral
#include <QVector> // for QVector
#include <QHash> // for QHash
#include <QDebug> // for QDebug

#include "defs.h"
#include "format.h"
Expand Down Expand Up @@ -78,7 +79,6 @@ class IgcFormat : public Format
ext_rec_gfo = 8, // G Force?
ext_rec_siu = 9, // Satellites In Use
ext_rec_acz = 10, // Z Acceleration

};

QVector<arglist_t>* get_args() override
Expand Down Expand Up @@ -131,6 +131,43 @@ class IgcFormat : public Format
rec_bad = 1, // Bad record
};

char* opt_enl{nullptr};
char* opt_tas{nullptr};
char* opt_vat{nullptr};
char* opt_oat{nullptr};
char* opt_trt{nullptr};
char* opt_gsp{nullptr};
char* opt_fxa{nullptr};
char* opt_siu{nullptr};
char* opt_acz{nullptr};
char* opt_gfo{nullptr};

QMap<IgcFormat::igc_ext_type_t, QString> ext_description_map = {
{IgcFormat::igc_ext_type_t::ext_rec_enl, QString("Engine Noise (ENL; default=1)")},
{IgcFormat::igc_ext_type_t::ext_rec_tas, QString("True Airspeed (TAS; default=1)")},
{IgcFormat::igc_ext_type_t::ext_rec_vat, QString("Total Energy Vario (VAT; default=1)")},
{IgcFormat::igc_ext_type_t::ext_rec_oat, QString("Outside Air Temperature (OAT; default=1)")},
{IgcFormat::igc_ext_type_t::ext_rec_trt, QString("True Track (TRT; default=0)")},
{IgcFormat::igc_ext_type_t::ext_rec_gsp, QString("Ground Speed (GSP; default=1)")},
{IgcFormat::igc_ext_type_t::ext_rec_fxa, QString("Fix Accuracy (FXA; default=1)")},
{IgcFormat::igc_ext_type_t::ext_rec_gfo, QString("G Force? (GFO; default=0)")},
{IgcFormat::igc_ext_type_t::ext_rec_siu, QString("# Of Sats (SIU; default=0)")},
{IgcFormat::igc_ext_type_t::ext_rec_acz, QString("Z Acceleration (ACZ; default=1)")},
};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just place the string literals directly in igc_args?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm with you here. That sounds better.

There's generally too many maps and vectors hashes and lists for my liking right now. It's something I'd like to tackle in another PR with some kind of ext_data construct that would combine ext_description_map, ext_option_map, and igc_extension_map, if that works for you.


QMap<IgcFormat::igc_ext_type_t, char**> ext_option_map = {
{IgcFormat::igc_ext_type_t::ext_rec_enl, &opt_enl},
{IgcFormat::igc_ext_type_t::ext_rec_tas, &opt_tas},
{IgcFormat::igc_ext_type_t::ext_rec_vat, &opt_vat},
{IgcFormat::igc_ext_type_t::ext_rec_oat, &opt_oat},
{IgcFormat::igc_ext_type_t::ext_rec_trt, &opt_trt},
{IgcFormat::igc_ext_type_t::ext_rec_gsp, &opt_gsp},
{IgcFormat::igc_ext_type_t::ext_rec_fxa, &opt_fxa},
{IgcFormat::igc_ext_type_t::ext_rec_gfo, &opt_gfo},
{IgcFormat::igc_ext_type_t::ext_rec_siu, &opt_siu},
{IgcFormat::igc_ext_type_t::ext_rec_acz, &opt_acz},
};

const QHash<QString, igc_ext_type_t> igc_extension_map{
{"ENL", igc_ext_type_t::ext_rec_enl},
{"TAS", igc_ext_type_t::ext_rec_tas},
Expand Down Expand Up @@ -268,7 +305,47 @@ class IgcFormat : public Format
"timeadj", &timeadj,
"(integer sec or 'auto') Barograph to GPS time diff",
nullptr, ARGTYPE_STRING, ARG_NOMINMAX, nullptr
}
},
{
"ENL", &opt_enl, ext_description_map.value(igc_ext_type_t::ext_rec_enl),
"1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
"TAS", &opt_tas, ext_description_map.value(igc_ext_type_t::ext_rec_tas),
"1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
"VAT", &opt_vat, ext_description_map.value(igc_ext_type_t::ext_rec_vat),
"1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
"OAT", &opt_oat, ext_description_map.value(igc_ext_type_t::ext_rec_oat),
"1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
"TRT", &opt_trt, ext_description_map.value(igc_ext_type_t::ext_rec_trt),
"0", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
"GSP", &opt_gsp, ext_description_map.value(igc_ext_type_t::ext_rec_gsp),
"1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
"FXA", &opt_fxa, ext_description_map.value(igc_ext_type_t::ext_rec_fxa),
"1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
"SIU", &opt_siu, ext_description_map.value(igc_ext_type_t::ext_rec_siu),
"0", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
"ACZ", &opt_acz, ext_description_map.value(igc_ext_type_t::ext_rec_acz),
"1", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
{
"GFO", &opt_gfo, ext_description_map.value(igc_ext_type_t::ext_rec_gfo),
"0", ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
},
};
};
/*
Expand Down
12 changes: 4 additions & 8 deletions kml.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1635,15 +1635,11 @@ void KmlFormat::kml_accumulate_track_traits(const route_head* rte)
if (fs_igc->acz.has_value()) {
track_traits[static_cast<int>(wp_field::igc_acz)] = true;
}
if constexpr(kIncludeIGCSIU) {
if (fs_igc->siu.has_value()) {
track_traits[static_cast<int>(wp_field::igc_siu)] = true;
}
if (fs_igc->siu.has_value()) {
track_traits[static_cast<int>(wp_field::igc_siu)] = true;
}
if constexpr(kIncludeIGCTRT) {
if (fs_igc->trt.has_value()) {
track_traits[static_cast<int>(wp_field::igc_trt)] = true;
}
if (fs_igc->trt.has_value()) {
track_traits[static_cast<int>(wp_field::igc_trt)] = true;
}
}
}
Expand Down
6 changes: 1 addition & 5 deletions kml.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class KmlFormat : public Format
igc_fxa, // Fix Accuracy
igc_gfo, // G Force
igc_siu, // Satellites In Use
igc_acz // Z Acceleration
igc_acz, // Z Acceleration
};
static constexpr int number_wp_fields = static_cast<int>(wp_field::igc_acz) + 1;

Expand Down Expand Up @@ -130,10 +130,6 @@ class KmlFormat : public Format
nullptr
};

// IGC option compile-time flags
static constexpr bool kIncludeIGCSIU = true;
static constexpr bool kIncludeIGCTRT = false;

/* Member Functions */

void kml_init_color_sequencer(unsigned int steps_per_rev);
Expand Down
20 changes: 20 additions & 0 deletions reference/format3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,26 @@ file --rwrw igc FAI/IGC Flight Recorder Data Format igc
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html
option igc timeadj (integer sec or 'auto') Barograph to GPS time diff string https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html#fmt_igc_o_timeadj

option igc ENL Engine Noise (ENL; default=1) boolean 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html#fmt_igc_o_ENL

option igc TAS True Airspeed (TAS; default=1) boolean 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html#fmt_igc_o_TAS

option igc VAT Total Energy Vario (VAT; default=1) boolean 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html#fmt_igc_o_VAT

option igc OAT Outside Air Temperature (OAT; default=1) boolean 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html#fmt_igc_o_OAT

option igc TRT True Track (TRT; default=0) boolean 0 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html#fmt_igc_o_TRT

option igc GSP Ground Speed (GSP; default=1) boolean 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html#fmt_igc_o_GSP

option igc FXA Fix Accuracy (FXA; default=1) boolean 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html#fmt_igc_o_FXA

option igc SIU # Of Sats (SIU; default=0) boolean 0 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html#fmt_igc_o_SIU

option igc ACZ Z Acceleration (ACZ; default=1) boolean 1 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html#fmt_igc_o_ACZ

option igc GFO G Force? (GFO; default=0) boolean 0 https://www.gpsbabel.org/WEB_DOC_DIR/fmt_igc.html#fmt_igc_o_GFO

file -wrw-- garmin_fit fit Flexible and Interoperable Data Transfer (FIT) Activity file garmin_fit
https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_fit.html
option garmin_fit allpoints Read all points even if latitude or longitude is missing boolean https://www.gpsbabel.org/WEB_DOC_DIR/fmt_garmin_fit.html#fmt_garmin_fit_o_allpoints
Expand Down
10 changes: 10 additions & 0 deletions reference/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ File Types (-i and -o options):
url Source for URL field in .dbf
igc FAI/IGC Flight Recorder Data Format
timeadj (integer sec or 'auto') Barograph to GPS time diff
ENL (0/1) Engine Noise (ENL; default=1)
TAS (0/1) True Airspeed (TAS; default=1)
VAT (0/1) Total Energy Vario (VAT; default=1)
OAT (0/1) Outside Air Temperature (OAT; default=1)
TRT (0/1) True Track (TRT; default=0)
GSP (0/1) Ground Speed (GSP; default=1)
FXA (0/1) Fix Accuracy (FXA; default=1)
SIU (0/1) # Of Sats (SIU; default=0)
ACZ (0/1) Z Acceleration (ACZ; default=1)
GFO (0/1) G Force? (GFO; default=0)
garmin_fit Flexible and Interoperable Data Transfer (FIT) Act
allpoints (0/1) Read all points even if latitude or longitude is m
recoverymode (0/1) Attempt to recovery data from corrupt file
Expand Down