diff --git a/RobotApp.Client/Pages/Order/OrderMess.razor b/RobotApp.Client/Pages/Order/OrderMess.razor
index 85e4f45..1d1a62f 100644
--- a/RobotApp.Client/Pages/Order/OrderMess.razor
+++ b/RobotApp.Client/Pages/Order/OrderMess.razor
@@ -86,6 +86,7 @@
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
});
}
+
private async Task OpenImportDialog()
{
var dialog = await DialogService.ShowAsync
(
@@ -177,22 +178,19 @@
void RemoveAction(Node node, VDA5050.InstantAction.Action action)
{
- node.Actions = node.Actions?.Where(a => a != action).ToArray()
- ?? Array.Empty();
+ node.Actions = node.Actions?.Where(a => a != action).ToArray() ?? [];
}
void AddActionParameter(VDA5050.InstantAction.Action act)
{
- var list = (act.ActionParameters ?? Array.Empty()).ToList();
+ var list = (act.ActionParameters ?? []).ToList();
list.Add(new UiActionParameter());
act.ActionParameters = list.ToArray();
}
void RemoveActionParameter(VDA5050.InstantAction.Action act, ActionParameter param)
{
- act.ActionParameters =
- act.ActionParameters?.Where(p => p != param).ToArray()
- ?? Array.Empty();
+ act.ActionParameters = act.ActionParameters?.Where(p => p != param).ToArray() ?? [];
}
// ================= SEND / COPY =================
@@ -302,7 +300,7 @@
_copyCts?.Cancel();
_copyCts = new();
- await JS.InvokeVoidAsync("navigator.clipboard.writeText", OrderJson);
+ await JS.InvokeVoidAsync("copyToClipboardFallback", OrderJson);
copied = true;
StateHasChanged();
diff --git a/RobotApp.Client/Services/UiEdge.cs b/RobotApp.Client/Services/UiEdge.cs
index 37fadd7..927384a 100644
--- a/RobotApp.Client/Services/UiEdge.cs
+++ b/RobotApp.Client/Services/UiEdge.cs
@@ -1,127 +1,9 @@
using RobotApp.VDA5050.InstantAction;
using RobotApp.VDA5050.Order;
-using System.Text.Json;
using System.Text.Json.Serialization;
-using System.Xml.Linq;
namespace RobotApp.Client.Services;
-// ======================================================
-// EDGE UI
-// ======================================================
-public class UiEdge
-{
- public string EdgeId { get; set; } = "";
- public int SequenceId { get; set; }
- public bool Released { get; set; } = true;
-
- public string StartNodeId { get; set; } = "";
- public string EndNodeId { get; set; } = "";
-
- // ===== CURVE (EDITOR GENERATED) =====
- public double Radius { get; set; } = 0;
- public Quadrant Quadrant { get; set; }
-
- // ===== IMPORTED TRAJECTORY =====
- public bool HasTrajectory { get; set; } = false;
- public UiTrajectory? Trajectory { get; set; }
-
- // ===== UI STATE =====
- public bool Expanded { get; private set; } = false;
-
- public void MarkExpanded()
- {
- Expanded = true;
- }
-}
-
-public class UiTrajectory
-{
- public int Degree { get; set; }
- public double[] KnotVector { get; set; } = Array.Empty();
- public List ControlPoints { get; set; } = new();
-}
-
-public enum Quadrant
-{
- I,
- II,
- III,
- IV
-}
-
-// ======================================================
-// GEOMETRY MODELS
-// ======================================================
-public record Point(double X, double Y);
-
-public record QuarterResult(
- Point EndPoint,
- object Trajectory
-);
-
-// ======================================================
-// GEOMETRY HELPER (QUARTER CIRCLE)
-// ======================================================
-public static class QuarterGeometry
-{
- private const double K = 0.5522847498307936;
-
- public static QuarterResult BuildQuarterTrajectory(
- Point A,
- double r,
- Quadrant q
- )
- {
- Point P1, P2, C;
-
- switch (q)
- {
- case Quadrant.I:
- P1 = new(A.X, A.Y + K * r);
- P2 = new(A.X + K * r, A.Y + r);
- C = new(A.X + r, A.Y + r);
- break;
-
- case Quadrant.II:
- P1 = new(A.X - K * r, A.Y);
- P2 = new(A.X - r, A.Y + K * r);
- C = new(A.X - r, A.Y + r);
- break;
-
- case Quadrant.III:
- P1 = new(A.X, A.Y - K * r);
- P2 = new(A.X - K * r, A.Y - r);
- C = new(A.X - r, A.Y - r);
- break;
-
- case Quadrant.IV:
- P1 = new(A.X + K * r, A.Y);
- P2 = new(A.X + r, A.Y - K * r);
- C = new(A.X + r, A.Y - r);
- break;
-
- default:
- throw new ArgumentOutOfRangeException(nameof(q));
- }
-
- return new QuarterResult(
- C,
- new
- {
- degree = 3,
- knotVector = new[] { 0, 0, 0, 0, 1, 1, 1, 1 },
- controlPoints = new[]
- {
- new { x = A.X, y = A.Y }, // P0
- new { x = P1.X, y = P1.Y }, // P1
- new { x = P2.X, y = P2.Y }, // P2
- new { x = C.X, y = C.Y } // P3
- }
- }
- );
- }
-}
// ======================================================
// ORDER MESSAGE
// ======================================================
@@ -141,110 +23,6 @@ public class OrderMessage
public OrderMsg ToSchemaObject()
{
- // ================= SORT NODES BY UI SEQUENCE =================
- var orderedNodes = Nodes
- .OrderBy(n => n.SequenceId)
- .ToList();
-
- // ================= BUILD NODE OBJECTS =================
- var nodeObjects = orderedNodes
- .Select((n, index) => new Node
- {
- NodeId = n.NodeId,
- SequenceId = index * 2, // ✅ NODE = EVEN
- Released = n.Released,
-
- NodePosition = new NodePosition
- {
- X = n.NodePosition.X,
- Y = n.NodePosition.Y,
- Theta = n.NodePosition.Theta,
-
- AllowedDeviationXY = n.NodePosition.AllowedDeviationXY,
- AllowedDeviationTheta = n.NodePosition.AllowedDeviationTheta,
-
- MapId = string.IsNullOrWhiteSpace(n.NodePosition.MapId)
- ? "MAP_01"
- : n.NodePosition.MapId
- },
-
- Actions = n.Actions?
- .Select(a => new VDA5050.InstantAction.Action
- {
- ActionId = a.ActionId,
- ActionType = a.ActionType,
- BlockingType = a.BlockingType,
-
- ActionParameters = a.ActionParameters?
- .Select(p => new ActionParameter
- {
- Key = p.Key,
- Value = p.Value
- })
- .ToArray()
- ?? []
- })
- .ToArray()
- ?? []
- })
- .ToArray();
-
- // ================= BUILD EDGE OBJECTS =================
- Edge[] edgeObjects = Edges
- .Select((e, index) =>
- {
- int sequenceId = index * 2 + 1; // ✅ EDGE = ODD
-
- // ---------- BASE ----------
- var baseEdge = new
- {
- edgeId = e.EdgeId,
- sequenceId,
- released = true,
- startNodeId = e.StartNodeId,
- endNodeId = e.EndNodeId
- };
-
- // =================================================
- // 1️⃣ IMPORTED TRAJECTORY
- // =================================================
- if (e.Trajectory != null)
- {
- return new Edge
- {
- EdgeId = baseEdge.edgeId,
- SequenceId = baseEdge.sequenceId,
- Released= baseEdge.released,
- StartNodeId= baseEdge.startNodeId,
- EndNodeId= baseEdge.endNodeId,
-
- Trajectory = new Trajectory
- {
- Degree = e.Trajectory.Degree,
- KnotVector = e.Trajectory.KnotVector,
- ControlPoints = e.Trajectory.ControlPoints
- .Select(p => new ControlPoint { X = p.X, Y = p.Y , Weight = 1})
- .ToArray()
- },
-
- Actions = []
- };
- }
-
- return new Edge
- {
- EdgeId = baseEdge.edgeId,
- SequenceId = baseEdge.sequenceId,
- Released = baseEdge.released,
- StartNodeId = baseEdge.startNodeId,
- EndNodeId = baseEdge.endNodeId,
-
- Actions = []
- };
- })
- .ToArray();
-
- // ================= FINAL SCHEMA OBJECT =================
return new OrderMsg
{
HeaderId = (uint)HeaderId++,
@@ -262,8 +40,8 @@ public class OrderMessage
? null
: ZoneSetId,
- Nodes = nodeObjects,
- Edges = edgeObjects,
+ Nodes = [..Nodes],
+ Edges = [..Edges],
};
}
diff --git a/RobotApp.Client/wwwroot/js/app.js b/RobotApp.Client/wwwroot/js/app.js
index 5f28270..c0e2497 100644
--- a/RobotApp.Client/wwwroot/js/app.js
+++ b/RobotApp.Client/wwwroot/js/app.js
@@ -1 +1,10 @@
-
\ No newline at end of file
+window.copyToClipboardFallback = function (text) {
+ const textarea = document.createElement('textarea');
+ textarea.value = text;
+ textarea.style.position = 'fixed';
+ textarea.style.opacity = '0';
+ document.body.appendChild(textarea);
+ textarea.select();
+ document.execCommand('copy');
+ document.body.removeChild(textarea);
+}
\ No newline at end of file
diff --git a/RobotApp.VDA5050/State/EdgeState.cs b/RobotApp.VDA5050/State/EdgeState.cs
index 9382df6..90d29c6 100644
--- a/RobotApp.VDA5050/State/EdgeState.cs
+++ b/RobotApp.VDA5050/State/EdgeState.cs
@@ -13,5 +13,5 @@ public class EdgeState
public string EdgeDescription { get; set; } = string.Empty;
[Required]
public bool Released { get; set; }
- public Trajectory Trajectory { get; set; } = new();
+ public Trajectory? Trajectory { get; set; }
}
diff --git a/RobotApp/Services/Robot/RobotOrderController.cs b/RobotApp/Services/Robot/RobotOrderController.cs
index 64f24ef..bfd0aee 100644
--- a/RobotApp/Services/Robot/RobotOrderController.cs
+++ b/RobotApp/Services/Robot/RobotOrderController.cs
@@ -480,17 +480,22 @@ public class RobotOrderController(INavigation NavigationManager,
for (int i = 0; i < nodes.Count - 1; i++)
{
if (edges[i] is null) return (NodeStates, [.. pathEdges]);
+
+ var trajectory = edges[i].Trajectory;
+ var controlPoints = trajectory?.ControlPoints;
+
+
pathEdges.Add(new()
{
StartX = nodes[i].NodePosition.X,
StartY = nodes[i].NodePosition.Y,
EndX = nodes[i + 1].NodePosition.X,
EndY = nodes[i + 1].NodePosition.Y,
- ControlPoint1X = edges[i].Trajectory is not null && edges[i].Trajectory.ControlPoints.Length > 2 ? edges[i].Trajectory.ControlPoints[1].X : 0,
- 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 is null ? 1 : edges[i].Trajectory.Degree,
+ ControlPoint1X = controlPoints is { Length: > 2 } ? controlPoints[1].X : 0,
+ ControlPoint1Y = controlPoints is { Length: > 2 } ? controlPoints[1].Y : 0,
+ ControlPoint2X = controlPoints is { Length: > 3 } ? controlPoints[2].X : 0,
+ ControlPoint2Y = controlPoints is { Length: > 3 } ? controlPoints[2].Y : 0,
+ Degree = trajectory is null ? 1 : trajectory.Degree,
});
}
}
diff --git a/RobotApp/Services/Robot/RobotPathPlanner.cs b/RobotApp/Services/Robot/RobotPathPlanner.cs
index 33f7238..b7919fa 100644
--- a/RobotApp/Services/Robot/RobotPathPlanner.cs
+++ b/RobotApp/Services/Robot/RobotPathPlanner.cs
@@ -21,11 +21,11 @@ public class RobotPathPlanner(IConfiguration Configuration)
Y1 = inNode.NodePosition.Y,
X2 = futureNode.NodePosition.X,
Y2 = futureNode.NodePosition.Y,
- ControlPoint1X = edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].X : 0,
- ControlPoint1Y = edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].Y : 0,
- ControlPoint2X = edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].X : 0,
- ControlPoint2Y = edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].Y : 0,
- TrajectoryDegree = edge.Trajectory.Degree == 1 ? TrajectoryDegree.One : edge.Trajectory.Degree == 2 ? TrajectoryDegree.Two : TrajectoryDegree.Three,
+ ControlPoint1X = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].X : 0,
+ ControlPoint1Y = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].Y : 0,
+ ControlPoint2X = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].X : 0,
+ ControlPoint2Y = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].Y : 0,
+ TrajectoryDegree = edge.Trajectory is null ? TrajectoryDegree.One : edge.Trajectory.Degree == 1 ? TrajectoryDegree.One : edge.Trajectory.Degree == 2 ? TrajectoryDegree.Two : TrajectoryDegree.Three,
});
(double robotx, double roboty) =
(
@@ -61,30 +61,46 @@ public class RobotPathPlanner(IConfiguration Configuration)
navigationNodes[0].Direction = GetDirectionInNode(currentTheta, nodes[0], nodes[1], edges[0]);
for (int i = 1; i < nodes.Length - 1; i++)
{
+ var trajectory = edges[i - 1].Trajectory;
+ var controlPoints = trajectory?.ControlPoints;
(double lastx, double lasty) = MathExtensions.Curve(0.1, new()
{
X1 = nodes[i - 1].NodePosition.X,
Y1 = nodes[i - 1].NodePosition.Y,
X2 = nodes[i].NodePosition.X,
Y2 = nodes[i].NodePosition.Y,
- ControlPoint1X = edges[i - 1].Trajectory.ControlPoints.Length > 2 ? edges[i - 1].Trajectory.ControlPoints[1].X : 0,
- ControlPoint1Y = edges[i - 1].Trajectory.ControlPoints.Length > 2 ? edges[i - 1].Trajectory.ControlPoints[1].Y : 0,
- ControlPoint2X = edges[i - 1].Trajectory.ControlPoints.Length > 3 ? edges[i - 1].Trajectory.ControlPoints[2].X : 0,
- ControlPoint2Y = edges[i - 1].Trajectory.ControlPoints.Length > 3 ? edges[i - 1].Trajectory.ControlPoints[2].Y : 0,
- TrajectoryDegree = edges[i - 1].Trajectory.Degree == 1 ? TrajectoryDegree.One : edges[i - 1].Trajectory.Degree == 2 ? TrajectoryDegree.Two : TrajectoryDegree.Three,
+ ControlPoint1X = controlPoints is { Length: > 2 } ? controlPoints[1].X : 0,
+ ControlPoint1Y = controlPoints is { Length: > 2 } ? controlPoints[1].Y : 0,
+ ControlPoint2X = controlPoints is { Length: > 3 } ? controlPoints[2].X : 0,
+ ControlPoint2Y = controlPoints is { Length: > 3 } ? controlPoints[2].Y : 0,
+ TrajectoryDegree = trajectory?.Degree switch
+ {
+ 1 => TrajectoryDegree.One,
+ 2 => TrajectoryDegree.Two,
+ _ => TrajectoryDegree.Three
+ },
});
+
+ trajectory = edges[i].Trajectory;
+ controlPoints = trajectory?.ControlPoints;
(double futurex, double futurey) = MathExtensions.Curve(0.1, new()
{
X1 = nodes[i].NodePosition.X,
Y1 = nodes[i].NodePosition.Y,
X2 = nodes[i + 1].NodePosition.X,
Y2 = nodes[i + 1].NodePosition.Y,
- ControlPoint1X = edges[i].Trajectory.ControlPoints.Length > 2 ? edges[i].Trajectory.ControlPoints[1].X : 0,
- ControlPoint1Y = edges[i].Trajectory.ControlPoints.Length > 2 ? edges[i].Trajectory.ControlPoints[1].Y : 0,
- ControlPoint2X = edges[i].Trajectory.ControlPoints.Length > 3 ? edges[i].Trajectory.ControlPoints[2].X : 0,
- ControlPoint2Y = edges[i].Trajectory.ControlPoints.Length > 3 ? edges[i].Trajectory.ControlPoints[2].Y : 0,
- TrajectoryDegree = edges[i].Trajectory.Degree == 1 ? TrajectoryDegree.One : edges[i].Trajectory.Degree == 2 ? TrajectoryDegree.Two : TrajectoryDegree.Three,
+ ControlPoint1X = controlPoints is { Length: > 2 } ? controlPoints[1].X : 0,
+ ControlPoint1Y = controlPoints is { Length: > 2 } ? controlPoints[1].Y : 0,
+ ControlPoint2X = controlPoints is { Length: > 3 } ? controlPoints[2].X : 0,
+ ControlPoint2Y = controlPoints is { Length: > 3 } ? controlPoints[2].Y : 0,
+ TrajectoryDegree = trajectory?.Degree switch
+ {
+ 1 => TrajectoryDegree.One,
+ 2 => TrajectoryDegree.Two,
+ _ => TrajectoryDegree.Three
+ },
});
+
var angle = MathExtensions.GetVectorAngle(
nodes[i].NodePosition.X,
nodes[i].NodePosition.Y,
@@ -128,11 +144,11 @@ public class RobotPathPlanner(IConfiguration Configuration)
Y1 = startNode.Y,
X2 = endNode.X,
Y2 = endNode.Y,
- ControlPoint1X = edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].X : 0,
- ControlPoint1Y = edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].Y : 0,
- ControlPoint2X = edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].X : 0,
- ControlPoint2Y = edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].Y : 0,
- TrajectoryDegree = edge.Trajectory.Degree == 1 ? TrajectoryDegree.One : edge.Trajectory.Degree == 2 ? TrajectoryDegree.Two : TrajectoryDegree.Three
+ ControlPoint1X = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].X : 0,
+ ControlPoint1Y = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].Y : 0,
+ ControlPoint2X = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].X : 0,
+ ControlPoint2Y = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].Y : 0,
+ TrajectoryDegree = edge.Trajectory is null ? TrajectoryDegree.One : edge.Trajectory.Degree == 1 ? TrajectoryDegree.One : edge.Trajectory.Degree == 2 ? TrajectoryDegree.Two : TrajectoryDegree.Three
};
double length = EdgeCalculatorModel.GetEdgeLength();
@@ -194,11 +210,11 @@ public class RobotPathPlanner(IConfiguration Configuration)
Y1 = startNode.NodePosition.Y,
X2 = endNode.NodePosition.X,
Y2 = endNode.NodePosition.Y,
- ControlPoint1X = edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].X : 0,
- ControlPoint1Y = edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].Y : 0,
- ControlPoint2X = edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].X : 0,
- ControlPoint2Y = edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].Y : 0,
- TrajectoryDegree = edge.Trajectory.Degree == 1 ? TrajectoryDegree.One : edge.Trajectory.Degree == 2 ? TrajectoryDegree.Two : TrajectoryDegree.Three
+ ControlPoint1X = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].X : 0,
+ ControlPoint1Y = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 2 ? edge.Trajectory.ControlPoints[1].Y : 0,
+ ControlPoint2X = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].X : 0,
+ ControlPoint2Y = edge.Trajectory is not null && edge.Trajectory.ControlPoints.Length > 3 ? edge.Trajectory.ControlPoints[2].Y : 0,
+ TrajectoryDegree = edge.Trajectory is null ? TrajectoryDegree.One : edge.Trajectory.Degree == 1 ? TrajectoryDegree.One : edge.Trajectory.Degree == 2 ? TrajectoryDegree.Two : TrajectoryDegree.Three
};
double length = EdgeCalculatorModel.GetEdgeLength();