Files
MARTe-Integrated-Components/Client/udpscope/Types.h
T
Martino FerrariandClaude Sonnet 4.6 5a8479cda9 feat(udpscope): per-element timestamp reconstruction from UDPS frames
Implements FrameDecoder with five timing rules that mirror
UDPSourceSession.cpp: FullArray (per-element time signal), FirstSample
and LastSample (rate-spread from anchor), accumulated scalar with
declared rate (forward-chain anchoring, immune to arrival jitter), and
PACKET burst (backward-span from previous arrival). 9 new tests, 38
pass total.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-08-27 20:01:30 +02:00

104 lines
3.3 KiB
C++

/**
* @file Types.h
* @brief Plain data shared across UDPScope modules. No logic, no dependencies.
*/
#pragma once
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
namespace udpscope {
/** A time series as two parallel arrays, which is what ImPlot wants. */
struct Series {
std::vector<double> t;
std::vector<double> v;
void clear() { t.clear(); v.clear(); }
size_t size() const { return t.size(); }
bool empty() const { return t.empty(); }
};
/** RGBA in 0..1. Framework-free so PaneTree needs no ImGui. */
struct Color {
float r = 1.f, g = 1.f, b = 1.f, a = 1.f;
};
/** Screen rectangle in pixels. */
struct Rect {
double x = 0.0, y = 0.0, w = 0.0, h = 0.0;
bool contains(double px, double py) const {
return px >= x && px < (x + w) && py >= y && py < (y + h);
}
};
/* Protocol constants, spelled out rather than included, so the framework-free
* modules stay independent of udps_client.h. They mirror Common/UDP/UDPSProtocol.h. */
constexpr uint8_t kTimePacket = 0;
constexpr uint8_t kTimeFullArray = 1;
constexpr uint8_t kTimeFirstSample = 2;
constexpr uint8_t kTimeLastSample = 3;
constexpr uint32_t kNoTimeSignal = 0xFFFFFFFFu;
/** Framework-free mirror of udps_signal_t, plus UI state. */
struct SignalMeta {
std::string name;
uint8_t typeCode = 255;
uint8_t quantType = 0;
uint32_t numRows = 1;
uint32_t numCols = 1;
double rangeMin = 0.0;
double rangeMax = 0.0;
uint8_t timeMode = kTimePacket;
double samplingRate = 0.0;
uint32_t timeSignalIdx = kNoTimeSignal;
std::string unit;
/** User override: treat an ambiguous PACKET array as a profile, not a burst. */
bool profileOverride = false;
uint32_t numElements() const {
const uint64_t n = static_cast<uint64_t>(numRows ? numRows : 1u) *
static_cast<uint64_t>(numCols ? numCols : 1u);
return n == 0u ? 1u : static_cast<uint32_t>(n);
}
bool hasTimeSignal(uint32_t numSignals) const {
return timeSignalIdx != kNoTimeSignal && timeSignalIdx < numSignals;
}
/**
* @brief True when this array should be plotted against element index
* rather than unrolled onto the time axis.
*
* Only PACKET arrays are ambiguous: the producer stamped the whole datagram
* with one time, which is what a genuine vector looks like and also what a
* burst carrying no time metadata looks like. Default is burst, matching
* UDPSourceSession, with this flag as the user's override.
*/
bool isVectorProfile() const {
return profileOverride && numElements() > 1u && timeMode == kTimePacket;
}
};
/**
* @brief Non-owning mirror of udps_frame_t.
*
* Kept separate from the C struct so FrameDecoder can be tested with plain
* arrays and no socket. Points at memory owned by the caller.
*/
struct FrameView {
uint32_t counter = 0;
uint64_t hrt = 0;
double recvTime = 0.0;
uint32_t numSamples = 1;
uint32_t numSignals = 0;
const double* const* values = nullptr; /**< values[i][0..counts[i]) */
const uint32_t* counts = nullptr;
};
} /* namespace udpscope */