@page "/motion/navigation-monitor"
@rendermode InteractiveWebAssemblyNoPrerender
@implements IAsyncDisposable
@using RobotNet10.RobotApp.Client.Clients
@using RobotNet10.RobotApp.Shared.NavigationMonitor
@using Microsoft.AspNetCore.SignalR.Client
@using MudBlazor
@using ApexCharts
@using Color = MudBlazor.Color
@using Size = MudBlazor.Size
Navigation Monitor
@* Connection status *@
@if (!hubClient.IsConnected)
{
Disconnected from Navigation Monitor hub. Reconnecting...
}
@* Controls *@
@if (telemetryEnabled)
{
@($"{updateFrequencyHz:F0} Hz")
}
else
{
Disabled
}
@* Safety Stop Latch Banner *@
@if (safetyStopLatched)
{
SAFETY STOP ACTIVE — @safetyStopReason
Release Safety Stop
}
@* DockTo Telemetry - special panel when docking *@
@if (telemetry.DockTo is not null)
{
Docking Telemetry
@telemetry.DockTo.Phase
@telemetry.DockTo.Direction
@{
var dock = telemetry.DockTo!;
var svgBounds = GetDockSvgBounds(dock, telemetry.X, telemetry.Y);
var vb = svgBounds;
}
@* SVG Visualization - left side *@
Docking Path
@* Docking Info - right side *@
| Phase |
@telemetry.DockTo.Phase
|
| Direction | @telemetry.DockTo.Direction |
| Fine Positioning Retries |
@telemetry.DockTo.RetryCount / @telemetry.DockTo.MaxRetries
|
| Waypoints | @telemetry.DockTo.TotalWaypoints |
| Goal X | @telemetry.DockTo.GoalX.ToString("F3") m |
| Goal Y | @telemetry.DockTo.GoalY.ToString("F3") m |
| Goal Theta | @((telemetry.DockTo.GoalTheta * 180 / Math.PI).ToString("F2"))° |
| Distance to Goal |
@telemetry.DistanceToGoal.ToString("F3") m
|
}
@* Telemetry Data Cards *@
@* Position *@
Position
| X | @telemetry.X.ToString("F3") m |
| Y | @telemetry.Y.ToString("F3") m |
| Theta | @((telemetry.Theta * 180 / Math.PI).ToString("F2"))° |
@* Velocity *@
Velocity
| Linear | @telemetry.LinearVelocity.ToString("F3") m/s |
| Angular | @telemetry.AngularVelocity.ToString("F3") rad/s |
| Confidence | @telemetry.ModelConfidence.ToString("F2") |
@* Navigation State *@
Navigation
| State |
@telemetry.NavigationState
|
| Driving | @(telemetry.Driving ? "Yes" : "No") |
| To Goal | @telemetry.DistanceToGoal.ToString("F3") m |
@* Tracking (CTE) *@
Tracking
| Cross-Track Error |
@telemetry.CrossTrackError.ToString("F3") m
|
| Heading Error |
@((telemetry.HeadingError * 180 / Math.PI).ToString("F2"))°
|
@* Acceleration *@
Acceleration
| Linear |
@telemetry.LinearAcceleration.ToString("F2") m/s²
|
| Angular |
@telemetry.AngularAcceleration.ToString("F2") m/s²
|
@* Telemetry Charts *@
Telemetry Charts
Cross-Track Error
Velocity
Heading Error
@* Navigation Path Visualization *@
@if (_cachedWaypoints is { Count: >= 2 })
{
Navigation Path
@_cachedWaypoints.Count waypoints
@telemetry.NavigationState
@{
var wp = _cachedWaypoints;
var pvb = GetPathSvgBounds(wp, _robotTrail);
var pStroke = (pvb.Width * 0.005).ToString("F4");
var pThin = (pvb.Width * 0.003).ToString("F4");
var pDash = (pvb.Width * 0.01).ToString("F4");
}
}
@* Safety Configuration *@
Safety Configuration
Apply
@* Safety Violations *@
Safety Violations
Clear
@if (violations.Count == 0)
{
No violations recorded.
}
else
{
@foreach (var v in violations)
{
@DateTimeOffset.FromUnixTimeMilliseconds(v.TimestampMs).ToLocalTime().ToString("HH:mm:ss.fff")
— @v.Message
}
}