using FObjBase;
using Misc;
using NLog.Fluent;
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting.Channels;
namespace FlyADBase
{
public partial class FlyAd2021B2 : IFlyADClientAdv
{
#region IFlyADClientAdv property
///
/// grid数据平滑
///
public int GridSmooth { get; set; }
///
/// 机架总长
///
public int PosLen { get; set; } = 8900;
///
/// 使用独立的脉冲最大最小值
///
public bool HasPosMaxMin { get; set; }
///
/// 最小脉冲,默认是0
///
public int PosMin { get; set; } = 0;
///
/// 最大脉冲,默认于PosLen 一样
///
public int PosMax { get; set; } = 8900;
public int GridLen => PosLen / PosOfGrid;
///
/// Speed1 = Velocity * Speed1Scale
///
public double Speed1Scale => (double)Ratio02 / Ratio01;
///
/// 动作完成
///
public bool IsFinish { get; set; }
///
/// ad滞后修正 单位ms
///
public int ADLag { get; set; }
///
/// ad2滞后修正 单位ms
///
public int AD2Lag { get; set; }
//一共有1.AD数据池(由timegrid提供) 1min
//2.pos数据池(pos推送提供) 1min
//4.当接收的grid事件数据。它有 (direction, grid_start,grid_len, systick )
//systick 就是结束的时间点。 当AD数据池出现了这个时间点
//pos数据池向前找。 pos 在 grid_start*posOfGrid 范围的数据。
//找到开始的systick 后,整合3个数据池的数据。
//5.最后代替 grid 推送出去。
public TimeGridAdvHelper mTimeGridAdvHelper { get; } = new TimeGridAdvHelper();
///
/// 动作指令完成,准备推送 timegridadv 事件
///
public bool IsTimeToPushTimeGridAdv { get; private set; } = false;
///
/// 以timegrid 为单位,推送数据
///
public event TimeGridAdv2EventHandler TimeGridAdv2Event;
#endregion
DateTime lastUpdateADTime;
int lastGrid = Misc.MyBase.NULL_VALUE;
DateTime lastGridTime;
Stopwatch stopwatch_gridTime = new Stopwatch();
void advConstructor()
{
mTimeGridAdvHelper.Init();
this.PropertyChanged += FlyAD7_PropertyChanged1;
//轮询事件触发
PollModule.Current.Poll_Config(PollModule.POLL_CONFIG.ADD, OnPoll);
}
private void FlyAD7_PropertyChanged1(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(DriveStatus))
{
switch (DriveStatus)
{
case DRIVE_MAN_STATUS.STOP_MANUAL:
case DRIVE_MAN_STATUS.STOP:
case DRIVE_MAN_STATUS.LIMIT:
IsFinish = true;
break;
case DRIVE_MAN_STATUS.RUNNING:
IsFinish = false;
break;
}
}
}
void advAfterContected()
{
mTimeGridAdvHelper.Clear();
lastUpdateADTime = DateTime.MinValue;
lastGrid = Misc.MyBase.NULL_VALUE;
lastGridTime = DateTime.MinValue;
}
#region IFlyADClientAdv function
///
/// Runto(0), 不同于 Backward
///
public void RuntoMin()
{
if (HasPosMaxMin)
Runto(PosMin);
else
Runto(0);
}
///
/// Runto(PosLen), 不同于 Forward
///
public void RuntoMax()
{
if (HasPosMaxMin)
Runto(PosMax);
else
Runto(PosLen);
}
///
/// 设置输出
///
///
///
public void SetOutputBit(int index, bool is1)
{
if (index > 15)//4)
return;
if (index < 0)
return;
if (is1)
{
SetOutput(
(UInt16)Misc.MyBase.BIT(index),
(UInt16)Misc.MyBase.BIT(index));
}
else
{
SetOutput(
(UInt16)Misc.MyBase.BIT(index),
(UInt16)~Misc.MyBase.BIT(index));
}
}
#endregion
void advPushData(DateTime dt, int ad, int ad2)
{
var ret = mTimeGridAdvHelper.AddData(dt, ad, ad2, Position, Position2, IStatus);
if (ret.isChanged)
{
if (ret.isIstatusChanged) {
IStatusChangedEvent?.Invoke(this,
new IStatusChangedEventArgs(Now, IStatus, ret.ichanged, Position, Position2));
}
if (ret.isPosChanged)
{
PositionChangedEvent?.Invoke(this, new PositionChangedEventArgs() { Time = Now, Position = Position });
}
if (ret.isPos2Changed)
{
Position2ChangedEvent?.Invoke(this, new PositionChangedEventArgs() { Time = Now, Position = Position2 });
}
}
}
void advPushStatus()
{
if (mTimeGridAdvHelper.AddDriveStatus(Now, DriveOrder, DriveStatus))
{
//状态变了
if (DriveStatus != DRIVE_MAN_STATUS.RUNNING)
{
//通知 mTimeGridAdvHelper 下次触发 timegridadv
IsTimeToPushTimeGridAdv = true;
}
DriveStatusChangedEvent?.Invoke(this, new DriveStatusChangedEventArgs()
{
Time = Now,
DriveOrder = DriveOrder,
DriveStatus = DriveStatus
});
}
}
///
/// ScanMotion 使用。
/// 给定按扫描的时间点。当探头停下来后,获取数据。
/// 数据带滞后修正,带运动方向。
///
///
///
public TimeGridAdv2EventArgs GetTimeGridAdv2Event(DateTime beginTime)
{
//获取ad列表
var dataList = mTimeGridAdvHelper.GetData(beginTime);
if (dataList.Count() == 0)
return null;
DateTime endTime = mTimeGridAdvHelper.NewestTime;
Misc.DIRECTION direction;
//判断运动方向
if (dataList.Last().pos > dataList.First().pos)
{
//正向
direction = DIRECTION.FORWARD;
}
else
{
direction = DIRECTION.BACKWARD;
}
//数据滞后
if(!TimeGridAdvHelperExt.AdLagCorr(dataList, ref endTime, ADLag, AD2Lag))
{
throw new Exception("数据量太少,无法滞后修正");
}
TimeGridAdv2EventArgs eventArgs = new TimeGridAdv2EventArgs();
eventArgs.Direction = direction;
eventArgs.EndTime = endTime;
eventArgs.DataList = dataList;
return eventArgs;
}
void OnPoll()
{
if (!IsConnected)
return;
if (!IsReady)
return;
OnPoll_TimeGrid();
OnPoll_TimeGridAdv();
OnPoll_miniGrid();
}
//没有滞后处理,没有机架修正
void OnPoll_TimeGrid()
{
if (lastUpdateADTime == DateTime.MinValue)
{
lastUpdateADTime = Now;
return;
}
if (Now - lastUpdateADTime < TimeSpan.FromSeconds(0.1))
return;
//获取0.1s到现在的数据
var dataList = mTimeGridAdvHelper.GetData(lastUpdateADTime);
//算AD均值
int[] ad1s = dataList.Select(d => d.ad).ToArray();
int[] ad2s = dataList.Select(d => d.ad2).ToArray();
int ad = (int)ad1s.Average();
AD = ad;
int ad2 = (int)ad2s.Average();
AD2 = ad2;
//推送timegrid事件
TimeGridEvent?.Invoke(this,
new TimeGridEventArgs()
{
Time = lastUpdateADTime,
Ad1s = ad1s,
Ad2s = ad2s
});
lastUpdateADTime = Now;
}
//没有滞后处理,没有机架修正
void OnPoll_miniGrid()
{
int grid = Position / PosOfGrid;
if (!Misc.MyBase.ISVALIDATA(lastGrid))
{
lastGrid = grid;
lastGridTime = Now;
stopwatch_gridTime.Restart();
return;
}
if (lastGrid == grid)
{
if (Now - lastGridTime > TimeSpan.FromSeconds(2))
{
//太慢,超过2秒还没走完一个grid
//强制缩少数据
lastGridTime = Now;
}
return;
}
if (stopwatch_gridTime.Elapsed < TimeSpan.FromSeconds(0.1))
{
//太快,控制推送频率
return;
}
stopwatch_gridTime.Restart();
//方向
Misc.DIRECTION direction;
if (lastGrid < grid)
direction = Misc.DIRECTION.FORWARD;
else
direction = Misc.DIRECTION.BACKWARD;
var dataList = mTimeGridAdvHelper.GetData(lastGridTime);
var endTime = mTimeGridAdvHelper.NewestTime;
//数据滞后
if (!TimeGridAdvHelperExt.AdLagCorr(dataList, ref endTime, ADLag, AD2Lag))
{
//throw new Exception("数据量太少,无法滞后修正");
return;
}
//获取grid图
TimeGridAdvHelperExt.ToGrid(dataList, PosOfGrid, GridLen,
out int grid_start, out int grid_end,
out int[] gridsOfAd1, out int[] gridsOfAd2,
isMiniGrid: true);
if (gridsOfAd1 == null)
return;
if (grid_start >= GridLen)
return;
//需要推送grid
MiniGridEvent?.Invoke(this, new MiniGridEventArgs()
{
direction = direction,
grid_start = grid_start,
posOfGrid = PosOfGrid,
buf = gridsOfAd1,
buf2= gridsOfAd2,
});
lastGrid = grid;
lastGridTime = Now;
}
void OnPoll_TimeGridAdv()
{
if (!IsTimeToPushTimeGridAdv)
return;
IsTimeToPushTimeGridAdv = false;
if (TimeGridAdv2Event == null)
return;
//触发全部高级版的 timegrid
bool ret = mTimeGridAdvHelper.GetLastRunningTime(out DateTime beginTime, out DateTime endTime, out DRIVE_MAN_ORDER order);
if (!ret)
return;
var eventArgs = GetTimeGridAdv2Event(beginTime);
//获取ad列表
var dataList = eventArgs.DataList;
int dataCnt = dataList.Count();
if (dataCnt == 0)
return;
endTime = eventArgs.EndTime;
var direction = eventArgs.Direction;
//生成grid图
TimeGridAdvHelperExt.ToGrid(dataList, PosOfGrid, GridLen,
out int grid_start, out int grid_end,
out int[] gridsOfAd1, out int[] gridsOfAd2);
//触发事件
TimeGridAdv2Event?.Invoke(this, new TimeGridAdv2EventArgs
{
Direction = direction,
EndTime = endTime,
DataList= dataList
});
}
}
class CalSpeed
{
DateTime last_now;
DateTime pos1_changed_time;
DateTime pos2_changed_time;
DateTime last_pos1_changed_time;
DateTime last_pos2_changed_time;
int last_pos1;
int last_pos2;
int pos1;
int pos2;
public bool Cal(DateTime now, out int speed1, out int speed2)
{
speed1 = 0;
speed2 = 0;
if (last_now == DateTime.MinValue && now != DateTime.MinValue)
{
last_now = now;
last_pos1_changed_time = pos1_changed_time;
last_pos2_changed_time = pos2_changed_time;
last_pos1 = pos1;
last_pos2 = pos2;
return false;
}
if (now - last_now < TimeSpan.FromSeconds(0.5))
return false;
bool isInvalid = false;
if (pos1_changed_time != last_pos1_changed_time && last_pos1_changed_time != DateTime.MinValue)
{
var spd = (int)((pos1 - last_pos1) / (pos1_changed_time - last_pos1_changed_time).TotalSeconds);
if (Math.Abs(spd) > 100000)
{
//肯定是溢出了,
isInvalid = true;
}
else
{
speed1 = spd;
}
}
else
{
//停了
speed1 = 0;
}
if (pos2_changed_time != last_pos2_changed_time && last_pos2_changed_time != DateTime.MinValue)
{
var spd= (int)((pos2 - last_pos2) / (pos2_changed_time - last_pos2_changed_time).TotalSeconds);
if (Math.Abs(spd) > 100000)
{
//肯定是溢出了,
isInvalid = true;
}
else {
speed2 = spd;
}
}
else
{
//停了
speed2 = 0;
}
last_now = now;
last_pos1_changed_time = pos1_changed_time;
last_pos2_changed_time = pos2_changed_time;
last_pos1 = pos1;
last_pos2 = pos2;
if (isInvalid)
return false;
else
return true;
}
public void SetPos1(DateTime changedTime, int pos)
{
pos1_changed_time = changedTime;
pos1 = pos;
}
public void SetPos2(DateTime changedTime, int pos)
{
pos2_changed_time = changedTime;
pos2 = pos;
}
public void Reset()
{
last_now = DateTime.MinValue;
pos1_changed_time = DateTime.MinValue;
pos1 = 0;
last_pos1_changed_time = DateTime.MinValue;
last_pos1 = 0;
pos2_changed_time = DateTime.MinValue;
pos2 = 0;
last_pos2_changed_time = DateTime.MinValue;
last_pos2 = 0;
}
}
///
/// 正反转 grid数据 缓存区
///
class SGrid
{
public const int GRID_MAX_SIZE = 1000;
int size;
public int[][] data = new int[2][];//data[0]=forword, data[1]=backward
public SGrid()
{
//清空所有数据
SetSize(GRID_MAX_SIZE);
}
public void SetSize(int size)
{
this.size = size;
data[0] = new int[size];
data[1] = new int[size];
Clear();
}
public void Clear()
{
//清空所有数据
for (int i = 0; i < size; i++)
{
data[0][i] = Misc.MyBase.NULL_VALUE;
data[1][i] = Misc.MyBase.NULL_VALUE;
}
}
}
}