matlab/matlab-import-tracking-data
Import raw data (CSV, XLSX, TXT, or MATLAB tables) into formats used by Sensor Fusion and Tracking Toolbox. Handles both ground truth trajectories and sensor detection data. For truth: builds trackingScenarioRecording, tuning timetable, truthlog, or converted table. For sensor data: builds task-oriented dataFormat structs (preferred) or objectDetection arrays (legacy). Use when importing flight logs, GPS logs, radar detections, IR measurements, lidar/camera bounding boxes, ADS-B data, AIS ship tracks, or any recorded data for use with trackers, filter tuning, or tracker evaluation.
npx skills add https://github.com/matlab/matlab-agentic-toolkit --skill matlab-import-tracking-data
Import raw data into MATLAB for use with Sensor Fusion and Tracking Toolbox. Handles ground truth trajectories and sensor detection data. Writes plain MATLAB code.
trackingDataImporter, objectDetection, trackerSensorSpec, dataFormat, or importing data for trackerstrackingScenario)Ask: "What kind of data are you importing?"
| User's data | Route |
|---|---|
| Recorded positions/trajectories (truth, GPS, flight logs) | Truth pathway |
| Sensor measurements (radar detections, IR bearings, lidar boxes, camera boxes) | Sensor pathway |
Inference signals from column inspection:
Important: If Step 1 determined the data is truth/trajectory (positions per platform over time), stay in the Truth Pathway. Do NOT enter this step just because the user mentions IMM, UKF, or filter tuning — those refer to what the tuner will produce, not how to format the input data. Truth data → timetable. Sensor data → objectDetection or dataFormat struct.
Ask: "What sensor produced this data?" and "What are you tracking?"
Then decide the API internally (do NOT ask the user about APIs):
Use task-oriented path (preferred) when:
trackerSensorSpec matches, ORsensorMeasurementModel (any combo of az/el/range/rr, position, position-velocity)Use legacy objectDetection path when:
sensorMeasurementModel (TDOA, custom geometry)trackingFilterTuner or existing code)Truth/trajectory data (positions, velocities per platform over time) always produces timetables or struct arrays — never objectDetection. This applies even when the user mentions filter tuning, IMM, UKF, or other filter types. For tuning, the truth pathway produces timetables with Time (duration) and Position, Velocity columns (or a single State vector). The tuner's *detection* input must come from separate sensor measurement data — do NOT fabricate objectDetection from truth positions.
Read the user's actual file — never generate synthetic data when the user provides a file path. Use readtable or equivalent to load the file, then display columns + sample rows. Infer the data model — do not ask yet:
See references/interpreter-categories.md for category selection and column name patterns.
Always present a data summary before writing any conversion code, even when the mapping is obvious. Include ALL of:
Present inferred mappings as a table. Iterate until confirmed.
Options: Cartesian ECEF, Cartesian Fixed NED/ENU (needs origin), Geodetic Local NED/ENU. Default: same as input. See references/coordinate-transforms.md.
Read references/output-formats.md before generating code — it defines required fields and defaults for missing states. Follow patterns in references/code-patterns.md. Key steps:
references/output-formats.md)See references/visualization.md. Geo → trackingGlobeViewer; Non-geo → theaterPlot.
Stop here — do NOT run downstream tools (trackers, trackOSPAMetric, trackingFilterTuner, etc.). The user's data is now in the correct format. Tell the user what they have and show the calling convention for their intended use case.
Use when measurements fit a prebuilt or custom trackerSensorSpec. The key insight: dataFormat is dynamic — it changes based on sensor spec properties. Never hardcode the struct; always query it.
| Sensor description | Spec |
|---|---|
| Aerospace monostatic radar | trackerSensorSpec('aerospace','radar','monostatic') |
| Aerospace bistatic radar | trackerSensorSpec('aerospace','radar','bistatic') |
| ESM / direction finder | trackerSensorSpec('aerospace','radar','direction-finder') |
| Aerospace IR (angle-only) | trackerSensorSpec('aerospace','infrared','angle-only') |
| Automotive radar (clustered detections) | trackerSensorSpec('automotive','radar','clustered-points') |
| Automotive camera (2D bounding boxes) | trackerSensorSpec('automotive','camera','bounding-boxes') |
| Automotive lidar (3D bounding boxes) | trackerSensorSpec('automotive','lidar','bounding-boxes') |
| Other standard measurements | trackerSensorSpec('custom') — see Step 2b |
Inspect the user's data and set properties that affect dataFormat:
Aerospace monostatic / ESM / IR:
HasElevation — does data have elevation measurements?HasRangeRate — does data have range-rate / Doppler? (radar only)IsPlatformStationary — is sensor position fixed or moving? (false adds PlatformPosition/Orientation/Velocity per look)MaxNumLooksPerUpdate — max scan dwells per update in the dataMaxNumMeasurementsPerUpdate — max detections per update in the dataAerospace bistatic:
HasElevation, HasRangeRate — as aboveMeasurementMode — "range-angle" or "range-only"IsReceiverStationary, IsEmitterStationary — adds platform fields when falseAutomotive radar:
HasElevation, MaxNumMeasurementsReferenceFrame — 'ego' (measurements in body frame) or 'global' (ego pose in global frame available)Automotive camera / lidar:
MaxNumMeasurementsReferenceFrame — 'ego' or 'global'For sensors with standard measurement types but no prebuilt spec (e.g., marine radar, sonar):
sensorSpec = trackerSensorSpec('custom');
sensorSpec.MeasurementModel = sensorMeasurementModel('<modelName>');
sensorSpec.DetectabilityModel = sensorDetectabilityModel('<modelName>');
sensorSpec.ClutterModel = sensorClutterModel('<modelName>');
sensorSpec.BirthModel = sensorBirthModel('<modelName>');
See references/sensor-data-formats.md for the complete model catalogs and property details.
For moving sensors, set UpdateModels = true — this adds Time, TimeVaryingModelData, and MeasurementVaryingModelData to the dataFormat.
Read the user's actual file — never generate synthetic data when the user provides a file path. Determine:
references/time-and-units.md). Convert to elapsed seconds from first timestamp._deg, _rad, _km, _kts, etc.) or ask. Target units for the dataFormat:dataFormat and propose mappingfmt = dataFormat(sensorSpec);
disp(fmt)
Present a mapping table for user confirmation:
Your column → dataFormat field Action
"azimuth_deg" → LookAzimuth (1×N) direct (deg→deg)
"range_km" → Range (M×N) convert km→m (×1000)
"doppler_mps" → RangeRate (M×N) direct
"timestamp_epoch" → MeasurementTime (1×N) parse epoch→elapsed sec
"elev_rad" → LookElevation (1×N) convert rad→deg
[unmapped: "snr"] → (not used)
Include unit conversions and frame transforms in the "Action" column. Show unmapped columns. Iterate until user confirms.
Set from user input or use defaults: MountingLocation, MountingAngles, FieldOfView, RangeLimits, DetectionProbability, FalseAlarmRate/NumFalsePositivesPerScan.
Write code that populates the dataFormat struct per timestep in a loop. The output is an array of structs (one per update) ready to be passed to a tracker. Stop here — do NOT create or run a tracker. Tell the user their data is ready and show them the calling convention: tracker = multiSensorTargetTracker(targetSpec, sensorSpec, algorithm); tracks = tracker(sensorData(iUpdate)).
Rotation matrices from Euler angles: When data has yaw/pitch/roll and you need a 3×3 rotation matrix (e.g., for PlatformOrientation), build it from a quaternion:
R = rotmat(quaternion([yaw pitch roll], 'eulerd', 'ZYX', 'frame'), 'frame');
| Data looks like... | Action |
|---|---|
| Raw radar point cloud (many points per scan, no object association) | Flag: needs clustering. Tools: dbscan, clusterDBSCAN (Radar Toolbox), partitionDetections. Offer to create a working example. |
| Raw lidar XYZ points (no bounding boxes) | Flag: needs bounding box extraction. Offer example. |
| Raw camera images (no detections) | Out of scope — needs an object detector first. |
Use when task-oriented API doesn't fit (TOMHT/PHD tracker, non-EKF filter, custom measurements, or explicit user need).
For measurements that fit cvmeas/cameas/ctmeas — any combo of az/el/range/rr in spherical, or position/velocity in rectangular.
Workflow:
references/time-and-units.md)Has* flags: HasAzimuth, HasElevation, HasRange, HasVelocityFrame: 'spherical' or 'rectangular'MeasurementParameters struct (see references/objectDetection-patterns.md)[az, el, range, rr] with missing elements removed[x, y, z, vx, vy, vz] with missing elements removedMeasurementNoise from accuracy columns or user-specified values10. Generate objectDetection cell array
11. Filter tuning data (when user has sensor measurement data for trackingFilterTuner): The tuner requires detection-to-target association. If the sensor data contains a target ID column (e.g., TargetID, PlatformID, ObjectID):
trackingFilterTuner requires detection-to-target association and ask how they want to proceed (provide IDs, or use single-target subset)12. Stop here — do NOT create or run a tracker. Tell user: "These detections work with built-in filter inits: initcvekf, initcaukf, initctekf, initcvukf, etc."
For measurements that don't fit built-in models (TDOA, custom geometry, etc.):
MeasurementParameters — must carry info needed by measurement function and include a discriminator field if multi-sensormeasurementFcn(state, mp) mapping state → expected measurementfilterInitFcn(detection) using the inverse measurement modelobjectDetection array with custom MeasurementParametersSee references/objectDetection-patterns.md for the standard struct, measurement ordering, and multi-sensor design patterns. See references/custom-measurement-models.md for custom function templates.
Read on-demand when you need details:
references/output-formats.md — Truth output struct/table schemas (recording, tuning, truthlog)references/code-patterns.md — End-to-end truth import code examplesreferences/coordinate-transforms.md — Frame transforms (LLA→ECEF, NED→ECEF, etc.)references/visualization.md — trackingGlobeViewer and theaterPlot usagereferences/interpreter-categories.md — Truth data categories, state elements, column name patternsreferences/time-and-units.md — Time parsing and unit conversionreferences/sensor-data-formats.md — Task-oriented: all prebuilt/custom sensor spec properties, model catalogs, dataFormat behaviorreferences/objectDetection-patterns.md — Legacy: MeasurementParameters struct, measurement vector ordering, multi-sensor patternsreferences/custom-measurement-models.md — Custom measurementFcn + filterInitFcn templates----
Copyright 2026 The MathWorks, Inc.
Take matlab/matlab-import-tracking-data from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.