258 lines
7.5 KiB
C#
258 lines
7.5 KiB
C#
using RobotApp.VDA5050.InstantAction;
|
|
using RobotApp.VDA5050.Order;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace RobotApp.Client.Services;
|
|
|
|
// ======================================================
|
|
// EDGE UI
|
|
// ======================================================
|
|
public class UiEdge : VDA5050.Order.Edge
|
|
{
|
|
public double Radius { get; set; } = 0.0;
|
|
public Quadrant Quadrant { get; set; } = Quadrant.I;
|
|
|
|
// Đánh dấu đã expand chưa
|
|
public bool Expanded { get; set; } = false;
|
|
}
|
|
|
|
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
|
|
// ======================================================
|
|
public class OrderMessage
|
|
{
|
|
public int HeaderId { get; set; }
|
|
public string Timestamp { get; set; } = "";
|
|
public string Version { get; set; } = "v1";
|
|
public string Manufacturer { get; set; } = "PNKX";
|
|
public string SerialNumber { get; set; } = "T800-002";
|
|
public string OrderId { get; set; } = Guid.NewGuid().ToString();
|
|
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
|
|
);
|
|
|
|
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 object ToSchemaObject()
|
|
{
|
|
int seq = 0;
|
|
|
|
return new
|
|
{
|
|
headerId = HeaderId++,
|
|
|
|
timestamp = string.IsNullOrWhiteSpace(Timestamp)
|
|
? DateTime.UtcNow.ToString("O")
|
|
: Timestamp,
|
|
|
|
version = Version,
|
|
manufacturer = Manufacturer,
|
|
serialNumber = SerialNumber,
|
|
orderId = OrderId,
|
|
orderUpdateId = OrderUpdateId,
|
|
|
|
zoneSetId = string.IsNullOrWhiteSpace(ZoneSetId)
|
|
? null
|
|
: ZoneSetId,
|
|
|
|
// ================= NODES =================
|
|
nodes = Nodes.Select(n => new
|
|
{
|
|
nodeId = n.NodeId,
|
|
sequenceId = seq++,
|
|
released = n.Released,
|
|
|
|
nodePosition = new
|
|
{
|
|
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
|
|
{
|
|
actionId = a.ActionId,
|
|
actionType = a.ActionType,
|
|
blockingType = a.BlockingType,
|
|
|
|
actionParameters = a.ActionParameters != null
|
|
? a.ActionParameters
|
|
.Select(p => new { key = p.Key, value = p.Value })
|
|
.ToArray()
|
|
: Array.Empty<object>()
|
|
}).ToArray()
|
|
}).ToArray(),
|
|
|
|
// ================= EDGES =================
|
|
edges = Edges.Select<UiEdge, object>(e =>
|
|
{
|
|
// ---------- ĐƯỜNG THẲNG ----------
|
|
if (e.Radius <= 0)
|
|
{
|
|
return new
|
|
{
|
|
edgeId = e.EdgeId,
|
|
sequenceId = seq++,
|
|
released = true,
|
|
startNodeId = e.StartNodeId,
|
|
endNodeId = e.EndNodeId,
|
|
actions = Array.Empty<object>()
|
|
};
|
|
}
|
|
|
|
// ---------- ĐƯỜNG CONG 1/4 ----------
|
|
var startNode = Nodes.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
|
|
{
|
|
edgeId = e.EdgeId,
|
|
sequenceId = seq++,
|
|
released = true,
|
|
|
|
startNodeId = e.StartNodeId,
|
|
endNodeId = e.EndNodeId,
|
|
|
|
trajectory = result.Trajectory,
|
|
actions = Array.Empty<object>()
|
|
};
|
|
}).ToArray()
|
|
};
|
|
}
|
|
}
|
|
|
|
// ======================================================
|
|
// UI ACTION PARAM
|
|
// ======================================================
|
|
public class UiActionParameter : ActionParameter
|
|
{
|
|
[JsonIgnore]
|
|
public string ValueString
|
|
{
|
|
get => Value?.ToString() ?? "";
|
|
set => Value = value;
|
|
}
|
|
}
|