|
|
@@ -171,7 +171,7 @@ namespace TeamAAS_VP.Core.Robots
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public int Timeout { get; set; } = 120000;
|
|
|
+ public int Timeout { get; set; } = 5000;
|
|
|
|
|
|
private bool _CanExecute = true;
|
|
|
|
|
|
@@ -483,9 +483,7 @@ namespace TeamAAS_VP.Core.Robots
|
|
|
CanExecute = false;
|
|
|
Dictionary<string, object> keyValues = new Dictionary<string, object>();
|
|
|
|
|
|
- // 1. 复位所有轴的开始移动命令
|
|
|
- //StopMove();
|
|
|
-
|
|
|
+ // 1. 写入目标位置到各轴的 ManuPositionNode
|
|
|
keyValues = new Dictionary<string, object>();
|
|
|
foreach (var axis in Axes)
|
|
|
{
|
|
|
@@ -514,12 +512,84 @@ namespace TeamAAS_VP.Core.Robots
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- // 4. 等待移动完成
|
|
|
+ // 准备停滞检测:收集所有实际位置节点
|
|
|
+ var actNodes = Axes.Where(a => !string.IsNullOrWhiteSpace(a.State.ActPositionNode))
|
|
|
+ .Select(a => a.State.ActPositionNode)
|
|
|
+ .Distinct()
|
|
|
+ .ToArray();
|
|
|
+
|
|
|
+ // lastPos 存储上一次读取到的位置,lastChange 存储上次发生“实质性”变化的时间
|
|
|
+ Dictionary<string, float> lastPos = new Dictionary<string, float>();
|
|
|
+ Dictionary<string, DateTime> lastChange = new Dictionary<string, DateTime>();
|
|
|
+ foreach (var node in actNodes)
|
|
|
+ {
|
|
|
+ lastPos[node] = float.NaN;
|
|
|
+ lastChange[node] = DateTime.UtcNow;
|
|
|
+ }
|
|
|
+
|
|
|
+ const float movementThreshold = 0.01f; // 判断位置变化的阈值,避免噪声
|
|
|
Stopwatch sw = new Stopwatch();
|
|
|
sw.Start();
|
|
|
while (true)
|
|
|
{
|
|
|
- //检查各轴是否到位和目标位置一致
|
|
|
+ // 先读取各轴的实际位置,用于停滞检测
|
|
|
+ Dictionary<string, object> posRead = new Dictionary<string, object>();
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (actNodes.Length > 0)
|
|
|
+ {
|
|
|
+ posRead = Plc.ReadNodes(actNodes);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch
|
|
|
+ {
|
|
|
+ // 如果读取失败,继续让 CheckMoveFinished 来处理状态或超时
|
|
|
+ }
|
|
|
+
|
|
|
+ var now = DateTime.UtcNow;
|
|
|
+
|
|
|
+ // 更新每个节点的变化时间:只要任意一个轴在最近 Timeout 时间内有变化,就视为系统仍在运动
|
|
|
+ foreach (var node in actNodes)
|
|
|
+ {
|
|
|
+ float actual = 0;
|
|
|
+ if (posRead != null && posRead.ContainsKey(node))
|
|
|
+ {
|
|
|
+ var raw = posRead[node];
|
|
|
+ if (raw != null)
|
|
|
+ {
|
|
|
+ try { actual = Convert.ToSingle(raw); } catch { /* 保持 actual = 0 */ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (float.IsNaN(lastPos[node]))
|
|
|
+ {
|
|
|
+ lastPos[node] = actual;
|
|
|
+ lastChange[node] = now;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (Math.Abs(actual - lastPos[node]) > movementThreshold)
|
|
|
+ {
|
|
|
+ // 有实质性变化,更新记录时间和值
|
|
|
+ lastPos[node] = actual;
|
|
|
+ lastChange[node] = now;
|
|
|
+ }
|
|
|
+ // 否则保持 lastChange 不变(表示该轴最近一次变化的时间)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 判断是否至少有一个轴在最近 Timeout 时间内发生过变化(即认为还在运动)
|
|
|
+ bool anyAxisMovedRecently = actNodes.Any(node => (now - lastChange[node]).TotalMilliseconds <= Timeout);
|
|
|
+
|
|
|
+ // 如果没有任何轴在最近 Timeout 时间内发生变化,则认为出现停滞异常
|
|
|
+ if (!anyAxisMovedRecently && actNodes.Length > 0)
|
|
|
+ {
|
|
|
+ StopMove();
|
|
|
+ LogHelper.WriteLogInfo($"轴停滞超时(整体判定),目标位置:X={position.X},Y={position.Y},Z={position.Z},U={position.U},超时阈值(ms)={Timeout}");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否整体到位或有错误(保留原有逻辑)
|
|
|
var (isFinished, isError) = CheckMoveFinished(position);
|
|
|
if (isFinished)
|
|
|
{
|
|
|
@@ -531,12 +601,15 @@ namespace TeamAAS_VP.Core.Robots
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
- if (sw.ElapsedMilliseconds > Timeout)
|
|
|
+
|
|
|
+ // 检查整体超时(防止一直有抖动导致 anyAxisMovedRecently 一直为 true)
|
|
|
+ if (sw.ElapsedMilliseconds > 60000) // 保守超时,一分钟,可根据需求调整
|
|
|
{
|
|
|
LogHelper.WriteLogInfo($"机器人执行移动超时,位置:X={position.X},Y={position.Y},Z={position.Z},U={position.U}");
|
|
|
StopMove();
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
Thread.Sleep(10);
|
|
|
}
|
|
|
}
|