@page "/motion/odometry"
@rendermode InteractiveWebAssemblyNoPrerender
@implements IAsyncDisposable
@using Microsoft.AspNetCore.SignalR.Client
@using RobotNet10.RobotApp.Client.Clients
@using RobotNet10.RobotApp.Client.Shared.Motion
@using MudBlazor
Odometry (XLOC)
@* Header *@
@if (!OdometryHubClient.IsConnected)
{
Đang kết nối tới hub odometry...
}
@if (lastOdom != null)
{
@* Meta: frame_id, child_frame_id, stamp *@
Header
@lastOdom.FrameId
@lastOdom.ChildFrameId
@lastOdom.Timestamp.ToString("HH:mm:ss.fff")
@* Pose: Position + Orientation *@
Position
(m)
Orientation
(yaw °)
Q: (@Format(lastOdom.OrientationX), @Format(lastOdom.OrientationY), @Format(lastOdom.OrientationZ), @Format(lastOdom.OrientationW))
@* Twist: Linear + Angular *@
Linear velocity
(m/s)
Angular velocity
(rad/s)
pose_position · pose_orientation · twist_linear · twist_angular → ToXlocOdometry()
}
else if (OdometryHubClient.IsConnected)
{
Chưa nhận dữ liệu. Đang chờ broadcast từ server.
}
@code {
[Inject]
private OdometryHubClient OdometryHubClient { get; set; } = null!;
private OdometryDto? lastOdom;
protected override async Task OnInitializedAsync()
{
OdometryHubClient.OdometryReceived += OnOdometryReceived;
OdometryHubClient.ConnectionStateChanged += OnConnectionStateChanged;
await OdometryHubClient.StartAsync();
if (OdometryHubClient.IsConnected)
{
lastOdom = await OdometryHubClient.GetCurrentOdometryAsync();
}
}
private void OnOdometryReceived(OdometryDto dto)
{
lastOdom = dto;
InvokeAsync(StateHasChanged);
}
private void OnConnectionStateChanged(HubConnectionState _)
{
InvokeAsync(StateHasChanged);
}
private double YawDegrees
{
get
{
if (lastOdom == null) return 0;
var qw = lastOdom.OrientationW;
var qz = lastOdom.OrientationZ;
var qx = lastOdom.OrientationX;
var qy = lastOdom.OrientationY;
var yaw = Math.Atan2(2.0 * (qw * qz + qx * qy), 1.0 - 2.0 * (qy * qy + qz * qz));
return yaw * 180.0 / Math.PI;
}
}
private static string Format(double value) => value.ToString("F4");
private static string FormatDegrees(double value) => value.ToString("F2") + " °";
public async ValueTask DisposeAsync()
{
OdometryHubClient.OdometryReceived -= OnOdometryReceived;
OdometryHubClient.ConnectionStateChanged -= OnConnectionStateChanged;
await OdometryHubClient.DisposeAsync();
}
}