Files
I150/srcs/RobotNet10/RobotApp/RobotNet10.RobotApp/Components/Pages/LidarView.razor
2026-07-03 16:37:12 +07:00

216 lines
6.1 KiB
Plaintext

@page "/lidar"
@using RobotNet10.RobotApp.Devices
@using RobotNet10.Shared
@using RobotNet10.RobotApp.Client.Shared.Devices
@rendermode InteractiveServer
@attribute [Authorize]
@inject IDeviceProvider DeviceProvider
<PageTitle>Tim781S LiDAR Visualization</PageTitle>
<style>
.lidar-container {
display: flex;
flex-direction: column;
height: 100vh;
background: #1a1a1a;
color: #ffffff;
}
.lidar-header {
padding: 20px;
background: #2a2a2a;
border-bottom: 2px solid #3a3a3a;
}
.lidar-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-top: 15px;
}
.stat-card {
background: #3a3a3a;
padding: 15px;
border-radius: 8px;
border-left: 4px solid #00ff88;
}
.stat-label {
font-size: 12px;
color: #888;
margin-bottom: 5px;
}
.stat-value {
font-size: 24px;
font-weight: bold;
color: #00ff88;
}
.canvas-container {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
#lidarCanvas {
border: 2px solid #3a3a3a;
background: #0a0a0a;
}
.status-indicator {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 8px;
}
.status-connected {
background: #00ff88;
box-shadow: 0 0 10px #00ff88;
}
.status-disconnected {
background: #ff4444;
}
</style>
<div class="lidar-container">
<div class="lidar-header">
<h1>
<span class="status-indicator @(isConnected ? "status-connected" : "status-disconnected")"></span>
Tim781S LiDAR Visualization
</h1>
<div class="lidar-stats">
<div class="stat-card">
<div class="stat-label">Scan Frequency</div>
<div class="stat-value">@scanFrequency Hz</div>
</div>
<div class="stat-card">
<div class="stat-label">Points Per Scan</div>
<div class="stat-value">@pointCount</div>
</div>
<div class="stat-card">
<div class="stat-label">Min Range</div>
<div class="stat-value">@minRange.ToString("F2") m</div>
</div>
<div class="stat-card">
<div class="stat-label">Max Range</div>
<div class="stat-value">@maxRange.ToString("F2") m</div>
</div>
<div class="stat-card">
<div class="stat-label">Valid Points</div>
<div class="stat-value">@validPoints</div>
</div>
</div>
</div>
<div class="canvas-container">
<canvas id="lidarCanvas" width="800" height="800"></canvas>
</div>
</div>
@code {
private IJSRuntime? JS { get; set; }
private bool isConnected = false;
private int scanFrequency = 0;
private int pointCount = 0;
private float minRange = 0.0f;
private float maxRange = 0.0f;
private int validPoints = 0;
private ILidar? lidar;
private System.Threading.Timer? updateTimer;
[Inject]
public required IJSRuntime JSRuntime { get; set; }
protected override async Task OnInitializedAsync()
{
JS = JSRuntime;
// Find Tim781S LiDAR device
var devices = DeviceProvider.GetDevicesByType(DeviceType.Lidar).OfType<ILidar>();
lidar = devices.FirstOrDefault(d => (d as DeviceBase)?.DeviceId.Contains("tim781s", StringComparison.OrdinalIgnoreCase) == true);
if (lidar != null)
{
lidar.ScanDataReceived += OnScanDataReceived;
var deviceBase = lidar as DeviceBase;
isConnected = deviceBase?.Status == DeviceStatus.Connected;
}
// Start update timer for stats
updateTimer = new System.Threading.Timer(async _ =>
{
await InvokeAsync(StateHasChanged);
}, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(10));
}
private async void OnScanDataReceived(object? sender, LidarScanDataEventArgs e)
{
if (JS == null) return;
var scan = e.MeasurementData;
// Update stats
pointCount = scan.Ranges.Length;
minRange = (float)scan.RangeMin;
maxRange = (float)scan.RangeMax;
validPoints = scan.Ranges.Count(r => r >= scan.RangeMin && r <= scan.RangeMax);
// Calculate scan frequency (simple moving average)
if (lidar != null && lidar.ScanFrequencyHz.HasValue)
{
scanFrequency = (int)lidar.ScanFrequencyHz.Value;
}
// Prepare data for JavaScript visualization
var points = new List<object>();
for (int i = 0; i < scan.Ranges.Length; i++)
{
float angle = (float)(scan.AngleMin + (i * scan.AngleIncrement));
float range = (float)scan.Ranges[i];
// Only add valid points
if (range >= scan.RangeMin && range <= scan.RangeMax)
{
points.Add(new { angle, range });
}
}
// Call JavaScript to draw
try
{
await JS.InvokeVoidAsync("drawLidarScan", points);
}
catch
{
// Silently ignore if JS not ready
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender && JS != null)
{
// Initialize canvas
await JS.InvokeVoidAsync("initLidarCanvas");
}
}
public void Dispose()
{
updateTimer?.Dispose();
if (lidar != null)
{
lidar.ScanDataReceived -= OnScanDataReceived;
}
}
}