98 const auto it = _formats.find(add_logged_message.messageName());
99 if (it != _formats.cend()) {
100 _subscriptions[add_logged_message.msgId()] = {
102 add_logged_message.multiId(),
103 add_logged_message.messageName()
118 if (!_headerComplete) {
122 const auto it = _subscriptions.find(
data.msgId());
123 if (it == _subscriptions.cend()) {
127 const SubscriptionInfo &sub = it->second;
133 const ulog_cpp::TypedDataView view(
data, *sub.format);
136 double timestampSecs = -1.0;
137 if (sub.format->fieldMap().count(
"timestamp") > 0) {
138 const uint64_t tsUs = view.at(
"timestamp").as<uint64_t>();
139 timestampSecs =
static_cast<double>(tsUs) / 1e6;
140 _lastTimestampSecs = timestampSecs;
145#ifndef QGC_NO_LOG_START_TIME
146 if (_result.
startTime.isNull() && timestampSecs >= 0.0) {
147 if ((sub.topicName ==
"sensor_gps" || sub.topicName ==
"vehicle_gps_position")
148 && sub.format->fieldMap().count(
"time_utc_usec") > 0) {
149 const uint64_t utcUsec = view.at(
"time_utc_usec").as<uint64_t>();
150 const uint64_t tsUs = view.at(
"timestamp").as<uint64_t>();
151 if (utcUsec > 0 && utcUsec >= tsUs) {
152 const qint64 startMs =
static_cast<qint64
>((utcUsec - tsUs) / 1000);
153 _result.
startTime = QDateTime::fromMSecsSinceEpoch(startMs, QTimeZone::utc());
160 const QString prefix = (sub.multiId > 0)
161 ? QStringLiteral(
"%1[%2].").arg(QString::fromStdString(sub.topicName)).arg(sub.multiId)
162 : QString::fromStdString(sub.topicName) + QLatin1Char(
'.');
164 for (
const auto &field : sub.format->fields()) {
166 if (field->name().rfind(
"_padding", 0) == 0) {
169 if (field->name() ==
"timestamp") {
172 if (!field->definitionResolved()) {
176 const QString fieldName = prefix + QString::fromStdString(field->name());
177 _fieldSet.insert(fieldName);
179 if (!_isNumericScalarField(*field) || timestampSecs < 0.0) {
183 const double value = view.at(field).as<
double>();
184 _result.
fieldSamples[fieldName].append(QPointF(timestampSecs, value));
185 _plottableFieldSet.insert(fieldName);
190 if (timestampSecs >= 0.0) {
196 }
catch (
const std::exception &e) {
197 qCWarning(ULogFullHandlerLog) <<
"Failed to decode data message:" << e.what();
260 const QString name = QString::fromStdString(param_default.field().name());
261 if (name.isEmpty()) {
265 const double defaultVal = param_default.value().as<
double>();
268 using DT = ulog_cpp::ulog_parameter_default_type_t;
269 if ((
static_cast<uint8_t
>(param_default.defaultType()) &
270 static_cast<uint8_t
>(DT::system)) != 0) {
271 _paramDefaults[name] = defaultVal;
273 }
catch (
const std::exception &) {
296 const auto vehicleTypeIt = _result.
fieldSamples.constFind(QStringLiteral(
"vehicle_status.vehicle_type"));
297 if (vehicleTypeIt != _result.
fieldSamples.cend() && !vehicleTypeIt->isEmpty()) {
298 const int vtype =
static_cast<int>(vehicleTypeIt->first().y());
310 const auto navStateIt = _result.
fieldSamples.constFind(QStringLiteral(
"vehicle_status.nav_state"));
312 const QVector<QPointF> &samples = navStateIt.value();
313 int lastNavState = -1;
314 double segmentStart = -1.0;
317 for (
const QPointF &pt : samples) {
318 const int navState =
static_cast<int>(pt.y());
319 if (navState != lastNavState) {
321 if (lastNavState >= 0 && segmentStart >= 0.0) {
323 seg[QStringLiteral(
"mode")] = segmentMode;
324 seg[QStringLiteral(
"start")] = segmentStart;
325 seg[QStringLiteral(
"end")] = pt.x();
328 lastNavState = navState;
329 segmentStart = pt.x();
330 segmentMode = _px4NavStateName(navState);
335 if (lastNavState >= 0 && segmentStart >= 0.0 && _result.
maxTimestamp >= segmentStart) {
337 seg[QStringLiteral(
"mode")] = segmentMode;
338 seg[QStringLiteral(
"start")] = segmentStart;
352 for (
int i = 0; i < _result.
parameters.size(); i++) {
353 QVariantMap row = _result.
parameters[i].toMap();
354 const QString name = row.value(QStringLiteral(
"name")).toString();
355 const auto it = _paramDefaults.constFind(name);
356 if (it != _paramDefaults.constEnd()) {
357 const double defaultVal = it.value();
358 const QVariant valueVariant = row.value(QStringLiteral(
"value"));
359 row[QStringLiteral(
"hasDefault")] =
true;
360 row[QStringLiteral(
"defaultValue")] = defaultVal;
364 bool isDefault =
false;
365 if (valueVariant.isValid() && valueVariant.canConvert<
double>()) {
366 const double currentVal = valueVariant.toDouble();
369 isDefault = (currentVal == defaultVal)
370 || (!qFuzzyIsNull(defaultVal) && qFuzzyCompare(currentVal, defaultVal));
372 row[QStringLiteral(
"isDefault")] = isDefault;
374 row[QStringLiteral(
"hasDefault")] =
false;
375 row[QStringLiteral(
"defaultValue")] = QVariant();
376 row[QStringLiteral(
"isDefault")] =
false;