Documentation
¶
Index ¶
- Constants
- Variables
- func ApplyPose(x, y, z float64, T [16]float64) (wx, wy, wz float64)
- func ClearTracks(db *sql.DB, sensorID string) error
- func ComputeSpeedPercentiles(speedHistory []float32) (p50, p85, p95 float32)
- func Debugf(format string, args ...interface{})
- func EncodeForegroundBlob(points []PointPolar) []byte
- func EncodePandar40PPacket(points []PointPolar, blockAzimuth float64, config *SensorConfig) ([]byte, error)
- func ExportBgSnapshotToASC(snap *BgSnapshot, ringElevations []float64) (string, error)
- func ExportForegroundSnapshotToASC(snap *ForegroundSnapshot) (string, error)
- func ExportPointsToASC(points []PointASC, extraHeader string) (string, error)
- func InsertCluster(db *sql.DB, cluster *WorldCluster) (int64, error)
- func InsertTrack(db *sql.DB, track *TrackedObject, worldFrame string) error
- func InsertTrackObservation(db *sql.DB, obs *TrackObservation) error
- func RegisterAnalysisRunManager(sensorID string, manager *AnalysisRunManager)
- func RegisterBackgroundManager(sensorID string, mgr *BackgroundManager)
- func RegisterFrameBuilder(sensorID string, fb *FrameBuilder)
- func SetDebugLogger(w io.Writer)
- func SphericalToCartesian(distance, azimuthDeg, elevationDeg float64) (x, y, z float64)
- func StoreForegroundSnapshot(sensorID string, ts time.Time, foreground []PointPolar, ...)
- func UpdateTrack(db *sql.DB, track *TrackedObject, worldFrame string) error
- func WriteNetworkStream(packets [][]byte, destAddr string, config *SensorConfig) error
- func WritePCAPFile(packets [][]byte, outputPath string, config *SensorConfig) error
- type AcceptanceMetrics
- type AnalysisRun
- type AnalysisRunManager
- func (m *AnalysisRunManager) CompleteRun() error
- func (m *AnalysisRunManager) CurrentRunID() string
- func (m *AnalysisRunManager) FailRun(errMsg string) error
- func (m *AnalysisRunManager) GetCurrentRunParams() (RunParams, bool)
- func (m *AnalysisRunManager) IsRunActive() bool
- func (m *AnalysisRunManager) RecordClusters(count int)
- func (m *AnalysisRunManager) RecordFrame()
- func (m *AnalysisRunManager) RecordTrack(track *TrackedObject) bool
- func (m *AnalysisRunManager) StartRun(sourcePath string, params RunParams) (string, error)
- type AnalysisRunStore
- func (s *AnalysisRunStore) CompleteRun(runID string, stats *AnalysisStats) error
- func (s *AnalysisRunStore) GetLabelingProgress(runID string) (total, labeled int, byClass map[string]int, err error)
- func (s *AnalysisRunStore) GetRun(runID string) (*AnalysisRun, error)
- func (s *AnalysisRunStore) GetRunTracks(runID string) ([]*RunTrack, error)
- func (s *AnalysisRunStore) GetUnlabeledTracks(runID string, limit int) ([]*RunTrack, error)
- func (s *AnalysisRunStore) InsertRun(run *AnalysisRun) error
- func (s *AnalysisRunStore) InsertRunTrack(track *RunTrack) error
- func (s *AnalysisRunStore) ListRuns(limit int) ([]*AnalysisRun, error)
- func (s *AnalysisRunStore) UpdateRunStatus(runID, status, errorMsg string) error
- func (s *AnalysisRunStore) UpdateTrackLabel(runID, trackID, userLabel string, confidence float32, labelerID string) error
- func (s *AnalysisRunStore) UpdateTrackQualityFlags(runID, trackID string, isSplit, isMerge bool, linkedIDs []string) error
- type AnalysisStats
- type BackgroundCell
- type BackgroundGrid
- type BackgroundManager
- func (bm *BackgroundManager) ExportBackgroundGridToASC() (string, error)
- func (bm *BackgroundManager) GetAcceptanceMetrics() *AcceptanceMetrics
- func (bm *BackgroundManager) GetGridCells() []ExportedCell
- func (bm *BackgroundManager) GetGridHeatmap(azimuthBucketDeg float64, settledThreshold uint32) *GridHeatmap
- func (bm *BackgroundManager) GetParams() BackgroundParams
- func (bm *BackgroundManager) GetRegionDebugInfo(includeCells bool) *RegionDebugInfo
- func (bm *BackgroundManager) GridStatus() map[string]interface{}
- func (bm *BackgroundManager) Persist(store BgStore, reason string) error
- func (bm *BackgroundManager) ProcessFramePolar(points []PointPolar)
- func (bm *BackgroundManager) ProcessFramePolarWithMask(points []PointPolar) (foregroundMask []bool, err error)
- func (bm *BackgroundManager) ResetAcceptanceMetrics() error
- func (bm *BackgroundManager) ResetGrid() error
- func (bm *BackgroundManager) SetClosenessSensitivityMultiplier(v float32) error
- func (bm *BackgroundManager) SetEnableDiagnostics(v bool)
- func (bm *BackgroundManager) SetForegroundClusterParams(minPts int, eps float32) error
- func (bm *BackgroundManager) SetNeighborConfirmationCount(v int) error
- func (bm *BackgroundManager) SetNoiseRelativeFraction(v float32) error
- func (bm *BackgroundManager) SetParams(p BackgroundParams) error
- func (bm *BackgroundManager) SetPostSettleUpdateFraction(v float32) error
- func (bm *BackgroundManager) SetRingElevations(elevations []float64) error
- func (bm *BackgroundManager) SetSeedFromFirstObservation(v bool) error
- func (bm *BackgroundManager) SetWarmupParams(durationNanos int64, minFrames int) error
- func (bm *BackgroundManager) ToASCPoints() []PointASC
- type BackgroundParams
- type BackgroundParamsExport
- type BgSnapshot
- type BgStore
- type ClassificationFeatures
- type ClassificationParamsExport
- type ClassificationResult
- type ClusteringParamsExport
- type CoarseBucket
- type DBSCANParams
- type Event
- type ExportedCell
- type ForegroundForwarder
- type ForegroundFrame
- type ForegroundSnapshot
- type FrameBuilder
- func GetFrameBuilder(sensorID string) *FrameBuilder
- func NewFrameBuilder(config FrameBuilderConfig) *FrameBuilder
- func NewFrameBuilderWithDebugLogging(sensorID string, debug bool) *FrameBuilder
- func NewFrameBuilderWithDebugLoggingAndInterval(sensorID string, debug bool, logInterval time.Duration) *FrameBuilder
- func NewFrameBuilderWithLogging(sensorID string) *FrameBuilder
- func (fb *FrameBuilder) AddPointsPolar(polar []PointPolar)
- func (fb *FrameBuilder) EnableTimeBased(enable bool)
- func (fb *FrameBuilder) GetCurrentFrameStats() (frameCount int, oldestAge time.Duration, newestAge time.Duration)
- func (fb *FrameBuilder) RequestExportFrameBatchASC(count int)
- func (fb *FrameBuilder) RequestExportNextFrameASC()
- func (fb *FrameBuilder) Reset()
- func (fb *FrameBuilder) SetDebug(enabled bool)
- func (fb *FrameBuilder) SetMotorSpeed(rpm uint16)
- type FrameBuilderConfig
- type FrameID
- type FrameMetrics
- type FrameStats
- type GridHeatmap
- type LiDARFrame
- type NoiseCoverageMetrics
- type ObjectClass
- type Point
- type PointASC
- type PointPolar
- type PolarPointCompact
- type Pose
- type PoseCache
- type ProjectedPoint
- type Region
- type RegionDebugInfo
- type RegionInfo
- type RegionManager
- type RegionParams
- type RetentionConfig
- type RingBuffer
- type RunComparison
- type RunParams
- type RunStatistics
- type RunTrack
- type SensorConfig
- type SidecarState
- type SpatialIndex
- type SystemEvent
- type Track
- type TrackClassifier
- type TrackMatch
- type TrackMerge
- type TrackObs
- type TrackObservation
- type TrackPoint
- type TrackPointCloudExporter
- type TrackPointCloudFrame
- type TrackPointCloudMetadata
- type TrackQualityMetrics
- type TrackSplit
- type TrackState
- type TrackState2D
- type TrackStore
- type TrackSummary
- type TrackTrainingFilter
- type TrackedObject
- func FilterTracksForTraining(tracks []*TrackedObject, filter *TrackTrainingFilter) []*TrackedObject
- func GetActiveTracks(db *sql.DB, sensorID string, state string) ([]*TrackedObject, error)
- func GetTracksInRange(db *sql.DB, sensorID string, state string, startNanos, endNanos int64, ...) ([]*TrackedObject, error)
- type Tracker
- func (t *Tracker) GetActiveTracks() []*TrackedObject
- func (t *Tracker) GetAllTracks() []*TrackedObject
- func (t *Tracker) GetConfirmedTracks() []*TrackedObject
- func (t *Tracker) GetTrack(trackID string) *TrackedObject
- func (t *Tracker) GetTrackCount() (total, tentative, confirmed, deleted int)
- func (t *Tracker) Update(clusters []WorldCluster, timestamp time.Time)
- type TrackerConfig
- type TrackingParamsExport
- type TrackingPipelineConfig
- type TrainingDataFilter
- type TrainingDatasetSummary
- type TrainingFrameMetadata
- type WorldCluster
- type WorldPoint
Constants ¶
const ( // Height thresholds (meters) BirdHeightMax = 0.5 // Birds are typically small PedestrianHeightMin = 1.0 // Pedestrians are at least 1m tall PedestrianHeightMax = 2.2 // Pedestrians are typically under 2.2m VehicleHeightMin = 1.2 // Vehicles are at least 1.2m VehicleLengthMin = 3.0 // Vehicles are at least 3m long VehicleWidthMin = 1.5 // Vehicles are at least 1.5m wide // Speed thresholds (m/s) BirdSpeedMax = 1.0 // Birds detected at low speeds PedestrianSpeedMax = 3.0 // Pedestrians walk up to ~3 m/s (10.8 km/h) VehicleSpeedMin = 5.0 // Vehicles typically move faster than 5 m/s StationarySpeedMax = 0.5 // Stationary threshold // Confidence levels HighConfidence = 0.85 MediumConfidence = 0.70 LowConfidence = 0.50 // Minimum observations for classification MinObservationsForClassification = 5 )
Classification thresholds (configurable for tuning)
const ( // DefaultDBSCANEps is the default neighborhood radius in meters for DBSCAN DefaultDBSCANEps = 0.6 // DefaultDBSCANMinPts is the default minimum points to form a cluster DefaultDBSCANMinPts = 12 // EstimatedPointsPerCell is used for initial spatial index capacity estimation EstimatedPointsPerCell = 4 )
Constants for clustering configuration
const ( // DefaultClosenessSensitivityMultiplier is the default multiplier for closeness threshold DefaultClosenessSensitivityMultiplier = 3.0 // DefaultNeighborConfirmationCount is the default number of neighbors needed for confirmation DefaultNeighborConfirmationCount = 3 // FreezeThresholdMultiplier is the multiplier applied to closeness threshold to trigger cell freeze FreezeThresholdMultiplier = 3.0 // DefaultReacquisitionBoostMultiplier is the default multiplier for fast re-acquisition DefaultReacquisitionBoostMultiplier = 5.0 // DefaultMinConfidenceFloor is the minimum TimesSeenCount to preserve during foreground DefaultMinConfidenceFloor = 3 // ThawGracePeriodNanos is the minimum time after freeze expiry before thaw detection triggers. // This prevents false triggers when FreezeDurationNanos=0 causes immediate "expiry". ThawGracePeriodNanos = int64(1_000_000) // 1ms // DefaultLockedBaselineThreshold is the minimum observations before locking baseline DefaultLockedBaselineThreshold = 50 // DefaultLockedBaselineMultiplier defines the acceptance window as LockedSpread * multiplier DefaultLockedBaselineMultiplier = 4.0 )
Constants for foreground extraction configuration
const ( // MinAzimuthCoverage is the minimum azimuth coverage (degrees) required for a valid frame // Must cover at least 340° of a full 360° rotation to be considered complete MinAzimuthCoverage = 340.0 // MinFramePointsForCompletion is the minimum number of points required for frame completion // Ensures substantial data before declaring a rotation complete (typical full rotation: ~70k points) MinFramePointsForCompletion = 10000 )
Frame detection constants for azimuth-based rotation detection
const ( // MinDeterminantThreshold is the minimum determinant for covariance matrix inversion MinDeterminantThreshold = 1e-6 // SingularDistanceRejection is the distance returned when covariance is singular SingularDistanceRejection = 1e9 // MaxSpeedHistoryLength is the maximum number of speed samples kept for percentile computation MaxSpeedHistoryLength = 100 // DefaultDeletedTrackGracePeriod is how long to keep deleted tracks before cleanup DefaultDeletedTrackGracePeriod = 5 * time.Second // MaxReasonableSpeedMps is the maximum reasonable speed for any tracked object (m/s) // Used to reject spurious associations that would imply impossible velocities MaxReasonableSpeedMps = 30.0 // ~108 km/h, ~67 mph // MaxPositionJumpMeters is the maximum allowed position jump between consecutive observations // Observations beyond this distance are rejected as likely false associations MaxPositionJumpMeters = 5.0 )
Constants for tracker configuration
const CompactPointSize = 8
CompactPointSize is the size in bytes of a single compact point.
Variables ¶
var IdentityTransform4x4 = [16]float64{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}
IdentityTransform4x4 is a 4x4 identity matrix for pose transforms. T is row-major: [m00,m01,m02,m03, m10,m11,m12,m13, m20,m21,m22,m23, m30,m31,m32,m33]
Functions ¶
func ApplyPose ¶
ApplyPose applies a 4x4 row-major transform T to point (x,y,z). T is expected as [16]float64 row-major: m00,m01,m02,m03, m10,...
func ClearTracks ¶
ClearTracks removes all tracks, observations, and clusters for a sensor. This is intended for development/debug resets and should not be exposed in production without auth.
func ComputeSpeedPercentiles ¶
ComputeSpeedPercentiles computes speed percentiles from a track's speed history. Uses floor-based indexing for percentiles. For small arrays (n<3), all percentiles may return similar values. For production use with precise percentile requirements, consider using linear interpolation between neighboring values.
func Debugf ¶
func Debugf(format string, args ...interface{})
Debugf is an exported helper for callers outside the lidar package.
func EncodeForegroundBlob ¶
func EncodeForegroundBlob(points []PointPolar) []byte
EncodeForegroundBlob encodes foreground points to a compact binary blob. Format: Each point is 8 bytes: distance(2) + azimuth(2) + elevation(2) + intensity(1) + ring(1)
func EncodePandar40PPacket ¶
func EncodePandar40PPacket(points []PointPolar, blockAzimuth float64, config *SensorConfig) ([]byte, error)
EncodePandar40PPacket encodes polar points into a Pandar40P-compatible UDP packet format. This allows exported tracks to be loaded in LidarView for visual inspection.
Pandar40P packet structure (1262 bytes): - 10 data blocks × 124 bytes each - Each block: 2-byte preamble (0xFFEE) + 2-byte azimuth + 40 channels × 3 bytes - 22-byte tail with timestamp and metadata
func ExportBgSnapshotToASC ¶
func ExportBgSnapshotToASC(snap *BgSnapshot, ringElevations []float64) (string, error)
ExportBgSnapshotToASC decodes a BgSnapshot's grid blob, constructs a temporary BackgroundGrid and BackgroundManager, supplies per-ring elevations (preferring a live BackgroundManager and falling back to embedded parser config), and exports the resulting points to an ASC file. Returns the path where the file was written.
func ExportForegroundSnapshotToASC ¶
func ExportForegroundSnapshotToASC(snap *ForegroundSnapshot) (string, error)
ExportForegroundSnapshotToASC writes only the foreground points to an ASC file. This is intended for quick inspection of live/replayed foreground extraction. Returns the path where the file was written.
func ExportPointsToASC ¶
ExportPointsToASC exports a slice of PointASC to a CloudCompare-compatible .asc file. The export path is generated internally using a timestamp and random suffix to prevent path traversal attacks. Returns the actual path where the file was written. extraHeader is a string describing extra columns (optional)
func InsertCluster ¶
func InsertCluster(db *sql.DB, cluster *WorldCluster) (int64, error)
InsertCluster inserts a cluster into the database and returns its ID.
func InsertTrack ¶
func InsertTrack(db *sql.DB, track *TrackedObject, worldFrame string) error
InsertTrack inserts a new track into the database.
func InsertTrackObservation ¶
func InsertTrackObservation(db *sql.DB, obs *TrackObservation) error
InsertTrackObservation inserts a track observation into the database.
func RegisterAnalysisRunManager ¶
func RegisterAnalysisRunManager(sensorID string, manager *AnalysisRunManager)
RegisterAnalysisRunManager registers a manager for a sensor ID.
func RegisterBackgroundManager ¶
func RegisterBackgroundManager(sensorID string, mgr *BackgroundManager)
RegisterBackgroundManager registers a BackgroundManager for a sensor ID.
func RegisterFrameBuilder ¶
func RegisterFrameBuilder(sensorID string, fb *FrameBuilder)
RegisterFrameBuilder registers a FrameBuilder for a sensor ID.
func SetDebugLogger ¶
SetDebugLogger installs a debug logger that receives verbose LiDAR diagnostics. Pass nil to disable debug logging.
func SphericalToCartesian ¶
SphericalToCartesian converts distance (meters), azimuth (degrees) and elevation (degrees) into Cartesian sensor-frame coordinates. Coordinate convention: X=right, Y=forward, Z=up (matches existing code).
func StoreForegroundSnapshot ¶
func StoreForegroundSnapshot(sensorID string, ts time.Time, foreground []PointPolar, background []PointPolar, totalPoints int, foregroundPoints int)
StoreForegroundSnapshot saves the latest foreground/background projections for a sensor. Points are projected in sensor frame (using az/el) to align with background polar charts.
func UpdateTrack ¶
func UpdateTrack(db *sql.DB, track *TrackedObject, worldFrame string) error
UpdateTrack updates an existing track in the database.
func WriteNetworkStream ¶
func WriteNetworkStream(packets [][]byte, destAddr string, config *SensorConfig) error
WriteNetworkStream sends packets to a UDP destination for real-time inspection. Allows streaming isolated track data to LidarView without intermediate files.
func WritePCAPFile ¶
func WritePCAPFile(packets [][]byte, outputPath string, config *SensorConfig) error
WritePCAPFile writes a sequence of packets to a PCAP file for LidarView inspection. This is a stub - actual implementation requires pcap library integration.
Types ¶
type AcceptanceMetrics ¶
AcceptanceMetrics exposes the acceptance/rejection counts per range bucket.
type AnalysisRun ¶
type AnalysisRun struct {
RunID string `json:"run_id"`
CreatedAt time.Time `json:"created_at"`
SourceType string `json:"source_type"` // "pcap" or "live"
SourcePath string `json:"source_path,omitempty"`
SensorID string `json:"sensor_id"`
ParamsJSON json.RawMessage `json:"params_json"`
DurationSecs float64 `json:"duration_secs"`
TotalFrames int `json:"total_frames"`
TotalClusters int `json:"total_clusters"`
TotalTracks int `json:"total_tracks"`
ConfirmedTracks int `json:"confirmed_tracks"`
ProcessingTimeMs int64 `json:"processing_time_ms"`
Status string `json:"status"` // "running", "completed", "failed"
ErrorMessage string `json:"error_message,omitempty"`
ParentRunID string `json:"parent_run_id,omitempty"`
Notes string `json:"notes,omitempty"`
}
AnalysisRun represents a complete analysis session with parameters. All LIDAR parameters are stored in ParamsJSON for full reproducibility.
type AnalysisRunManager ¶
type AnalysisRunManager struct {
// contains filtered or unexported fields
}
AnalysisRunManager coordinates analysis run lifecycle and track collection. It is safe for concurrent use and provides hooks for the tracking pipeline.
func GetAnalysisRunManager ¶
func GetAnalysisRunManager(sensorID string) *AnalysisRunManager
GetAnalysisRunManager retrieves the manager for a sensor ID.
func NewAnalysisRunManager ¶
func NewAnalysisRunManager(db *sql.DB, sensorID string) *AnalysisRunManager
NewAnalysisRunManager creates a new manager for tracking analysis runs.
func (*AnalysisRunManager) CompleteRun ¶
func (m *AnalysisRunManager) CompleteRun() error
CompleteRun finalizes the current analysis run with statistics.
func (*AnalysisRunManager) CurrentRunID ¶
func (m *AnalysisRunManager) CurrentRunID() string
CurrentRunID returns the current run ID, or empty string if no run is active.
func (*AnalysisRunManager) FailRun ¶
func (m *AnalysisRunManager) FailRun(errMsg string) error
FailRun marks the current run as failed with an error message.
func (*AnalysisRunManager) GetCurrentRunParams ¶
func (m *AnalysisRunManager) GetCurrentRunParams() (RunParams, bool)
GetCurrentRunParams retrieves the current run's parameters for display.
func (*AnalysisRunManager) IsRunActive ¶
func (m *AnalysisRunManager) IsRunActive() bool
IsRunActive returns true if there's an active analysis run.
func (*AnalysisRunManager) RecordClusters ¶
func (m *AnalysisRunManager) RecordClusters(count int)
RecordClusters increments the cluster count for the current run.
func (*AnalysisRunManager) RecordFrame ¶
func (m *AnalysisRunManager) RecordFrame()
RecordFrame increments the frame count for the current run.
func (*AnalysisRunManager) RecordTrack ¶
func (m *AnalysisRunManager) RecordTrack(track *TrackedObject) bool
RecordTrack records a track for the current analysis run. This inserts a RunTrack record and returns true if this is a new track.
type AnalysisRunStore ¶
type AnalysisRunStore struct {
// contains filtered or unexported fields
}
AnalysisRunStore provides persistence for analysis runs.
func NewAnalysisRunStore ¶
func NewAnalysisRunStore(db *sql.DB) *AnalysisRunStore
NewAnalysisRunStore creates a new AnalysisRunStore.
func (*AnalysisRunStore) CompleteRun ¶
func (s *AnalysisRunStore) CompleteRun(runID string, stats *AnalysisStats) error
CompleteRun marks a run as completed with final statistics.
func (*AnalysisRunStore) GetLabelingProgress ¶
func (s *AnalysisRunStore) GetLabelingProgress(runID string) (total, labeled int, byClass map[string]int, err error)
GetLabelingProgress returns labeling statistics for a run.
func (*AnalysisRunStore) GetRun ¶
func (s *AnalysisRunStore) GetRun(runID string) (*AnalysisRun, error)
GetRun retrieves an analysis run by ID.
func (*AnalysisRunStore) GetRunTracks ¶
func (s *AnalysisRunStore) GetRunTracks(runID string) ([]*RunTrack, error)
GetRunTracks retrieves all tracks for an analysis run.
func (*AnalysisRunStore) GetUnlabeledTracks ¶
func (s *AnalysisRunStore) GetUnlabeledTracks(runID string, limit int) ([]*RunTrack, error)
GetUnlabeledTracks returns tracks that need labeling.
func (*AnalysisRunStore) InsertRun ¶
func (s *AnalysisRunStore) InsertRun(run *AnalysisRun) error
InsertRun creates a new analysis run.
func (*AnalysisRunStore) InsertRunTrack ¶
func (s *AnalysisRunStore) InsertRunTrack(track *RunTrack) error
InsertRunTrack inserts a track for an analysis run. Uses retry logic to handle SQLITE_BUSY errors from concurrent writes.
func (*AnalysisRunStore) ListRuns ¶
func (s *AnalysisRunStore) ListRuns(limit int) ([]*AnalysisRun, error)
ListRuns retrieves recent analysis runs.
func (*AnalysisRunStore) UpdateRunStatus ¶
func (s *AnalysisRunStore) UpdateRunStatus(runID, status, errorMsg string) error
UpdateRunStatus updates the status of an analysis run.
func (*AnalysisRunStore) UpdateTrackLabel ¶
func (s *AnalysisRunStore) UpdateTrackLabel(runID, trackID, userLabel string, confidence float32, labelerID string) error
UpdateTrackLabel updates the user label for a track.
func (*AnalysisRunStore) UpdateTrackQualityFlags ¶
func (s *AnalysisRunStore) UpdateTrackQualityFlags(runID, trackID string, isSplit, isMerge bool, linkedIDs []string) error
UpdateTrackQualityFlags updates the split/merge flags for a track.
type AnalysisStats ¶
type AnalysisStats struct {
DurationSecs float64
TotalFrames int
TotalClusters int
TotalTracks int
ConfirmedTracks int
ProcessingTimeMs int64
}
AnalysisStats holds statistics for a completed analysis run.
type BackgroundCell ¶
type BackgroundCell struct {
AverageRangeMeters float32
RangeSpreadMeters float32
TimesSeenCount uint32
LastUpdateUnixNanos int64
FrozenUntilUnixNanos int64
// RecentForegroundCount tracks consecutive foreground observations.
// Used for fast re-acquisition: when this is >0 and observation matches
// background, we apply boosted alpha for faster convergence.
RecentForegroundCount uint16
// LockedBaseline is the stable reference distance that only updates when
// we have high confidence (TimesSeenCount > LockedThreshold). This protects
// against transit corruption where EMA average drifts during occlusion.
LockedBaseline float32
// LockedSpread is the acceptable variance around LockedBaseline. Observations
// within LockedBaseline ± (LockedSpread * multiplier) are considered background.
// This allows per-cell variance (trees, glass have more variance).
LockedSpread float32
// LockedAtCount is the TimesSeenCount when baseline was last locked.
// Used to detect when we should update the locked values.
LockedAtCount uint32
}
BackgroundCell matches the compressed storage format for schema persistence
type BackgroundGrid ¶
type BackgroundGrid struct {
SensorID string
SensorFrame FrameID // e.g., "sensor/hesai-01"
Rings int // e.g., 40 - matches schema rings INTEGER NOT NULL
AzimuthBins int // e.g., 1800 for 0.2° - matches schema azimuth_bins INTEGER NOT NULL
Cells []BackgroundCell // len = Rings * AzimuthBins
Params BackgroundParams
// Enhanced persistence tracking matching schema lidar_bg_snapshot table
Manager *BackgroundManager
LastSnapshotTime time.Time
ChangesSinceSnapshot int
SnapshotID *int64 // tracks last persisted snapshot_id from schema
// Performance tracking for system_events table integration
LastProcessingTimeUs int64
WarmupFramesRemaining int
SettlingComplete bool
// Telemetry for monitoring (feeds into system_events)
ForegroundCount int64
BackgroundCount int64
// Simple range-bucketed acceptance metrics to help tune NoiseRelativeFraction.
// Buckets are upper bounds in meters; counts are number of accepted/rejected
// observations that fell into that distance bucket. These are incremented
// inside ProcessFramePolar while holding g.mu, and can be read via
// BackgroundManager.GetAcceptanceMetrics().
AcceptanceBucketsMeters []float64
AcceptByRangeBuckets []int64
RejectByRangeBuckets []int64
// Optional per-ring elevation angles (degrees) for converting polar->cartesian.
// If populated (len == Rings) ToASCPoints will use these to compute Z = r*sin(elev).
RingElevations []float64
// LastObservedNoiseRel tracks the last noise_relative value observed by
// ProcessFramePolar so we can log when the runtime value changes.
LastObservedNoiseRel float32
// RegionMgr handles adaptive parameter regions for different settling characteristics
RegionMgr *RegionManager
// contains filtered or unexported fields
}
BackgroundGrid enhanced for schema persistence and 100-track performance
func (*BackgroundGrid) Idx ¶
func (g *BackgroundGrid) Idx(ring, azBin int) int
Helper to index Cells: idx = ring*AzimuthBins + azBin
type BackgroundManager ¶
type BackgroundManager struct {
Grid *BackgroundGrid
SettlingTimer *time.Timer
PersistTimer *time.Timer
HasSettled bool
LastPersistTime time.Time
StartTime time.Time
// Persistence callback to main app - should save to schema lidar_bg_snapshot table
PersistCallback func(snapshot *BgSnapshot) error
// EnableDiagnostics controls whether this manager emits diagnostic messages
// via the shared monitoring logger. Default: false.
EnableDiagnostics bool
// contains filtered or unexported fields
}
BackgroundManager handles automatic persistence following schema lidar_bg_snapshot pattern
func GetBackgroundManager ¶
func GetBackgroundManager(sensorID string) *BackgroundManager
GetBackgroundManager returns a registered manager or nil
func NewBackgroundManager ¶
func NewBackgroundManager(sensorID string, rings, azBins int, params BackgroundParams, store BgStore) *BackgroundManager
NewBackgroundManager creates a BackgroundGrid and manager, registers it under sensorID, and optionally wires a BgStore for persistence (sets PersistCallback to call Persist).
func (*BackgroundManager) ExportBackgroundGridToASC ¶
func (bm *BackgroundManager) ExportBackgroundGridToASC() (string, error)
ExportBackgroundGridToASC exports the background grid using the shared ASC export utility. Returns the actual path where the file was written.
func (*BackgroundManager) GetAcceptanceMetrics ¶
func (bm *BackgroundManager) GetAcceptanceMetrics() *AcceptanceMetrics
GetAcceptanceMetrics returns a snapshot of the acceptance metrics. The returned slices are copies and safe for the caller to inspect without further synchronization.
func (*BackgroundManager) GetGridCells ¶
func (bm *BackgroundManager) GetGridCells() []ExportedCell
GetGridCells returns all non-empty cells from the grid.
func (*BackgroundManager) GetGridHeatmap ¶
func (bm *BackgroundManager) GetGridHeatmap(azimuthBucketDeg float64, settledThreshold uint32) *GridHeatmap
GetGridHeatmap aggregates the fine-grained grid into coarse spatial buckets for visualization and analysis. Returns nil if the manager or grid is nil.
Parameters:
- azimuthBucketDeg: size of each azimuth bucket in degrees (e.g., 3.0 for 120 buckets)
- settledThreshold: minimum TimesSeenCount to consider a cell "settled"
func (*BackgroundManager) GetParams ¶
func (bm *BackgroundManager) GetParams() BackgroundParams
GetParams returns a copy of the BackgroundParams for the manager's grid.
func (*BackgroundManager) GetRegionDebugInfo ¶
func (bm *BackgroundManager) GetRegionDebugInfo(includeCells bool) *RegionDebugInfo
GetRegionDebugInfo returns comprehensive region information for debugging
func (*BackgroundManager) GridStatus ¶
func (bm *BackgroundManager) GridStatus() map[string]interface{}
GridStatus returns a simple snapshot of grid-level statistics useful for debugging settling behavior. The returned map includes total_cells, frozen_cells, a times-seen distribution (string->count) and foreground/background counters.
func (*BackgroundManager) Persist ¶
func (bm *BackgroundManager) Persist(store BgStore, reason string) error
Persist serializes the BackgroundGrid and writes a BgSnapshot via the provided store. It updates grid snapshot metadata on success.
func (*BackgroundManager) ProcessFramePolar ¶
func (bm *BackgroundManager) ProcessFramePolar(points []PointPolar)
ProcessFramePolar ingests sensor-frame polar points and updates the BackgroundGrid. Behavior:
- Bins points by ring (channel) and azimuth bin.
- Uses an EMA (BackgroundUpdateFraction) to update AverageRangeMeters and RangeSpreadMeters.
- Tracks a simple two-level confidence via TimesSeenCount (increment on close matches, decrement on mismatches). When a cell deviates strongly repeatedly it is frozen for FreezeDurationNanos to avoid corrupting the background model.
- Uses neighbor confirmation: updates are applied more readily when adjacent cells agree (helps suppress isolated noise).
func (*BackgroundManager) ProcessFramePolarWithMask ¶
func (bm *BackgroundManager) ProcessFramePolarWithMask(points []PointPolar) (foregroundMask []bool, err error)
ProcessFramePolarWithMask classifies each point as foreground/background in polar coordinates. Returns a mask where true indicates foreground (object), false indicates background (static). This is Phase 2.9 of the foreground tracking pipeline.
Unlike ProcessFramePolar which aggregates points per cell, this operates per-point for finer-grained foreground detection suitable for downstream clustering.
func (*BackgroundManager) ResetAcceptanceMetrics ¶
func (bm *BackgroundManager) ResetAcceptanceMetrics() error
ResetAcceptanceMetrics zeros the acceptance/rejection counters for the grid. This is intended for clean A/B testing when tuning parameters.
func (*BackgroundManager) ResetGrid ¶
func (bm *BackgroundManager) ResetGrid() error
ResetGrid zeros per-cell stats (AverageRangeMeters, RangeSpreadMeters, TimesSeenCount, LastUpdateUnixNanos, FrozenUntilUnixNanos) and acceptance counters. Intended for testing and A/B sweeps only.
func (*BackgroundManager) SetClosenessSensitivityMultiplier ¶
func (bm *BackgroundManager) SetClosenessSensitivityMultiplier(v float32) error
SetClosenessSensitivityMultiplier safely updates the ClosenessSensitivityMultiplier parameter.
func (*BackgroundManager) SetEnableDiagnostics ¶
func (bm *BackgroundManager) SetEnableDiagnostics(v bool)
SetEnableDiagnostics toggles emission of diagnostics for this manager.
func (*BackgroundManager) SetForegroundClusterParams ¶
func (bm *BackgroundManager) SetForegroundClusterParams(minPts int, eps float32) error
SetForegroundClusterParams updates the minimum cluster size and eps used for foreground gating.
func (*BackgroundManager) SetNeighborConfirmationCount ¶
func (bm *BackgroundManager) SetNeighborConfirmationCount(v int) error
SetNeighborConfirmationCount safely updates the NeighborConfirmationCount parameter.
func (*BackgroundManager) SetNoiseRelativeFraction ¶
func (bm *BackgroundManager) SetNoiseRelativeFraction(v float32) error
SetNoiseRelativeFraction safely updates the NoiseRelativeFraction parameter.
func (*BackgroundManager) SetParams ¶
func (bm *BackgroundManager) SetParams(p BackgroundParams) error
SetParams replaces the manager's BackgroundParams atomically.
func (*BackgroundManager) SetPostSettleUpdateFraction ¶
func (bm *BackgroundManager) SetPostSettleUpdateFraction(v float32) error
SetPostSettleUpdateFraction updates the post-settle alpha.
func (*BackgroundManager) SetRingElevations ¶
func (bm *BackgroundManager) SetRingElevations(elevations []float64) error
SetRingElevations sets per-ring elevation angles (degrees) on the BackgroundGrid. The provided slice must have length equal to the grid's Rings; values are copied.
func (*BackgroundManager) SetSeedFromFirstObservation ¶
func (bm *BackgroundManager) SetSeedFromFirstObservation(v bool) error
SetSeedFromFirstObservation toggles seeding empty cells from the first observation.
func (*BackgroundManager) SetWarmupParams ¶
func (bm *BackgroundManager) SetWarmupParams(durationNanos int64, minFrames int) error
SetWarmupParams updates settle duration/frame requirements.
func (*BackgroundManager) ToASCPoints ¶
func (bm *BackgroundManager) ToASCPoints() []PointASC
ToASCPoints converts the background grid to a slice of PointASC for export.
type BackgroundParams ¶
type BackgroundParams struct {
BackgroundUpdateFraction float32 // e.g., 0.02
ClosenessSensitivityMultiplier float32 // e.g., 3.0
SafetyMarginMeters float32 // e.g., 0.5
FreezeDurationNanos int64 // e.g., 5e9 (5s)
NeighborConfirmationCount int // e.g., 5 of 8 neighbors
WarmupDurationNanos int64 // optional extra settle time before emitting foreground
WarmupMinFrames int // optional minimum frames before considering settled
PostSettleUpdateFraction float32 // optional lower alpha after settle for stability
ForegroundMinClusterPoints int // min points for a cluster to be forwarded/considered
ForegroundDBSCANEps float32 // clustering radius for foreground gating
// NoiseRelativeFraction is the fraction of range (distance) to treat as
// expected measurement noise. This allows closeness thresholds to grow
// with distance so that farther returns (which naturally have larger
// absolute noise) aren't biased as foreground. Typical values: 0.01
// (1%) to 0.02 (2%). If zero, a sensible default (0.01) is used.
NoiseRelativeFraction float32
// SeedFromFirstObservation, when true, will initialize empty background cells
// from the first observation seen for that cell. This is useful for PCAP
// replay mode where there is no prior live-warmup data; default: false.
SeedFromFirstObservation bool
// ReacquisitionBoostMultiplier controls how much faster cells re-acquire
// background after a foreground event. When a cell that recently saw foreground
// receives an observation matching the prior background, the effective alpha
// is multiplied by this factor for faster convergence. Default: 5.0.
// Set to 1.0 to disable the boost.
ReacquisitionBoostMultiplier float32
// MinConfidenceFloor is the minimum TimesSeenCount to preserve during foreground
// observations. This prevents cells from completely "forgetting" their settled
// background when a vehicle passes through. Default: 3.
MinConfidenceFloor uint32
// LockedBaselineThreshold is the minimum TimesSeenCount before we lock the
// baseline. Once locked, the baseline only updates slowly. Default: 50.
LockedBaselineThreshold uint32
// LockedBaselineMultiplier controls how many times the LockedSpread defines
// the acceptance window. Observations within LockedBaseline ± (LockedSpread *
// LockedBaselineMultiplier) are considered background. Default: 4.0.
LockedBaselineMultiplier float32
// Debug logging region (only active if EnableDiagnostics is true)
DebugRingMin int // Min ring index (inclusive)
DebugRingMax int // Max ring index (inclusive)
DebugAzMin float32 // Min azimuth degrees (inclusive)
DebugAzMax float32 // Max azimuth degrees (inclusive)
// Additional params for persistence matching schema requirements
SettlingPeriodNanos int64 // 5 minutes before first snapshot
SnapshotIntervalNanos int64 // 2 hours between snapshots
ChangeThresholdForSnapshot int // min changed cells to trigger snapshot
}
BackgroundParams configuration matching the param storage approach in schema
func (BackgroundParams) HasDebugRange ¶
func (p BackgroundParams) HasDebugRange() bool
HasDebugRange returns true if any debug range parameters are set.
func (BackgroundParams) IsInDebugRange ¶
func (p BackgroundParams) IsInDebugRange(ring int, az float64) bool
IsInDebugRange returns true if the given ring and azimuth fall within the configured debug range. If no range is configured, it returns false.
type BackgroundParamsExport ¶
type BackgroundParamsExport struct {
BackgroundUpdateFraction float32 `json:"background_update_fraction"`
ClosenessSensitivityMultiplier float32 `json:"closeness_sensitivity_multiplier"`
SafetyMarginMeters float32 `json:"safety_margin_meters"`
NeighborConfirmationCount int `json:"neighbor_confirmation_count"`
NoiseRelativeFraction float32 `json:"noise_relative_fraction"`
SeedFromFirstObservation bool `json:"seed_from_first_observation"`
FreezeDurationNanos int64 `json:"freeze_duration_nanos"`
}
BackgroundParamsExport is the JSON-serializable background params.
func FromBackgroundParams ¶
func FromBackgroundParams(p BackgroundParams) BackgroundParamsExport
FromBackgroundParams creates export params from BackgroundParams.
type BgSnapshot ¶
type BgSnapshot struct {
SnapshotID *int64 // will be set by database after insert
SensorID string // matches sensor_id TEXT NOT NULL
TakenUnixNanos int64 // matches taken_unix_nanos INTEGER NOT NULL
Rings int // matches rings INTEGER NOT NULL
AzimuthBins int // matches azimuth_bins INTEGER NOT NULL
ParamsJSON string // matches params_json TEXT NOT NULL
RingElevationsJSON string // matches ring_elevations_json TEXT NULL - optional per-ring elevation JSON
GridBlob []byte // matches grid_blob BLOB NOT NULL (compressed BackgroundCell data)
ChangedCellsCount int // matches changed_cells_count INTEGER
SnapshotReason string // matches snapshot_reason TEXT ('settling_complete', 'periodic_update', 'manual')
}
BgSnapshot exactly matches schema lidar_bg_snapshot table structure
type BgStore ¶
type BgStore interface {
InsertBgSnapshot(s *BgSnapshot) (int64, error)
}
BgStore is an interface required to persist BgSnapshot records. Implemented by lidardb.LidarDB.
type ClassificationFeatures ¶
type ClassificationFeatures struct {
// Spatial features
AvgHeight float32 // Average bounding box height
AvgLength float32 // Average bounding box length
AvgWidth float32 // Average bounding box width
HeightP95 float32 // Maximum P95 height
// Kinematic features
AvgSpeed float32 // Average speed
PeakSpeed float32 // Peak speed
P50Speed float32 // Median speed
P85Speed float32 // 85th percentile speed
P95Speed float32 // 95th percentile speed
// Temporal features
ObservationCount int
DurationSecs float32
}
ClassificationFeatures holds the features used for classification.
type ClassificationParamsExport ¶
type ClassificationParamsExport struct {
ModelType string `json:"model_type"`
Thresholds map[string]interface{} `json:"thresholds,omitempty"`
}
ClassificationParamsExport is the JSON-serializable classification params.
type ClassificationResult ¶
type ClassificationResult struct {
Class ObjectClass
Confidence float32
Model string // Model version used
Features ClassificationFeatures
}
ClassificationResult holds the result of track classification.
type ClusteringParamsExport ¶
type ClusteringParamsExport struct {
Eps float64 `json:"eps"`
MinPts int `json:"min_pts"`
CellSize float64 `json:"cell_size,omitempty"`
}
ClusteringParamsExport is the JSON-serializable clustering params.
func FromDBSCANParams ¶
func FromDBSCANParams(p DBSCANParams) ClusteringParamsExport
FromDBSCANParams creates export params from DBSCANParams.
type CoarseBucket ¶
type CoarseBucket struct {
Ring int `json:"ring"`
AzimuthDegStart float64 `json:"azimuth_deg_start"`
AzimuthDegEnd float64 `json:"azimuth_deg_end"`
TotalCells int `json:"total_cells"`
FilledCells int `json:"filled_cells"`
SettledCells int `json:"settled_cells"`
FrozenCells int `json:"frozen_cells"`
MeanTimesSeen float64 `json:"mean_times_seen"`
MeanRangeMeters float64 `json:"mean_range_meters"`
MinRangeMeters float64 `json:"min_range_meters"`
MaxRangeMeters float64 `json:"max_range_meters"`
}
CoarseBucket represents aggregated metrics for a spatial bucket
type DBSCANParams ¶
type DBSCANParams struct {
Eps float64 // Neighborhood radius in meters
MinPts int // Minimum points to form a cluster
}
DBSCANParams contains parameters for the DBSCAN clustering algorithm.
func DefaultDBSCANParams ¶
func DefaultDBSCANParams() DBSCANParams
DefaultDBSCANParams returns default DBSCAN parameters suitable for vehicle detection.
type Event ¶
type Event struct {
When time.Time // event timestamp
Level string // "info", "warn", "error", "debug"
Message string // human-readable message
Context map[string]interface{} // structured context data
// Schema integration fields
SensorID *string // sensor that generated the event (if applicable)
EventType string // maps to system_events.event_type for persistence
}
Event represents a system event with structured context for debugging and monitoring
func NewPerformanceEvent ¶
Helper constructors for common event types
func NewTrackInitiateEvent ¶
type ExportedCell ¶
type ExportedCell struct {
Ring int
AzimuthDeg float32
Range float32
Spread float32
TimesSeen uint32
LastUpdate int64
FrozenUntil int64
}
ExportedCell represents a background cell for API consumption
type ForegroundForwarder ¶
type ForegroundForwarder interface {
ForwardForeground(points []PointPolar)
}
ForegroundForwarder interface allows forwarding foreground points without importing network package.
type ForegroundFrame ¶
type ForegroundFrame struct {
SensorID string // Sensor that captured this frame
TSUnixNanos int64 // Timestamp of the frame
SequenceID string // Optional sequence grouping (e.g., "seq_20251130_001")
ForegroundPoints []PointPolar // Foreground points in polar (sensor) frame
// Frame statistics
TotalPoints int
BackgroundPoints int
}
ForegroundFrame represents a single frame of foreground points for ML training. Points are stored in sensor frame (polar coordinates) for pose independence.
func ExportForegroundFrame ¶
func ExportForegroundFrame(polarPoints []PointPolar, mask []bool, sensorID string, ts time.Time) *ForegroundFrame
ExportForegroundFrame creates a ForegroundFrame from classified points. Points are stored in polar (sensor) coordinates for pose independence.
func (*ForegroundFrame) ForegroundCount ¶
func (f *ForegroundFrame) ForegroundCount() int
ForegroundCount returns the number of foreground points.
func (*ForegroundFrame) ForegroundFraction ¶
func (f *ForegroundFrame) ForegroundFraction() float64
ForegroundFraction returns the ratio of foreground to total points.
func (*ForegroundFrame) SetSequenceID ¶
func (f *ForegroundFrame) SetSequenceID(sequenceID string)
SetSequenceID assigns this frame to a sequence for grouping.
type ForegroundSnapshot ¶
type ForegroundSnapshot struct {
SensorID string
Timestamp time.Time
ForegroundPoints []ProjectedPoint
BackgroundPoints []ProjectedPoint
TotalPoints int
ForegroundCount int
BackgroundCount int
}
ForegroundSnapshot stores the latest foreground/background projections for a sensor. Points are kept in sensor frame (X=right, Y=forward) to match the background polar chart.
func GetForegroundSnapshot ¶
func GetForegroundSnapshot(sensorID string) *ForegroundSnapshot
GetForegroundSnapshot returns a copy of the latest foreground snapshot for a sensor.
type FrameBuilder ¶
type FrameBuilder struct {
// contains filtered or unexported fields
}
FrameBuilder accumulates points from multiple packets into complete rotational frames Uses azimuth-based rotation detection and UDP sequence tracking for completeness
func GetFrameBuilder ¶
func GetFrameBuilder(sensorID string) *FrameBuilder
GetFrameBuilder returns a registered FrameBuilder or nil
func NewFrameBuilder ¶
func NewFrameBuilder(config FrameBuilderConfig) *FrameBuilder
NewFrameBuilder creates a new FrameBuilder with the specified configuration
func NewFrameBuilderWithDebugLogging ¶
func NewFrameBuilderWithDebugLogging(sensorID string, debug bool) *FrameBuilder
NewFrameBuilderWithDebugLogging creates a FrameBuilder with optional debug logging
func NewFrameBuilderWithDebugLoggingAndInterval ¶
func NewFrameBuilderWithDebugLoggingAndInterval(sensorID string, debug bool, logInterval time.Duration) *FrameBuilder
NewFrameBuilderWithDebugLoggingAndInterval creates a FrameBuilder with optional debug logging and export interval
func NewFrameBuilderWithLogging ¶
func NewFrameBuilderWithLogging(sensorID string) *FrameBuilder
NewFrameBuilderWithLogging creates a FrameBuilder that logs completed frames This is a convenience function for common use cases where you want to log frame completion
func (*FrameBuilder) AddPointsPolar ¶
func (fb *FrameBuilder) AddPointsPolar(polar []PointPolar)
AddPointsPolar accepts polar points (sensor-frame) and converts them to cartesian Points before processing. This is used by network listeners that parse into polar form.
func (*FrameBuilder) EnableTimeBased ¶
func (fb *FrameBuilder) EnableTimeBased(enable bool)
EnableTimeBased enables or disables time-based frame detection
func (*FrameBuilder) GetCurrentFrameStats ¶
func (fb *FrameBuilder) GetCurrentFrameStats() (frameCount int, oldestAge time.Duration, newestAge time.Duration)
GetCurrentFrameStats returns statistics about the frames currently being built
func (*FrameBuilder) RequestExportFrameBatchASC ¶
func (fb *FrameBuilder) RequestExportFrameBatchASC(count int)
RequestExportFrameBatchASC schedules export of the next N completed frames. Export paths are generated internally for security.
func (*FrameBuilder) RequestExportNextFrameASC ¶
func (fb *FrameBuilder) RequestExportNextFrameASC()
RequestExportNextFrameASC schedules export of the next completed frame to ASC format. The export path is generated internally for security.
func (*FrameBuilder) Reset ¶
func (fb *FrameBuilder) Reset()
Reset clears all buffered frame state. This should be called when switching data sources (e.g., live to PCAP) to prevent stale frames from contaminating the new data stream.
func (*FrameBuilder) SetDebug ¶
func (fb *FrameBuilder) SetDebug(enabled bool)
SetDebug enables or disables lightweight debug logging for frame completion
func (*FrameBuilder) SetMotorSpeed ¶
func (fb *FrameBuilder) SetMotorSpeed(rpm uint16)
SetMotorSpeed updates the expected frame duration based on motor speed (RPM) This enables time-based frame detection for accurate motor speed handling
type FrameBuilderConfig ¶
type FrameBuilderConfig struct {
SensorID string // sensor identifier
FrameCallback func(*LiDARFrame) // callback when frame is complete
AzimuthTolerance float64 // tolerance for azimuth wrap detection (default: 10°)
MinFramePoints int // minimum points required for valid frame (default: 1000)
MaxBackfillDelay time.Duration // max time to wait for backfill packets (default: 100ms)
FrameBufferSize int // max frames to buffer (default: 10)
BufferTimeout time.Duration // how long to wait before finalizing frame (default: 1s)
CleanupInterval time.Duration // how often to check for frames to finalize (default: 250ms)
ExpectedFrameDuration time.Duration // expected duration per frame based on motor speed (default: 0 = azimuth-only)
EnableTimeBased bool // true to use time-based detection with azimuth validation
}
FrameBuilderConfig contains configuration for the FrameBuilder
type FrameID ¶
type FrameID string
FrameID is a human-readable name like "sensor/hesai-01" or "site/main-st-001".
type FrameMetrics ¶
type FrameMetrics struct {
TotalPoints int `json:"total_points"`
ForegroundPoints int `json:"foreground_points"`
BackgroundPoints int `json:"background_points"`
ForegroundFraction float64 `json:"foreground_fraction"`
ProcessingTimeUs int64 `json:"processing_time_us"`
}
FrameMetrics contains per-frame statistics about foreground extraction.
func ComputeFrameMetrics ¶
func ComputeFrameMetrics(mask []bool, processingTimeUs int64) FrameMetrics
ComputeFrameMetrics computes metrics from a foreground mask.
type FrameStats ¶
type FrameStats struct {
TSUnixNanos int64
PacketsReceived int
PointsTotal int
ForegroundPoints int
ClustersFound int
TracksActive int
ProcessingTimeUs int64
// Additional metrics for 100-track monitoring
MemoryUsageMB int64
CPUUsagePercent float32
DroppedPackets int64
}
Performance tracking for system_events table integration
type GridHeatmap ¶
type GridHeatmap struct {
SensorID string `json:"sensor_id"`
Timestamp time.Time `json:"timestamp"`
GridParams map[string]interface{} `json:"grid_params"`
HeatmapParams map[string]interface{} `json:"heatmap_params"`
Summary map[string]interface{} `json:"summary"`
Buckets []CoarseBucket `json:"buckets"`
}
GridHeatmap represents the full aggregated grid state
type LiDARFrame ¶
type LiDARFrame struct {
FrameID string // unique identifier for this frame
SensorID string // which sensor generated this frame
StartTimestamp time.Time // timestamp of first point in frame
EndTimestamp time.Time // timestamp of last point in frame
StartWallTime time.Time // wall-clock time when frame started (ingest time)
EndWallTime time.Time // wall-clock time when last point was ingested
Points []Point // all points in this complete rotation
MinAzimuth float64 // minimum azimuth angle observed
MaxAzimuth float64 // maximum azimuth angle observed
PointCount int // total number of points in frame
SpinComplete bool // true when full 360° rotation detected
// Completeness tracking
ExpectedPackets map[uint32]bool // expected UDP sequence numbers
ReceivedPackets map[uint32]bool // received UDP sequence numbers
MissingPackets []uint32 // sequence numbers of missing packets
PacketGaps int // count of missing packets
CompletenessRatio float64 // ratio of received/expected packets
AzimuthCoverage float64 // degrees of azimuth covered (0-360)
}
LiDARFrame represents one complete 360° rotation of LiDAR data
type NoiseCoverageMetrics ¶
type NoiseCoverageMetrics struct {
TotalTracks int `json:"total_tracks"`
TracksWithHighNoise int `json:"tracks_with_high_noise"` // noise_ratio > 0.3
TracksUnknownClass int `json:"tracks_unknown_class"` // object_class == "other"
TracksLowConfidence int `json:"tracks_low_confidence"` // object_confidence < 0.6
UnknownRatioBySpeed map[string]float32 `json:"unknown_ratio_by_speed"` // "slow"/"medium"/"fast"
UnknownRatioBySize map[string]float32 `json:"unknown_ratio_by_size"` // "small"/"medium"/"large"
NoiseRatioHistogram []int `json:"noise_ratio_histogram_counts"` // Counts for bins [0-0.1, 0.1-0.2, ...]
}
NoiseCoverageMetrics quantifies "unknown" classification coverage. Phase 3: Scaffolding for coverage analysis.
func ComputeNoiseCoverageMetrics ¶
func ComputeNoiseCoverageMetrics(tracks []*TrackedObject) *NoiseCoverageMetrics
ComputeNoiseCoverageMetrics calculates coverage metrics for a set of tracks. Phase 3: Placeholder implementation.
type ObjectClass ¶
type ObjectClass string
ObjectClass represents the classification of a tracked object.
const ( // ClassPedestrian indicates a pedestrian or person ClassPedestrian ObjectClass = "pedestrian" // ClassCar indicates a car or vehicle ClassCar ObjectClass = "car" // ClassBird indicates a bird or small flying object ClassBird ObjectClass = "bird" // ClassOther indicates an unclassified object ClassOther ObjectClass = "other" )
type Point ¶
type Point struct {
// 3D Cartesian coordinates (computed from spherical measurements)
X float64 `json:"x"` // X coordinate in meters (forward direction from sensor)
Y float64 `json:"y"` // Y coordinate in meters (right direction from sensor)
Z float64 `json:"z"` // Z coordinate in meters (upward direction from sensor)
// Measurement metadata
Intensity uint8 `json:"intensity"` // Laser return intensity/reflectivity (0-255)
Distance float64 `json:"distance"` // Radial distance from sensor in meters
Azimuth float64 `json:"azimuth"` // Horizontal angle in degrees (0-360, corrected)
Elevation float64 `json:"elevation"` // Vertical angle in degrees (corrected for channel)
Channel int `json:"channel"` // Laser channel number (1-40)
Timestamp time.Time `json:"timestamp"` // Point acquisition time (with firetime correction)
BlockID int `json:"block_id"` // Data block index within packet (0-9)
// Packet tracking for completeness validation
UDPSequence uint32 `json:"udp_sequence"` // UDP sequence number for gap detection
RawBlockAzimuth uint16 `json:"raw_block_azimuth"` // Original block azimuth from packet (0.01 deg units)
}
Point represents a single 3D LiDAR measurement point in Cartesian coordinates Each point contains both the processed 3D coordinates and raw measurement data
type PointASC ¶
PointASC is a cartesian point with optional extra columns for export (X, Y, Z, Intensity, ...extra)
type PointPolar ¶
type PointPolar struct {
Channel int
Azimuth float64
Elevation float64
Distance float64
Intensity uint8
Timestamp int64 // unix nanos if needed; keep small to avoid heavy time usage
BlockID int
UDPSequence uint32
RawBlockAzimuth uint16 // Original block azimuth from packet (0.01 deg units)
}
PointPolar is a compact representation of a LiDAR return in polar terms. It can be used where sensor-frame operations are preferred (background model).
func DecodeForegroundBlob ¶
func DecodeForegroundBlob(blob []byte) []PointPolar
DecodeForegroundBlob decodes a compact binary blob back to polar points.
func ExtractForegroundPoints ¶
func ExtractForegroundPoints(points []PointPolar, mask []bool) []PointPolar
ExtractForegroundPoints returns only the foreground points from the input slice based on the provided mask. Points where mask[i] == true are included.
type PolarPointCompact ¶
type PolarPointCompact struct {
DistanceCm uint16 // Distance in centimeters (0-655.35m range)
AzimuthCentideg uint16 // Azimuth in centidegrees (0-36000 = 0-360°)
ElevationCentideg int16 // Elevation in centidegrees (-18000 to +18000 = -180° to +180°)
Intensity uint8 // Laser return intensity
Ring uint8 // Ring/channel number
}
PolarPointCompact is a compact binary representation of a polar point. Total: 8 bytes per point (vs ~40+ bytes for PointPolar struct)
type Pose ¶
type Pose struct {
PoseID int64 // matches pose_id INTEGER PRIMARY KEY
SensorID string // matches sensor_id TEXT NOT NULL
FromFrame FrameID // matches from_frame TEXT NOT NULL
ToFrame FrameID // matches to_frame TEXT NOT NULL
T [16]float64 // matches T_rowmajor_4x4 BLOB (16 floats)
ValidFromNanos int64 // matches valid_from_ns INTEGER NOT NULL
ValidToNanos *int64 // matches valid_to_ns INTEGER (NULL = current)
Method string // matches method TEXT
RootMeanSquareErrorMeters float32 // matches root_mean_square_error_meters REAL
}
Pose is a rigid transform (sensor -> world) with versioning. T is 4x4 row-major (m00..m03, m10..m13, m20..m23, m30..m33).
type PoseCache ¶
type PoseCache struct {
BySensorID map[string]*Pose
WorldFrame FrameID // canonical site frame (e.g., "site/main-st-001")
}
PoseCache holds the current pose used for realtime transforms.
type ProjectedPoint ¶
ProjectedPoint is a lightweight 3D sensor-frame projection used for debug charts.
type Region ¶
type Region struct {
ID int // unique region identifier
CellMask []bool // len = Rings * AzimuthBins; true if cell belongs to this region
Params RegionParams // parameters for this region
CellList []int // list of cell indices in this region (for efficient iteration)
// Statistics for region characterization
MeanVariance float64 // mean variance of cells in this region during settling
CellCount int // number of cells in this region
}
Region represents a contiguous spatial region with distinct parameters
type RegionDebugInfo ¶
type RegionDebugInfo struct {
SensorID string `json:"sensor_id"`
Timestamp time.Time `json:"timestamp"`
IdentificationComplete bool `json:"identification_complete"`
IdentificationTime time.Time `json:"identification_time,omitempty"`
FramesSampled int `json:"frames_sampled"`
RegionCount int `json:"region_count"`
Regions []RegionInfo `json:"regions"`
// Grid mapping: for each cell, which region it belongs to
GridMapping []int `json:"grid_mapping"` // maps cell index to region ID
}
RegionDebugInfo contains full region visualization data
type RegionInfo ¶
type RegionInfo struct {
ID int `json:"id"`
CellCount int `json:"cell_count"`
MeanVariance float64 `json:"mean_variance"`
Params RegionParams `json:"params"`
Cells []struct {
Ring int `json:"ring"`
AzimuthDeg float32 `json:"azimuth_deg"`
} `json:"cells,omitempty"` // Optional: can be large, include only on request
}
RegionInfo represents a region for API export
type RegionManager ¶
type RegionManager struct {
Regions []*Region // list of identified regions
CellToRegionID []int // maps cell index to region ID (-1 if unassigned)
SettlingMetrics struct {
VariancePerCell []float64 // variance observed per cell during settling
FramesSampled int // frames sampled for variance calculation
}
IdentificationComplete bool // true once regions are identified
IdentificationTime time.Time // when regions were identified
}
RegionManager handles dynamic region identification and management
func NewRegionManager ¶
func NewRegionManager(rings, azBins int) *RegionManager
NewRegionManager creates a RegionManager for the grid
func (*RegionManager) GetRegionForCell ¶
func (rm *RegionManager) GetRegionForCell(cellIdx int) int
GetRegionForCell returns the region ID for a given cell index
func (*RegionManager) GetRegionParams ¶
func (rm *RegionManager) GetRegionParams(regionID int) *RegionParams
GetRegionParams returns the parameters for a given region ID
func (*RegionManager) IdentifyRegions ¶
func (rm *RegionManager) IdentifyRegions(grid *BackgroundGrid, maxRegions int) error
IdentifyRegions performs clustering based on variance characteristics and creates contiguous regions with distinct parameters
func (*RegionManager) UpdateVarianceMetrics ¶
func (rm *RegionManager) UpdateVarianceMetrics(cells []BackgroundCell)
UpdateVarianceMetrics accumulates variance data during settling Computes running mean of RangeSpreadMeters values per cell
type RegionParams ¶
type RegionParams struct {
NoiseRelativeFraction float32 `json:"noise_relative_fraction"` // noise threshold for this region
NeighborConfirmationCount int `json:"neighbor_confirmation_count"` // neighbor confirmation for this region
SettleUpdateFraction float32 `json:"settle_update_fraction"` // alpha during settling for this region
}
RegionParams defines parameters that can vary per region
type RetentionConfig ¶
type RetentionConfig struct {
MaxConcurrentTracks int // 100 - matches design target
MaxTrackObservationsPerTrack int // 1000 observations per track - ring buffer size
MaxRecentClusters int // 10,000 recent clusters - memory management
MaxTrackAge time.Duration // 30 minutes for inactive tracks
BgSnapshotInterval time.Duration // 2 hours - matches schema automatic persistence
BgSnapshotRetention time.Duration // 48 hours - cleanup old snapshots
BgSettlingPeriod time.Duration // 5 minutes before first persist
// Enhanced cleanup policies for schema maintenance
MaxTrackFeatureAge time.Duration // 7 days - cleanup old feature vectors
MaxSystemEventAge time.Duration // 30 days - cleanup old performance metrics
ClusterPruneInterval time.Duration // 1 hour - memory cleanup frequency
}
Retention policies optimized for 100 concurrent tracks and schema constraints
type RingBuffer ¶
type RingBuffer[T any] struct { Items []T Head int Tail int Size int Capacity int // contains filtered or unexported fields }
Ring buffer implementation for efficient memory management at 100-track scale
func (*RingBuffer[T]) Len ¶
func (rb *RingBuffer[T]) Len() int
func (*RingBuffer[T]) Pop ¶
func (rb *RingBuffer[T]) Pop() (T, bool)
func (*RingBuffer[T]) Push ¶
func (rb *RingBuffer[T]) Push(item T) bool
Ring buffer methods for safe concurrent access
type RunComparison ¶
type RunComparison struct {
Run1ID string `json:"run1_id"`
Run2ID string `json:"run2_id"`
ParamDiff map[string]any `json:"param_diff,omitempty"`
TracksOnlyRun1 []string `json:"tracks_only_run1,omitempty"`
TracksOnlyRun2 []string `json:"tracks_only_run2,omitempty"`
SplitCandidates []TrackSplit `json:"split_candidates,omitempty"`
MergeCandidates []TrackMerge `json:"merge_candidates,omitempty"`
MatchedTracks []TrackMatch `json:"matched_tracks,omitempty"`
}
RunComparison shows differences between two analysis runs.
type RunParams ¶
type RunParams struct {
Version string `json:"version"`
Timestamp time.Time `json:"timestamp"`
Background BackgroundParamsExport `json:"background"`
Clustering ClusteringParamsExport `json:"clustering"`
Tracking TrackingParamsExport `json:"tracking"`
Classification ClassificationParamsExport `json:"classification,omitempty"`
}
RunParams captures all configurable parameters for reproducibility. This is the structure serialized into AnalysisRun.ParamsJSON.
func DefaultRunParams ¶
func DefaultRunParams() RunParams
DefaultRunParams returns default run parameters.
func ParseRunParams ¶
func ParseRunParams(data json.RawMessage) (*RunParams, error)
ParseRunParams deserializes RunParams from JSON.
type RunStatistics ¶
type RunStatistics struct {
// Track Quality Distribution
AvgTrackLength float32 `json:"avg_track_length_meters"`
MedianTrackLength float32 `json:"median_track_length_meters"`
AvgTrackDuration float32 `json:"avg_track_duration_secs"`
AvgOcclusionCount float32 `json:"avg_occlusion_count"`
// Classification Distribution
ClassCounts map[string]int `json:"class_counts"`
ClassConfidenceAvg map[string]float32 `json:"class_confidence_avg"`
UnknownRatio float32 `json:"unknown_ratio"`
// Noise & Coverage
AvgNoiseRatio float32 `json:"avg_noise_ratio"`
AvgSpatialCoverage float32 `json:"avg_spatial_coverage"`
// Track Lifecycle
TentativeRatio float32 `json:"tentative_ratio"`
ConfirmedRatio float32 `json:"confirmed_ratio"`
AvgObservationsPerTrack int `json:"avg_observations_per_track"`
}
RunStatistics holds aggregate statistics for an analysis run.
func ComputeRunStatistics ¶
func ComputeRunStatistics(tracks []*TrackedObject) *RunStatistics
ComputeRunStatistics calculates aggregate statistics from a set of tracks.
func ParseRunStatistics ¶
func ParseRunStatistics(jsonStr string) (*RunStatistics, error)
ParseRunStatistics deserializes RunStatistics from JSON.
func (*RunStatistics) ToJSON ¶
func (rs *RunStatistics) ToJSON() (string, error)
ToJSON serializes RunStatistics to JSON for database storage.
type RunTrack ¶
type RunTrack struct {
RunID string `json:"run_id"`
TrackID string `json:"track_id"`
// Track fields (from TrackedObject)
SensorID string `json:"sensor_id"`
TrackState string `json:"track_state"`
StartUnixNanos int64 `json:"start_unix_nanos"`
EndUnixNanos int64 `json:"end_unix_nanos,omitempty"`
ObservationCount int `json:"observation_count"`
AvgSpeedMps float32 `json:"avg_speed_mps"`
PeakSpeedMps float32 `json:"peak_speed_mps"`
P50SpeedMps float32 `json:"p50_speed_mps,omitempty"`
P85SpeedMps float32 `json:"p85_speed_mps,omitempty"`
P95SpeedMps float32 `json:"p95_speed_mps,omitempty"`
BoundingBoxLengthAvg float32 `json:"bounding_box_length_avg"`
BoundingBoxWidthAvg float32 `json:"bounding_box_width_avg"`
BoundingBoxHeightAvg float32 `json:"bounding_box_height_avg"`
HeightP95Max float32 `json:"height_p95_max"`
IntensityMeanAvg float32 `json:"intensity_mean_avg"`
ObjectClass string `json:"object_class,omitempty"`
ObjectConfidence float32 `json:"object_confidence,omitempty"`
ClassificationModel string `json:"classification_model,omitempty"`
// User labels (for ML training)
UserLabel string `json:"user_label,omitempty"`
LabelConfidence float32 `json:"label_confidence,omitempty"`
LabelerID string `json:"labeler_id,omitempty"`
LabeledAt int64 `json:"labeled_at,omitempty"`
// Track quality flags
IsSplitCandidate bool `json:"is_split_candidate,omitempty"`
IsMergeCandidate bool `json:"is_merge_candidate,omitempty"`
LinkedTrackIDs []string `json:"linked_track_ids,omitempty"`
}
RunTrack represents a track within a specific analysis run. This extends TrackedObject with run-specific fields like user labels.
func RunTrackFromTrackedObject ¶
func RunTrackFromTrackedObject(runID string, t *TrackedObject) *RunTrack
RunTrackFromTrackedObject creates a RunTrack from a TrackedObject.
type SensorConfig ¶
type SensorConfig struct {
ModelName string // e.g., "Pandar40P"
Channels int // Number of laser channels (40 for Pandar40P)
MotorSpeedRPM float64 // Motor speed for packet metadata
UDPPort int // Target UDP port (default 2368)
}
SensorConfig holds sensor-specific configuration for packet generation.
func DefaultPandar40PConfig ¶
func DefaultPandar40PConfig() *SensorConfig
DefaultPandar40PConfig returns default configuration for Pandar40P sensor.
type SidecarState ¶
type SidecarState struct {
Poses *PoseCache // thread-safe pose management
BackgroundManagers map[string]*BackgroundManager // enhanced with persistence
Tracks map[string]*Track // up to 100 concurrent
// Ring buffers sized for 100 tracks with thread safety
RecentClusters *RingBuffer[*WorldCluster] // 10,000 capacity
RecentTrackObs map[string]*RingBuffer[*TrackObs] // 1000 per track
RecentFrameStats *RingBuffer[*FrameStats] // 1000 capacity
// Performance monitoring for system_events integration
TrackCount int64
DroppedPackets int64
ActiveTracks int64 // current number of active tracks
TotalClusters int64 // lifetime cluster count
TotalFrames int64 // lifetime frame count
// Configuration
Config *RetentionConfig
// Schema integration hooks
SystemEventCallback func(event *SystemEvent) error // callback to persist system events
ClusterCallback func(cluster *WorldCluster) error // callback to persist clusters
TrackObsCallback func(obs *TrackObs) error // callback to persist track observations
// contains filtered or unexported fields
}
SidecarState is the main state container optimized for 100 concurrent tracks
func (*SidecarState) AddTrack ¶
func (s *SidecarState) AddTrack(track *Track)
func (*SidecarState) GetActiveTrackCount ¶
func (s *SidecarState) GetActiveTrackCount() int64
Thread-safe methods for SidecarState
func (*SidecarState) RemoveTrack ¶
func (s *SidecarState) RemoveTrack(trackID string)
type SpatialIndex ¶
SpatialIndex provides efficient nearest neighbor queries using a regular grid. Cell size should approximately match the DBSCAN eps parameter.
func NewSpatialIndex ¶
func NewSpatialIndex(cellSize float64) *SpatialIndex
NewSpatialIndex creates a spatial index with the specified cell size.
func (*SpatialIndex) Build ¶
func (si *SpatialIndex) Build(points []WorldPoint)
Build populates the spatial index from a set of world points. Uses 2D (x, y) coordinates for cell assignment.
func (*SpatialIndex) RegionQuery ¶
func (si *SpatialIndex) RegionQuery(points []WorldPoint, idx int, eps float64) []int
RegionQuery returns indices of all points within eps distance of points[idx]. Uses 2D (x, y) Euclidean distance for neighborhood queries.
type SystemEvent ¶
type SystemEvent struct {
EventID *int64 // auto-generated by database
SensorID *string // NULL for system-wide events
TSUnixNanos int64 // event timestamp
EventType string // 'performance', 'track_initiate', etc.
EventData map[string]interface{} // JSON data specific to event type
}
SystemEvent represents entries for the schema system_events table
type Track ¶
type Track struct {
// Core identification matching schema exactly
TrackID string // matches track_id TEXT PRIMARY KEY
SensorID string // matches sensor_id TEXT NOT NULL
WorldFrame FrameID // matches world_frame TEXT NOT NULL
PoseID int64 // matches pose_id INTEGER NOT NULL
// Lifecycle timestamps matching schema
FirstUnixNanos int64 // matches start_unix_nanos INTEGER NOT NULL
LastUnixNanos int64 // matches end_unix_nanos INTEGER (NULL if active)
// Current state for real-time tracking
State TrackState2D
// Running averages matching schema summary fields
BoundingBoxLengthAvg, BoundingBoxWidthAvg, BoundingBoxHeightAvg float32 // matches bounding_box_length_avg, bounding_box_width_avg, bounding_box_height_avg REAL
// Rollups for features/training matching schema fields
ObservationCount int // matches observation_count INTEGER
AvgSpeedMps float32 // matches avg_speed_mps REAL
PeakSpeedMps float32 // matches peak_speed_mps REAL
HeightP95Max float32 // matches height_p95_max REAL
IntensityMeanAvg float32 // matches intensity_mean_avg REAL
// Classification matching schema
ClassLabel string // matches class_label TEXT
ClassConfidence float32 // matches class_conf REAL
// Source tracking matching schema (LiDAR-only implementation)
SourceMask uint8 // matches source_mask INTEGER (bit0=lidar only for now)
// Life-cycle management (in-memory only)
Misses int // consecutive misses for deletion
}
Track enhanced to match schema lidar_tracks table structure
type TrackClassifier ¶
type TrackClassifier struct {
ModelVersion string
}
TrackClassifier performs rule-based classification of tracked objects. This can be replaced with an ML model in future iterations.
func NewTrackClassifier ¶
func NewTrackClassifier() *TrackClassifier
NewTrackClassifier creates a new track classifier.
func (*TrackClassifier) Classify ¶
func (tc *TrackClassifier) Classify(track *TrackedObject) ClassificationResult
Classify determines the object class for a tracked object. Returns the classification result with class, confidence, and features used.
func (*TrackClassifier) ClassifyAndUpdate ¶
func (tc *TrackClassifier) ClassifyAndUpdate(track *TrackedObject)
ClassifyAndUpdate classifies a track and updates its classification fields. This should be called periodically or when track state changes.
type TrackMatch ¶
type TrackMatch struct {
Track1ID string `json:"track1_id"`
Track2ID string `json:"track2_id"`
OverlapPct float32 `json:"overlap_pct"`
}
TrackMatch represents a matched track between two runs.
type TrackMerge ¶
type TrackMerge struct {
MergedTrack string `json:"merged_track"`
SourceTracks []string `json:"source_tracks"`
MergeX float32 `json:"merge_x"`
MergeY float32 `json:"merge_y"`
Confidence float32 `json:"confidence"`
}
TrackMerge represents a suspected track merge between runs.
type TrackObs ¶
type TrackObs struct {
TrackID string // matches track_id TEXT NOT NULL
UnixNanos int64 // matches ts_unix_nanos INTEGER NOT NULL
WorldFrame FrameID // matches world_frame TEXT NOT NULL
PoseID int64 // matches pose_id INTEGER NOT NULL
// Position matching schema
X, Y, Z float32 // matches x, y, z REAL
// Velocity matching schema
VelocityX, VelocityY, VelocityZ float32 // matches velocity_x, velocity_y, velocity_z REAL
// Derived kinematics matching schema
SpeedMps float32 // matches speed_mps REAL
HeadingRad float32 // matches heading_rad REAL
// Shape matching schema
BoundingBoxLength, BoundingBoxWidth, BoundingBoxHeight float32 // matches bounding_box_length, bounding_box_width, bounding_box_height REAL
// Quality metrics matching schema
HeightP95 float32 // matches height_p95 REAL
IntensityMean float32 // matches intensity_mean REAL
}
TrackObs exactly matches schema lidar_track_obs table structure
type TrackObservation ¶
type TrackObservation struct {
TrackID string
TSUnixNanos int64
WorldFrame string
// Position (world frame)
X, Y, Z float32
// Velocity (world frame)
VelocityX, VelocityY float32
SpeedMps float32
HeadingRad float32
// Shape
BoundingBoxLength float32
BoundingBoxWidth float32
BoundingBoxHeight float32
HeightP95 float32
IntensityMean float32
}
TrackObservation represents a single observation of a track at a point in time.
func GetTrackObservations ¶
GetTrackObservations retrieves observations for a track.
func GetTrackObservationsInRange ¶
func GetTrackObservationsInRange(db *sql.DB, sensorID string, startNanos, endNanos int64, limit int, trackID string) ([]*TrackObservation, error)
GetTrackObservationsInRange returns observations for a sensor within a time window (inclusive). Joins against tracks to scope by sensor.
type TrackPoint ¶
TrackPoint represents a single point in a track's history.
type TrackPointCloudExporter ¶
type TrackPointCloudExporter struct {
// contains filtered or unexported fields
}
TrackPointCloudExporter handles exporting point clouds for individual tracks. Maintains polar frame representation with minimal transformations.
type TrackPointCloudFrame ¶
type TrackPointCloudFrame struct {
TrackID string // Track identifier
FrameIndex int // Frame sequence number within track
Timestamp time.Time // Frame timestamp
PolarPoints []PointPolar // Points in polar coordinates
}
TrackPointCloudFrame represents a single frame of point cloud data for a track. Points are stored in polar coordinates (sensor frame) for compatibility with parsers.
func ExportTrackPointCloud ¶
func ExportTrackPointCloud(track *TrackedObject, observationHistory []*TrackObservation) ([]*TrackPointCloudFrame, error)
ExportTrackPointCloud extracts point clouds for a specific track from observation history. Returns frames that can be encoded into PCAP format for LidarView inspection.
type TrackPointCloudMetadata ¶
type TrackPointCloudMetadata struct {
TrackID string `json:"track_id"`
SensorID string `json:"sensor_id"`
StartTime time.Time `json:"start_time"`
EndTime time.Time `json:"end_time"`
TotalFrames int `json:"total_frames"`
TotalPoints int `json:"total_points"`
ObjectClass string `json:"object_class,omitempty"`
ObjectConfidence float32 `json:"object_confidence,omitempty"`
// Phase 1 quality metrics
TrackLength float32 `json:"track_length_meters"`
Duration float32 `json:"duration_secs"`
OcclusionCount int `json:"occlusion_count"`
QualityScore float32 `json:"quality_score,omitempty"`
}
TrackPointCloudMetadata contains metadata for exported track point clouds.
func ExtractMetadata ¶
func ExtractMetadata(track *TrackedObject, frames []*TrackPointCloudFrame) *TrackPointCloudMetadata
ExtractMetadata generates metadata for an exported track point cloud.
type TrackQualityMetrics ¶
type TrackQualityMetrics struct {
TrackID string `json:"track_id"`
TrackLengthMeters float32 `json:"track_length_meters"`
TrackDurationSecs float32 `json:"track_duration_secs"`
OcclusionCount int `json:"occlusion_count"`
MaxOcclusionFrames int `json:"max_occlusion_frames"`
SpatialCoverage float32 `json:"spatial_coverage"`
NoisePointRatio float32 `json:"noise_point_ratio"`
QualityScore float32 `json:"quality_score"` // Composite quality metric (0-1)
}
TrackQualityMetrics provides per-track quality assessment.
func ComputeTrackQualityMetrics ¶
func ComputeTrackQualityMetrics(track *TrackedObject) *TrackQualityMetrics
ComputeTrackQualityMetrics extracts quality metrics from a TrackedObject.
type TrackSplit ¶
type TrackSplit struct {
OriginalTrack string `json:"original_track"`
SplitTracks []string `json:"split_tracks"`
SplitX float32 `json:"split_x"`
SplitY float32 `json:"split_y"`
Confidence float32 `json:"confidence"`
}
TrackSplit represents a suspected track split between runs.
type TrackState ¶
type TrackState string
TrackState represents the lifecycle state of a track.
const ( TrackTentative TrackState = "tentative" // New track, needs confirmation TrackConfirmed TrackState = "confirmed" // Stable track with sufficient history TrackDeleted TrackState = "deleted" // Track marked for removal )
type TrackState2D ¶
type TrackState2D struct {
X, Y float32 // State vector in world frame: [x y velocity_x velocity_y]
VelocityX, VelocityY float32 // Velocity components in world frame
CovarianceMatrix [16]float32 // Row-major covariance (4x4). float32 saves RAM for 100-track performance.
}
TrackState2D represents the core kinematic state for Kalman filtering
type TrackStore ¶
type TrackStore interface {
InsertCluster(cluster *WorldCluster) (int64, error)
InsertTrack(track *TrackedObject, worldFrame string) error
UpdateTrack(track *TrackedObject, worldFrame string) error
InsertTrackObservation(obs *TrackObservation) error
ClearTracks(sensorID string) error
GetTrack(trackID string) (*TrackedObject, error)
GetActiveTracks(sensorID string, state string) ([]*TrackedObject, error)
GetTracksInRange(sensorID string, state string, startNanos, endNanos int64, limit int) ([]*TrackedObject, error)
GetTrackObservations(trackID string, limit int) ([]*TrackObservation, error)
GetTrackObservationsInRange(sensorID string, startNanos, endNanos int64, limit int, trackID string) ([]*TrackObservation, error)
GetRecentClusters(sensorID string, startNanos, endNanos int64, limit int) ([]*WorldCluster, error)
}
TrackStore defines the interface for track persistence operations.
type TrackSummary ¶
type TrackSummary struct {
TrackID string // matches schema track_id TEXT PRIMARY KEY
SensorID string // matches schema sensor_id TEXT NOT NULL
WorldFrame FrameID // matches schema world_frame TEXT NOT NULL
UnixNanos int64 // current observation timestamp
// Current kinematics (world frame; road-plane oriented)
X, Y float32 // current position
VelocityX, VelocityY float32 // current velocity
SpeedMps float32 // current speed magnitude
HeadingRad float32 // current heading
// Current shape/quality
BoundingBoxLength float32
BoundingBoxWidth float32
BoundingBoxHeight float32
PointsCount int
HeightP95 float32
IntensityMean float32
// Classification from track summary
ClassLabel string // matches schema class_label TEXT
ClassConfidence float32 // matches schema class_conf REAL
// Optional uncertainty (for advanced fusion)
Covariance4x4 []float32 // flattened 4x4 covariance of [x y velocity_x velocity_y]
}
TrackSummary for HTTP API responses - streamlined view of track state
type TrackTrainingFilter ¶
type TrackTrainingFilter struct {
MinQualityScore float32 // Minimum composite quality score (0-1)
MinDuration float32 // Minimum track duration (seconds)
MinLength float32 // Minimum track length (meters)
MaxOcclusionRatio float32 // Maximum occlusion ratio (occlusions / observations)
MinObservations int // Minimum observation count
RequireClass bool // Only include tracks with assigned class
AllowedStates []TrackState // Allowed track states (e.g., only confirmed)
}
TrackTrainingFilter defines criteria for selecting high-quality tracks for ML training.
func DefaultTrackTrainingFilter ¶
func DefaultTrackTrainingFilter() *TrackTrainingFilter
DefaultTrackTrainingFilter returns sensible defaults for high-quality training tracks.
type TrackedObject ¶
type TrackedObject struct {
// Identity
TrackID string
SensorID string
State TrackState
// Lifecycle counters
Hits int // Consecutive successful associations
Misses int // Consecutive missed associations
// Timestamps
FirstUnixNanos int64
LastUnixNanos int64
// Kalman state (world frame): [x, y, vx, vy]
X float32 // Position X
Y float32 // Position Y
VX float32 // Velocity X
VY float32 // Velocity Y
// Kalman covariance (4x4, row-major)
P [16]float32
// Aggregated features
ObservationCount int
BoundingBoxLengthAvg float32
BoundingBoxWidthAvg float32
BoundingBoxHeightAvg float32
HeightP95Max float32
IntensityMeanAvg float32
AvgSpeedMps float32
PeakSpeedMps float32
// History of positions
History []TrackPoint
// Classification (Phase 3.4)
ObjectClass string // Classification result: "pedestrian", "car", "bird", "other"
ObjectConfidence float32 // Classification confidence [0, 1]
ClassificationModel string // Model version used for classification
// Phase 1: Track Quality Metrics
TrackLengthMeters float32 // Total distance traveled (meters)
TrackDurationSecs float32 // Total lifetime (seconds)
OcclusionCount int // Number of missed frames (gaps)
MaxOcclusionFrames int // Longest gap in observations
SpatialCoverage float32 // % of bounding box covered by observations
NoisePointRatio float32 // Ratio of noise points to cluster points
// contains filtered or unexported fields
}
TrackedObject represents a single tracked object in the tracker.
func FilterTracksForTraining ¶
func FilterTracksForTraining(tracks []*TrackedObject, filter *TrackTrainingFilter) []*TrackedObject
FilterTracksForTraining selects tracks that meet training data quality criteria.
func GetActiveTracks ¶
GetActiveTracks retrieves active tracks from the database. If state is empty, returns all non-deleted tracks.
func GetTracksInRange ¶
func GetTracksInRange(db *sql.DB, sensorID string, state string, startNanos, endNanos int64, limit int) ([]*TrackedObject, error)
GetTracksInRange retrieves tracks whose lifespan overlaps the given time window (nanoseconds). A track is included if its start is on/before endNanos and its end (or start when end is NULL) is on/after startNanos. Deleted tracks are excluded by default unless state explicitly requests them.
func (*TrackedObject) ComputeQualityMetrics ¶
func (track *TrackedObject) ComputeQualityMetrics()
ComputeQualityMetrics calculates track quality metrics for Phase 1. This should be called when a track is finalized (state changes to deleted or when exporting).
func (*TrackedObject) Heading ¶
func (track *TrackedObject) Heading() float32
Heading returns the current heading in radians for a track.
func (*TrackedObject) Speed ¶
func (track *TrackedObject) Speed() float32
Speed returns the current speed magnitude for a track.
func (*TrackedObject) SpeedHistory ¶
func (track *TrackedObject) SpeedHistory() []float32
SpeedHistory returns a copy of the track's speed history for percentile computation.
type Tracker ¶
type Tracker struct {
Tracks map[string]*TrackedObject
NextTrackID int64
Config TrackerConfig
// Last update timestamp for dt computation
LastUpdateNanos int64
// contains filtered or unexported fields
}
Tracker manages multi-object tracking with explicit lifecycle states.
func NewTracker ¶
func NewTracker(config TrackerConfig) *Tracker
NewTracker creates a new tracker with the specified configuration.
func (*Tracker) GetActiveTracks ¶
func (t *Tracker) GetActiveTracks() []*TrackedObject
GetActiveTracks returns a slice of currently active (non-deleted) tracks.
func (*Tracker) GetAllTracks ¶
func (t *Tracker) GetAllTracks() []*TrackedObject
GetAllTracks returns a slice of all tracks including deleted ones. This is useful for analysis and reporting after processing is complete.
func (*Tracker) GetConfirmedTracks ¶
func (t *Tracker) GetConfirmedTracks() []*TrackedObject
GetConfirmedTracks returns only confirmed tracks.
func (*Tracker) GetTrack ¶
func (t *Tracker) GetTrack(trackID string) *TrackedObject
GetTrack returns a track by ID, or nil if not found.
func (*Tracker) GetTrackCount ¶
GetTrackCount returns counts of tracks by state.
type TrackerConfig ¶
type TrackerConfig struct {
MaxTracks int // Maximum number of concurrent tracks
MaxMisses int // Consecutive misses before deletion
HitsToConfirm int // Consecutive hits needed for confirmation
GatingDistanceSquared float32 // Squared gating distance for association (meters²)
ProcessNoisePos float32 // Process noise for position (σ²)
ProcessNoiseVel float32 // Process noise for velocity (σ²)
MeasurementNoise float32 // Measurement noise (σ²)
DeletedTrackGracePeriod time.Duration // How long to keep deleted tracks before cleanup
}
TrackerConfig holds configuration parameters for the tracker.
func DefaultTrackerConfig ¶
func DefaultTrackerConfig() TrackerConfig
DefaultTrackerConfig returns default tracker configuration.
type TrackingParamsExport ¶
type TrackingParamsExport struct {
MaxTracks int `json:"max_tracks"`
MaxMisses int `json:"max_misses"`
HitsToConfirm int `json:"hits_to_confirm"`
GatingDistanceSquared float32 `json:"gating_distance_squared"`
ProcessNoisePos float32 `json:"process_noise_pos"`
ProcessNoiseVel float32 `json:"process_noise_vel"`
MeasurementNoise float32 `json:"measurement_noise"`
DeletedTrackGracePeriod time.Duration `json:"deleted_track_grace_period_nanos"`
}
TrackingParamsExport is the JSON-serializable tracking params.
func FromTrackerConfig ¶
func FromTrackerConfig(c TrackerConfig) TrackingParamsExport
FromTrackerConfig creates export params from TrackerConfig.
type TrackingPipelineConfig ¶
type TrackingPipelineConfig struct {
BackgroundManager *BackgroundManager
FgForwarder ForegroundForwarder // Use interface to avoid import cycle
Tracker *Tracker
Classifier *TrackClassifier
DB *sql.DB // Use standard sql.DB to avoid import cycle with db package
SensorID string
DebugMode bool
AnalysisRunManager *AnalysisRunManager // Optional: for recording analysis runs
}
TrackingPipelineConfig holds dependencies for the tracking pipeline callback.
func (*TrackingPipelineConfig) NewFrameCallback ¶
func (cfg *TrackingPipelineConfig) NewFrameCallback() func(*LiDARFrame)
NewFrameCallback creates a FrameBuilder callback that processes frames through the full tracking pipeline: foreground extraction, clustering, tracking, and persistence.
type TrainingDataFilter ¶
type TrainingDataFilter struct {
SensorID string // Filter by sensor (empty = all)
SequenceID string // Filter by sequence (empty = all)
MinForeground int // Minimum foreground points per frame
AnnotationOnly bool // Only return annotated frames
}
TrainingDataFilter defines criteria for filtering training frames.
func DefaultTrainingDataFilter ¶
func DefaultTrainingDataFilter() TrainingDataFilter
DefaultTrainingDataFilter returns a filter suitable for high-quality training data.
type TrainingDatasetSummary ¶
type TrainingDatasetSummary struct {
TotalTracks int `json:"total_tracks"`
TotalFrames int `json:"total_frames"`
TotalPoints int `json:"total_points"`
ClassDistribution map[string]int `json:"class_distribution"`
AvgQualityScore float32 `json:"avg_quality_score"`
AvgDuration float32 `json:"avg_duration_secs"`
AvgLength float32 `json:"avg_length_meters"`
}
TrainingDatasetSummary provides statistics about a curated training dataset.
func SummarizeTrainingDataset ¶
func SummarizeTrainingDataset(tracks []*TrackedObject) *TrainingDatasetSummary
SummarizeTrainingDataset generates statistics for a curated training dataset.
type TrainingFrameMetadata ¶
type TrainingFrameMetadata struct {
FrameID int64
SensorID string
TSUnixNanos int64
SequenceID string
TotalPoints int
ForegroundPoints int
BackgroundPoints int
AnnotationStatus string // "unlabeled", "in_progress", "labeled"
}
TrainingFrameMetadata contains metadata for a training frame without the point data. Useful for querying/filtering frames before loading full point clouds.
type WorldCluster ¶
type WorldCluster struct {
ClusterID int64 // matches lidar_cluster_id INTEGER PRIMARY KEY
SensorID string // matches sensor_id TEXT NOT NULL
WorldFrame FrameID // matches world_frame TEXT NOT NULL
TSUnixNanos int64 // matches ts_unix_nanos INTEGER NOT NULL
CentroidX float32 // matches centroid_x REAL
CentroidY float32 // matches centroid_y REAL
CentroidZ float32 // matches centroid_z REAL
BoundingBoxLength float32 // matches bounding_box_length REAL
BoundingBoxWidth float32 // matches bounding_box_width REAL
BoundingBoxHeight float32 // matches bounding_box_height REAL
PointsCount int // matches points_count INTEGER
HeightP95 float32 // matches height_p95 REAL
IntensityMean float32 // matches intensity_mean REAL
// Debug hints matching schema optional fields
SensorRingHint *int // matches sensor_ring_hint INTEGER
SensorAzDegHint *float32 // matches sensor_azimuth_deg_hint REAL
// Optional in-memory only fields (not persisted to schema)
SamplePoints [][3]float32 // for debugging/thumbnails
}
WorldCluster matches schema lidar_clusters table structure exactly
func DBSCAN ¶
func DBSCAN(points []WorldPoint, params DBSCANParams) []WorldCluster
DBSCAN performs density-based clustering on world points. Uses 2D (x, y) Euclidean distance. Z is used only for cluster features. Returns a slice of WorldCluster objects representing detected clusters.
func GetRecentClusters ¶
func GetRecentClusters(db *sql.DB, sensorID string, startNanos, endNanos int64, limit int) ([]*WorldCluster, error)
GetRecentClusters retrieves recent clusters from the database.
type WorldPoint ¶
type WorldPoint struct {
X, Y, Z float64 // World frame position (meters)
Intensity uint8 // Laser return intensity
Timestamp time.Time // Acquisition time
SensorID string // Source sensor
}
WorldPoint represents a point in Cartesian world coordinates (site frame). This is the output of the polar → world transformation (Phase 3.0).
func TransformPointsToWorld ¶
func TransformPointsToWorld(points []Point, pose *Pose) []WorldPoint
TransformPointsToWorld is a convenience function that uses Point (Cartesian sensor frame) instead of PointPolar. This is useful when points already have X,Y,Z computed.
func TransformToWorld ¶
func TransformToWorld(polarPoints []PointPolar, pose *Pose, sensorID string) []WorldPoint
TransformToWorld converts foreground polar points to world frame coordinates. This is Phase 3.0 of the foreground tracking pipeline.
Steps: 1. Polar → Sensor Cartesian using spherical to Cartesian conversion 2. Sensor Cartesian → World Cartesian using pose transform
If pose is nil, an identity transform is used (sensor frame = world frame).