217 lines
7.4 KiB
C#
217 lines
7.4 KiB
C#
using sc.modeling.splines.runtime;
|
|
using Simulator.Data;
|
|
using Simulator.Data.Transport;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using UnityEngine.Splines;
|
|
using UVC.Core;
|
|
using UVC.Data;
|
|
using UVC.Data.Core;
|
|
using UVC.Data.Mqtt;
|
|
public class ConveyorPathMeta : MonoBehaviour
|
|
{
|
|
public string Name;
|
|
public string From;
|
|
public string To;
|
|
public float Speed;
|
|
public float Length;
|
|
public int Capacity;
|
|
}
|
|
|
|
public class ConveyorManager : SingletonScene<ConveyorManager>
|
|
{
|
|
[Header("Root & Visual")]
|
|
[SerializeField] private Transform rootParent; // 생성될 경로의 부모(없으면 빌더 자신)
|
|
[SerializeField] private float tangentScale = 0.25f; // 곡률(탄젠트 길이 비율)
|
|
[SerializeField]
|
|
ConveyorComponent splineprefab;
|
|
[SerializeField]
|
|
GameObject cube;
|
|
|
|
public Dictionary<string, ConveyorNode> Nodes = new Dictionary<string, ConveyorNode>();
|
|
public Dictionary<(string,string), ConveyorComponent> Paths = new Dictionary<(string, string), ConveyorComponent>();
|
|
public DataMapper conveyorStartDataMapper;
|
|
public DataMapper conveyorCompleteDataMapper;
|
|
|
|
protected override void Init()
|
|
{
|
|
var conveyorStartDataMask = new DataMask();
|
|
conveyorStartDataMask.ObjectName = "conveyor"; // AGV 객체의 이름을 설정합니다.
|
|
conveyorStartDataMask.ObjectIdKey = "component_id"; // AGV의 고유 식별자로 사용할 키를 설정합니다.
|
|
conveyorStartDataMask["component_id"] = "";
|
|
conveyorStartDataMask["event_name"] = "";
|
|
conveyorStartDataMask["timestamp"] = new DateTime();
|
|
conveyorStartDataMask["data"] = new DataMask()
|
|
{
|
|
["entity_id_original"] = "",
|
|
["start_node"] = "",
|
|
["end_node"] = "",
|
|
["travel_time"]=0.0f
|
|
};
|
|
conveyorStartDataMapper=new DataMapper(conveyorStartDataMask);
|
|
|
|
var conveyorCompleteDataMask = new DataMask();
|
|
conveyorCompleteDataMask.ObjectName = "conveyor"; // AGV 객체의 이름을 설정합니다.
|
|
conveyorCompleteDataMask.ObjectIdKey = "component_id"; // AGV의 고유 식별자로 사용할 키를 설정합니다.
|
|
conveyorCompleteDataMask["component_id"] = "";
|
|
conveyorCompleteDataMask["event_name"] = "";
|
|
conveyorCompleteDataMask["timestamp"] = new DateTime();
|
|
conveyorCompleteDataMask["data"] = new DataMask()
|
|
{
|
|
["entity_id_original"] = "",
|
|
["start_node"] = "",
|
|
["end_node"] = "",
|
|
};
|
|
conveyorCompleteDataMapper = new DataMapper(conveyorCompleteDataMask);
|
|
}
|
|
|
|
public void Build(List<ConveyorDataClass> datas)
|
|
{
|
|
if (datas==null||datas.Count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
var data = datas[0];
|
|
if (rootParent == null) rootParent = transform;
|
|
|
|
if (data.nodes != null)
|
|
{
|
|
foreach (var n in data.nodes)
|
|
{
|
|
Nodes[n.name] = n;
|
|
}
|
|
}
|
|
|
|
foreach (var path in data.paths)
|
|
{
|
|
CreatePathGOWithSpline(path, Nodes[path.from_node], Nodes[path.to_node]);
|
|
}
|
|
SpawnJunction();
|
|
|
|
SubscribeConveyor(data);
|
|
}
|
|
|
|
public void SubscribeConveyor(ConveyorDataClass data)
|
|
{
|
|
DataRepository.Instance.MqttReceiver.AddTopic($"simulation/{SimulationConfig.SimulationCode}/components/+/{data.name}/+/node_started");
|
|
var mqttConfigConveyorStart = new MqttSubscriptionConfig($"simulation/{SimulationConfig.SimulationCode}/components/+/{data.name}/+/node_started");
|
|
mqttConfigConveyorStart.SetDataMapper(conveyorStartDataMapper);
|
|
mqttConfigConveyorStart.SetHandler(OnSetData);
|
|
DataRepository.Instance.MqttReceiver.Add(mqttConfigConveyorStart);
|
|
/*
|
|
DataRepository.Instance.MqttReceiver.AddTopic($"simulation/{SimulationConfig.SimulationCode}/components/+/{data.name}/+/node_completed");
|
|
var mqttConfigConveyorComplete = new MqttSubscriptionConfig($"simulation/{SimulationConfig.SimulationCode}/components/+/{data.name}/+/node_completed");
|
|
mqttConfigConveyorComplete.SetDataMapper(conveyorCompleteDataMapper);
|
|
mqttConfigConveyorComplete.SetHandler(OnUnSetData);
|
|
DataRepository.Instance.MqttReceiver.Add(mqttConfigConveyorComplete);
|
|
*/
|
|
}
|
|
|
|
private void CreatePathGOWithSpline(ConveyorPath path, ConveyorNode fromNode, ConveyorNode toNode)
|
|
{
|
|
TryGetNodePos(fromNode.name, out Vector3 fromPos);
|
|
TryGetNodePos(toNode.name, out Vector3 toPos);
|
|
string goName = path.name;
|
|
|
|
var go = Instantiate(splineprefab);
|
|
Paths.Add((fromNode.name,toNode.name), go);
|
|
go.transform.SetParent(rootParent, worldPositionStays: false);
|
|
|
|
var container = go.GetComponent<SplineContainer>();
|
|
|
|
var spline = new Spline();
|
|
|
|
Vector3 dir = (toPos - fromPos);
|
|
float dist = dir.magnitude;
|
|
Vector3 dirNorm = dist > 1e-5f ? dir / dist : Vector3.forward;
|
|
|
|
Vector3 tan = dirNorm * dist * Mathf.Clamp01(tangentScale);
|
|
|
|
var k0 = new BezierKnot(fromPos)
|
|
{
|
|
TangentOut = tan,
|
|
TangentIn = Vector3.zero
|
|
};
|
|
|
|
var k1 = new BezierKnot(toPos)
|
|
{
|
|
TangentIn = -tan,
|
|
TangentOut = Vector3.zero
|
|
};
|
|
|
|
spline.Add(k0, TangentMode.Broken);
|
|
spline.Add(k1, TangentMode.Broken);
|
|
|
|
container.Spline = spline;
|
|
var mesher = go.GetComponent<SplineMesher>();
|
|
if(string.Equals(fromNode.node_type, "junction"))
|
|
{
|
|
mesher.DetachCap(0);
|
|
}
|
|
if (string.Equals(toNode.node_type, "junction"))
|
|
{
|
|
mesher.DetachCap(1);
|
|
}
|
|
mesher.UpdateCaps();
|
|
mesher.Rebuild();
|
|
}
|
|
|
|
private void SpawnJunction()
|
|
{
|
|
foreach(var node in Nodes)
|
|
{
|
|
if (string.Equals(node.Value.node_type, "junction"))
|
|
{
|
|
var module = Instantiate(cube);
|
|
module.transform.position=ToVector3(node.Value.position);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnSetData(IDataObject idata)
|
|
{
|
|
if (idata == null) return;
|
|
|
|
DataObject? obj = idata as DataObject;
|
|
if (obj == null) return;
|
|
//Debug.Log($"OnUpdateData:{obj}, {obj["data"]}");
|
|
var data = obj.GetDataObject("data");
|
|
var fromNodeName = data.GetString("start_node");
|
|
var toNodeName = data.GetString("end_node");
|
|
ConveyorComponent? conveyor = Paths[(fromNodeName,toNodeName)];
|
|
conveyor.SetModelData(obj);
|
|
}
|
|
|
|
private void OnUnSetData(IDataObject idata)
|
|
{
|
|
if (idata == null) return;
|
|
|
|
DataObject? obj = idata as DataObject;
|
|
if (obj == null) return;
|
|
//Debug.Log($"OnUpdateData:{obj}, {obj["data"]}");
|
|
var data = obj.GetDataObject("data");
|
|
var fromNodeName = data.GetString("start_node");
|
|
var toNodeName = data.GetString("end_node");
|
|
ConveyorComponent? conveyor = Paths[(fromNodeName, toNodeName)];
|
|
conveyor.UnSetModelData(obj);
|
|
}
|
|
|
|
private bool TryGetNodePos(string nodeName, out Vector3 pos)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(nodeName) && Nodes.TryGetValue(nodeName, out ConveyorNode node))
|
|
{
|
|
pos = ToVector3(node.position);
|
|
return true;
|
|
}
|
|
|
|
pos = default;
|
|
return false;
|
|
}
|
|
|
|
private Vector3 ToVector3(Position p)
|
|
{
|
|
return new Vector3(p.x, p.z, p.y);
|
|
}
|
|
} |