update
This commit is contained in:
parent
8362713dcc
commit
49c0c1ab39
|
|
@ -141,8 +141,7 @@
|
|||
[Parameter] public OrderMessage Order { get; set; } = default!;
|
||||
|
||||
[Parameter] public EventCallback OnAddEdge { get; set; }
|
||||
[Parameter] public EventCallback<UiEdge> OnRemoveEdge { get; set; }
|
||||
[Parameter] public EventCallback<UiEdge> OnApplyCurve { get; set; }
|
||||
[Parameter] public EventCallback<VDA5050.Order.Edge> OnRemoveEdge { get; set; }
|
||||
|
||||
[Parameter] public EventCallback OnOrderChanged { get; set; }
|
||||
|
||||
|
|
@ -158,15 +157,9 @@
|
|||
await OnOrderChanged.InvokeAsync();
|
||||
}
|
||||
|
||||
private async Task RemoveEdgeAsync(UiEdge edge)
|
||||
private async Task RemoveEdgeAsync(VDA5050.Order.Edge edge)
|
||||
{
|
||||
await OnRemoveEdge.InvokeAsync(edge);
|
||||
await OnOrderChanged.InvokeAsync();
|
||||
}
|
||||
|
||||
private async Task ApplyCurveAsync(UiEdge edge)
|
||||
{
|
||||
await OnApplyCurve.InvokeAsync(edge);
|
||||
await OnOrderChanged.InvokeAsync();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,17 +132,17 @@
|
|||
|
||||
try
|
||||
{
|
||||
using var doc = JsonDocument.Parse(JsonText);
|
||||
var root = doc.RootElement;
|
||||
|
||||
// ===== BASIC STRUCTURE CHECK =====
|
||||
if (!root.TryGetProperty("nodes", out _) ||
|
||||
!root.TryGetProperty("edges", out _))
|
||||
var order = JsonSerializer.Deserialize<OrderMsg>(JsonText, new JsonSerializerOptions
|
||||
{
|
||||
throw new Exception("Missing 'nodes' or 'edges' field.");
|
||||
WriteIndented = true,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
});
|
||||
if(order is null)
|
||||
{
|
||||
ShowWarning = true;
|
||||
ErrorMessage = "Can not convert file to Order message";
|
||||
return;
|
||||
}
|
||||
|
||||
var order = OrderMessage.FromSchemaObject(root);
|
||||
ValidateOrder(order);
|
||||
|
||||
MudDialog.Close(DialogResult.Ok(order));
|
||||
|
|
@ -160,15 +160,15 @@
|
|||
}
|
||||
|
||||
// ================= DOMAIN VALIDATION =================
|
||||
private void ValidateOrder(OrderMessage order)
|
||||
private void ValidateOrder(OrderMsg order)
|
||||
{
|
||||
if (order.Nodes.Count == 0)
|
||||
if (order.Nodes.Length == 0)
|
||||
throw new Exception("Order must contain at least one node.");
|
||||
|
||||
if (order.Nodes.Count != order.Edges.Count + 1)
|
||||
if (order.Nodes.Length != order.Edges.Length + 1)
|
||||
throw new Exception(
|
||||
$"Invalid path structure: Nodes count ({order.Nodes.Count}) " +
|
||||
$"must equal Edges count + 1 ({order.Edges.Count + 1})."
|
||||
$"Invalid path structure: Nodes count ({order.Nodes.Length}) " +
|
||||
$"must equal Edges count + 1 ({order.Edges.Length + 1})."
|
||||
);
|
||||
|
||||
var nodeIds = order.Nodes
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@
|
|||
<div class="d-flex gap-2">
|
||||
|
||||
<!-- IMPORT -->
|
||||
@* <MudButton Variant="Variant.Outlined"
|
||||
<MudButton Variant="Variant.Outlined"
|
||||
Color="Color.Secondary"
|
||||
Size="Size.Small"
|
||||
StartIcon="@Icons.Material.Filled.UploadFile"
|
||||
OnClick="OnImport">
|
||||
Import JSON
|
||||
</MudButton>
|
||||
*@
|
||||
|
||||
<!-- CANCEL -->
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Color="@CancelButtonColor"
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
<EdgesPanel Order="Order"
|
||||
OnAddEdge="AddEdge"
|
||||
OnRemoveEdge="RemoveEdge"
|
||||
OnApplyCurve="ApplyCurve"
|
||||
OnOrderChanged="OnOrderChanged" />
|
||||
</MudItem>
|
||||
|
||||
|
|
@ -99,9 +98,9 @@
|
|||
|
||||
var result = await dialog.Result;
|
||||
|
||||
if (!result.Canceled && result.Data is OrderMessage imported)
|
||||
if (result is not null && !result.Canceled && result.Data is OrderMsg imported)
|
||||
{
|
||||
Order = imported;
|
||||
Order.Import(imported);
|
||||
RebuildOrderJson();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
|
@ -149,7 +148,7 @@
|
|||
? Order.Nodes[1].NodeId
|
||||
: start; // 👈 1 node thì start = end
|
||||
|
||||
Order.Edges.Add(new UiEdge
|
||||
Order.Edges.Add(new VDA5050.Order.Edge
|
||||
{
|
||||
EdgeId = $"EDGE_{Order.Edges.Count + 1}",
|
||||
StartNodeId = start,
|
||||
|
|
@ -158,25 +157,10 @@
|
|||
}
|
||||
|
||||
|
||||
void RemoveEdge(UiEdge edge)
|
||||
void RemoveEdge(VDA5050.Order.Edge edge)
|
||||
{
|
||||
Order.Edges.Remove(edge);
|
||||
}
|
||||
|
||||
void ApplyCurve(UiEdge edge)
|
||||
{
|
||||
if (edge.Radius <= 0 || edge.Expanded) return;
|
||||
|
||||
var startNode = Order.Nodes.First(n => n.NodeId == edge.StartNodeId);
|
||||
var newNode = OrderMessage.CreateCurveNode(startNode, edge);
|
||||
|
||||
Order.Nodes.Add(newNode);
|
||||
edge.EndNodeId = newNode.NodeId;
|
||||
edge.MarkExpanded(); // ✅
|
||||
|
||||
ResequenceNodes();
|
||||
}
|
||||
|
||||
// ================= ACTION =================
|
||||
void AddAction(Node node)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
using RobotApp.VDA5050.Order;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace RobotApp.Client.Services;
|
||||
|
||||
|
|
@ -126,7 +127,7 @@ public static class QuarterGeometry
|
|||
// ======================================================
|
||||
public class OrderMessage
|
||||
{
|
||||
public int HeaderId { get; set; }
|
||||
public uint HeaderId { get; set; }
|
||||
public string Timestamp { get; set; } = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
|
||||
public string Version { get; set; } = "2.1.0";
|
||||
public string Manufacturer { get; set; } = "PhenikaaX";
|
||||
|
|
@ -135,139 +136,9 @@ public class OrderMessage
|
|||
public int OrderUpdateId { get; set; }
|
||||
public string? ZoneSetId { get; set; }
|
||||
|
||||
public List<Node> Nodes { get; set; } = new();
|
||||
public List<UiEdge> Edges { get; set; } = new();
|
||||
public static Node CreateCurveNode(Node startNode, UiEdge edge)
|
||||
{
|
||||
var A = new Point(
|
||||
startNode.NodePosition.X,
|
||||
startNode.NodePosition.Y
|
||||
);
|
||||
public List<Node> Nodes { get; set; } = [];
|
||||
public List<Edge> Edges { get; set; } = [];
|
||||
|
||||
var result = QuarterGeometry.BuildQuarterTrajectory(
|
||||
A,
|
||||
edge.Radius,
|
||||
edge.Quadrant
|
||||
);
|
||||
|
||||
return new Node
|
||||
{
|
||||
NodeId = $"NODE_C{Guid.NewGuid():N}".Substring(0, 12),
|
||||
Released = true,
|
||||
NodePosition = new NodePosition
|
||||
{
|
||||
X = result.EndPoint.X,
|
||||
Y = result.EndPoint.Y,
|
||||
Theta = startNode.NodePosition.Theta,
|
||||
MapId = startNode.NodePosition.MapId
|
||||
}
|
||||
};
|
||||
}
|
||||
public static OrderMessage FromSchemaObject(JsonElement root)
|
||||
{
|
||||
var order = new OrderMessage
|
||||
{
|
||||
HeaderId = root.GetProperty("headerId").GetInt32(),
|
||||
Timestamp = root.GetProperty("timestamp").GetString(),
|
||||
Version = root.GetProperty("version").GetString(),
|
||||
Manufacturer = root.GetProperty("manufacturer").GetString(),
|
||||
SerialNumber = root.GetProperty("serialNumber").GetString(),
|
||||
OrderId = root.GetProperty("orderId").GetString(),
|
||||
OrderUpdateId = root.GetProperty("orderUpdateId").GetInt32()
|
||||
};
|
||||
|
||||
// ================= NODES =================
|
||||
foreach (var n in root.GetProperty("nodes").EnumerateArray())
|
||||
{
|
||||
var node = new Node
|
||||
{
|
||||
NodeId = n.GetProperty("nodeId").GetString()!,
|
||||
SequenceId = n.GetProperty("sequenceId").GetInt32(),
|
||||
Released = n.GetProperty("released").GetBoolean(),
|
||||
|
||||
NodePosition = new NodePosition
|
||||
{
|
||||
X = n.GetProperty("nodePosition").GetProperty("x").GetDouble(),
|
||||
Y = n.GetProperty("nodePosition").GetProperty("y").GetDouble(),
|
||||
Theta = n.GetProperty("nodePosition").GetProperty("theta").GetDouble(),
|
||||
AllowedDeviationXY = n.GetProperty("nodePosition").GetProperty("allowedDeviationXY").GetDouble(),
|
||||
AllowedDeviationTheta = n.GetProperty("nodePosition").GetProperty("allowedDeviationTheta").GetDouble(),
|
||||
MapId = n.GetProperty("nodePosition").GetProperty("mapId").GetString()
|
||||
},
|
||||
|
||||
Actions = ParseActions(n)
|
||||
};
|
||||
|
||||
order.Nodes.Add(node);
|
||||
}
|
||||
|
||||
foreach (var e in root.GetProperty("edges").EnumerateArray())
|
||||
{
|
||||
var edge = new UiEdge
|
||||
{
|
||||
EdgeId = e.GetProperty("edgeId").GetString()!,
|
||||
SequenceId = e.GetProperty("sequenceId").GetInt32(),
|
||||
Released = e.GetProperty("released").GetBoolean(),
|
||||
StartNodeId = e.GetProperty("startNodeId").GetString()!,
|
||||
EndNodeId = e.GetProperty("endNodeId").GetString()!,
|
||||
};
|
||||
|
||||
// ===== IMPORT TRAJECTORY =====
|
||||
if (e.TryGetProperty("trajectory", out var traj))
|
||||
{
|
||||
edge.HasTrajectory = true;
|
||||
edge.Trajectory = new UiTrajectory
|
||||
{
|
||||
Degree = traj.GetProperty("degree").GetInt32(),
|
||||
KnotVector = traj.GetProperty("knotVector")
|
||||
.EnumerateArray()
|
||||
.Select(x => x.GetDouble())
|
||||
.ToArray(),
|
||||
|
||||
ControlPoints = traj.GetProperty("controlPoints")
|
||||
.EnumerateArray()
|
||||
.Select(p => new Point(
|
||||
p.GetProperty("x").GetDouble(),
|
||||
p.GetProperty("y").GetDouble()
|
||||
))
|
||||
.ToList()
|
||||
};
|
||||
|
||||
// 🔥 IMPORTED CURVE → LOCK APPLY
|
||||
edge.MarkExpanded();
|
||||
}
|
||||
|
||||
order.Edges.Add(edge);
|
||||
}
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
// ================= ACTION PARSER =================
|
||||
private static VDA5050.InstantAction.Action[] ParseActions(JsonElement parent)
|
||||
{
|
||||
if (!parent.TryGetProperty("actions", out var acts))
|
||||
return Array.Empty<VDA5050.InstantAction.Action>();
|
||||
|
||||
return acts.EnumerateArray().Select(a =>
|
||||
new VDA5050.InstantAction.Action
|
||||
{
|
||||
ActionId = a.GetProperty("actionId").GetString(),
|
||||
ActionType = a.GetProperty("actionType").GetString(),
|
||||
BlockingType = a.GetProperty("blockingType").GetString(),
|
||||
|
||||
ActionParameters = a.TryGetProperty("actionParameters", out var ps)
|
||||
? ps.EnumerateArray()
|
||||
.Select(p => new ActionParameter
|
||||
{
|
||||
Key = p.GetProperty("key").GetString(),
|
||||
Value = p.GetProperty("value").GetString()
|
||||
})
|
||||
.ToArray()
|
||||
: Array.Empty<ActionParameter>()
|
||||
}
|
||||
).ToArray();
|
||||
}
|
||||
public OrderMsg ToSchemaObject()
|
||||
{
|
||||
// ================= SORT NODES BY UI SEQUENCE =================
|
||||
|
|
@ -337,7 +208,7 @@ public class OrderMessage
|
|||
// =================================================
|
||||
// 1️⃣ IMPORTED TRAJECTORY
|
||||
// =================================================
|
||||
if (e.HasTrajectory && e.Trajectory != null)
|
||||
if (e.Trajectory != null)
|
||||
{
|
||||
return new Edge
|
||||
{
|
||||
|
|
@ -360,39 +231,6 @@ public class OrderMessage
|
|||
};
|
||||
}
|
||||
|
||||
// =================================================
|
||||
// 2️⃣ STRAIGHT EDGE
|
||||
// =================================================
|
||||
if (e.Radius <= 0)
|
||||
{
|
||||
return new Edge
|
||||
{
|
||||
EdgeId = baseEdge.edgeId,
|
||||
SequenceId = baseEdge.sequenceId,
|
||||
Released = baseEdge.released,
|
||||
StartNodeId = baseEdge.startNodeId,
|
||||
EndNodeId = baseEdge.endNodeId,
|
||||
|
||||
Actions = []
|
||||
};
|
||||
}
|
||||
|
||||
// =================================================
|
||||
// 3️⃣ GENERATED CURVE (EDITOR)
|
||||
// =================================================
|
||||
var startNode = orderedNodes.First(n => n.NodeId == e.StartNodeId);
|
||||
|
||||
var A = new Point(
|
||||
startNode.NodePosition.X,
|
||||
startNode.NodePosition.Y
|
||||
);
|
||||
|
||||
var result = QuarterGeometry.BuildQuarterTrajectory(
|
||||
A,
|
||||
e.Radius,
|
||||
e.Quadrant
|
||||
);
|
||||
|
||||
return new Edge
|
||||
{
|
||||
EdgeId = baseEdge.edgeId,
|
||||
|
|
@ -428,6 +266,20 @@ public class OrderMessage
|
|||
Edges = edgeObjects,
|
||||
};
|
||||
}
|
||||
|
||||
public void Import(OrderMsg order)
|
||||
{
|
||||
HeaderId = order.HeaderId;
|
||||
Timestamp = order.Timestamp;
|
||||
Version = order.Version;
|
||||
Manufacturer = order.Manufacturer;
|
||||
SerialNumber = order.SerialNumber;
|
||||
OrderId = order.OrderId;
|
||||
ZoneSetId = order.ZoneSetId;
|
||||
OrderUpdateId = order.OrderUpdateId;
|
||||
Nodes = [.. order.Nodes];
|
||||
Edges = [.. order.Edges];
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================
|
||||
|
|
|
|||
|
|
@ -479,6 +479,7 @@ public class RobotOrderController(INavigation NavigationManager,
|
|||
var edges = NewOrderEdges.ToList().GetRange(lastNodeIndex + 1, nodes.Count - 1);
|
||||
for (int i = 0; i < nodes.Count - 1; i++)
|
||||
{
|
||||
if (edges[i] is null) return (NodeStates, [.. pathEdges]);
|
||||
pathEdges.Add(new()
|
||||
{
|
||||
StartX = nodes[i].NodePosition.X,
|
||||
|
|
@ -489,7 +490,7 @@ public class RobotOrderController(INavigation NavigationManager,
|
|||
ControlPoint1Y = edges[i].Trajectory is not null && edges[i].Trajectory.ControlPoints.Length > 2 ? edges[i].Trajectory.ControlPoints[1].Y : 0,
|
||||
ControlPoint2X = edges[i].Trajectory is not null && edges[i].Trajectory.ControlPoints.Length > 3 ? edges[i].Trajectory.ControlPoints[2].X : 0,
|
||||
ControlPoint2Y = edges[i].Trajectory is not null && edges[i].Trajectory.ControlPoints.Length > 3 ? edges[i].Trajectory.ControlPoints[2].Y : 0,
|
||||
Degree = edges[i].Trajectory.Degree,
|
||||
Degree = edges[i].Trajectory is null ? 1 : edges[i].Trajectory.Degree,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user