using System; using System.Collections.Generic; using System.Linq; using System.Text; using FlyADBase; namespace FLY.Simulation.Flyad7 { //public interface ISimDrive //{ // MOTORTYPE MotorType{get;set;} // bool IsMaxLimit{get;} // bool IsMinLimit { get; } // bool IsOrg { get; } // int MaxPos { get; } // int MinPos { get; } // double Mmpp { get; } // UInt32 AccTime { get; set; } // UInt32 DecTime { get; set; } // double Velocity { get; set; } // int Pos { get; set; } // int Speed { get; } // SimDrive_STATE State { get; } // void QuickRunto(int pos); // void Forw(); // void Backw(); // void Stop(); // void OnPoll(DateTime now); //} public enum SimDrive_STATE { STOPPING, STOP_BY_LIMIT, RUNNING } public class SimDrive { public MOTORTYPE MotorType { get; set; } = MOTORTYPE.VF0; /// /// 当前正向限位 /// public bool IsMaxLimit { get { if (PhysicalPos >= MaxPos) { return true; } return false; } } /// /// 当前反向限位 /// public bool IsMinLimit { get { if (PhysicalPos <= MinPos) { return true; } return false; } } /// /// 归0信号灯亮 /// public bool IsOrg { get { if (PhysicalPos <= OrgPos) return true; else return false; } } /// /// 最大脉冲,这个是内部位置 /// public int MaxPos { get; set; } = 8000; /// /// 最小脉冲, 这个是内部位置 /// public int MinPos { get; set; } = -100; public int OrgPos { get; set; } = 50; /// /// 目标速度 脉冲/s /// public double Velocity { get; set; } = 1000; /// /// 启动速度 /// public double SVelocity { get; set; } = 50; /// /// 加速时间 ms /// public UInt32 AccTime { get; set; } /// /// 减速时间 ms /// public UInt32 DecTime { get; set; } /// /// 当前脉冲 /// double m_currpos => m_physicalPos + m_offset + PosOffset; double m_physicalPos = 3200; /// /// 归0信号偏移 /// int m_offset; public int CurrPos=> (int)m_currpos; public void Reset() { m_offset = -PhysicalPos; } public int PhysicalPos => (int)m_physicalPos; /// /// /// public int PosOffset { get; set; } /// /// 当前 脉冲/s /// public double CurrSpeed { get; private set; } public enum STATE { STOPPING, STOP_BY_LIMIT, RUNNING } public STATE state = STATE.STOPPING; public enum ORDER { IDLE, STOP, FORW, BACKW, /// /// 超快速,无视加速时间 /// QUICK_RUNTO, /// /// 运行到 /// RUNTO, } public ORDER order = ORDER.IDLE; ORDER runto_order_sub; public SimDrive() { } int runto_target_pos; public void QuickRunto(int pos) { order = ORDER.QUICK_RUNTO; state = STATE.RUNNING; runto_target_pos = pos; } public void Runto(int pos) { order = ORDER.RUNTO; state = STATE.RUNNING; runto_target_pos = pos; if (runto_target_pos > CurrPos) { runto_order_sub = ORDER.FORW; } else if (runto_target_pos < CurrPos) { runto_order_sub = ORDER.BACKW; } else { runto_order_sub = ORDER.STOP; } } public void Forw() { order = ORDER.FORW; state = STATE.RUNNING; } public void Backw() { order = ORDER.BACKW; state = STATE.RUNNING; } public void Stop() { order = ORDER.STOP; state = STATE.RUNNING; } void calSpeed_forw(TimeSpan ts) { if (CurrSpeed < Velocity) { double acc = (Velocity - SVelocity) / (AccTime / 1000.0); CurrSpeed += acc * ts.TotalSeconds; if (CurrSpeed < SVelocity) CurrSpeed = SVelocity; else if (CurrSpeed > Velocity) CurrSpeed = Velocity; } } void calSpeed_backw(TimeSpan ts) { if (CurrSpeed > -Velocity) { double acc = (Velocity - SVelocity) / (AccTime / 1000.0); CurrSpeed -= acc * ts.TotalSeconds; if (CurrSpeed > -SVelocity) CurrSpeed = -SVelocity; else if (CurrSpeed < -Velocity) CurrSpeed = -Velocity; } } void calSpeed_stop(TimeSpan ts) { double dec = (Velocity - SVelocity) / (DecTime / 1000.0); if (CurrSpeed > 0) { CurrSpeed -= dec * ts.TotalSeconds; if (CurrSpeed < SVelocity) CurrSpeed = 0; } else { CurrSpeed += dec * ts.TotalSeconds; if (CurrSpeed > -SVelocity) CurrSpeed = 0; } } void OnPoll_Order(TimeSpan ts) { switch (order) { case ORDER.QUICK_RUNTO: { //不允许走过了 double target_speed = (runto_target_pos - m_currpos) / ts.TotalSeconds; CurrSpeed = target_speed; }break; case ORDER.RUNTO: { switch (runto_order_sub) { case ORDER.FORW: { calSpeed_forw(ts); double currpos = m_currpos + CurrSpeed * ts.TotalSeconds; if (currpos >= runto_target_pos) { runto_order_sub = ORDER.STOP; if (MotorType == MOTORTYPE.SERVO) { CurrSpeed = (runto_target_pos - m_currpos)/ ts.TotalSeconds; } } } break; case ORDER.BACKW: { calSpeed_backw(ts); double currpos = m_currpos + CurrSpeed * ts.TotalSeconds; if (currpos <= runto_target_pos) { runto_order_sub = ORDER.STOP; if (MotorType == MOTORTYPE.SERVO) { CurrSpeed = (runto_target_pos - m_currpos) / ts.TotalSeconds; } } } break; case ORDER.STOP: if (MotorType == MOTORTYPE.SERVO) { CurrSpeed = 0; } else { calSpeed_stop(ts); } break; } }break; case ORDER.STOP: if (MotorType == MOTORTYPE.SERVO) { CurrSpeed = 0; } else { calSpeed_stop(ts); } break; case ORDER.FORW: { calSpeed_forw(ts); } break; case ORDER.BACKW: { calSpeed_backw(ts); } break; } if(CurrSpeed!=0) { state = STATE.RUNNING; double physicalPos = m_physicalPos + CurrSpeed * ts.TotalSeconds; if ((CurrSpeed > 0) && (physicalPos >= MaxPos)) { //限位了 m_physicalPos = MaxPos; CurrSpeed = 0; state = STATE.STOP_BY_LIMIT; order = ORDER.IDLE; } else if ((CurrSpeed < 0) && (physicalPos <= MinPos)) { CurrSpeed = 0; m_physicalPos = MinPos; state = STATE.STOP_BY_LIMIT; order = ORDER.IDLE; } else { m_physicalPos = physicalPos; } } else { state = STATE.STOPPING; order = ORDER.IDLE; } } DateTime dtLast = DateTime.MinValue; public void OnPoll(DateTime now) { DateTime dt = now; if (dtLast != DateTime.MinValue) { TimeSpan ts = dt - dtLast; OnPoll_Order(ts); } dtLast = dt; } } public class OrderMan { public delegate void FinishEventHandler(bool isNormalStop); public event FinishEventHandler FinishEvent; public Order_Runto order_runto = new Order_Runto(); public Order_Stop order_stop = new Order_Stop(); public Order_Org order_org = new Order_Org(); public Order_Forward order_forw = new Order_Forward(); public Order_Backward order_backw = new Order_Backward(); public Order_Sync order_sync = new Order_Sync(); public Order order; public void Init(FLYAD7 flyad, SimDrive simDrive) { order_runto.Init(flyad, simDrive); order_stop.Init(flyad, simDrive); order_org.Init(flyad, simDrive); order_forw.Init(flyad, simDrive); order_backw.Init(flyad, simDrive); order_sync.Init(flyad, simDrive); } public void Stop() { order = order_stop; order.Start(); } public void Org() { order = order_org; order.Start(); } public void Forw() { order = order_forw; order.Start(); } public void Backw() { order = order_backw; order.Start(); } public void Runto(int dest) { order_runto.destpos = dest; order = order_runto; order.Start(); } public void Sync() { order = order_sync; order.Start(); } public void OnPoll() { if (order != null) { Order.STATE state = order.OnPoll(); if (state != Order.STATE.RUNNING) { if (FinishEvent != null) FinishEvent((state == Order.STATE.STOP)); order = null; } } } } public abstract class Order { public enum STATE { INIT, RUNNING, STOP, STOP_BY_LIMIT } public STATE State = STATE.INIT; public virtual void Start() { State = STATE.RUNNING; } public virtual STATE OnPoll() { State = STATE.STOP; return State; } public virtual void Init(FLYAD7 flyad, SimDrive simDrive) { mflyad7 = flyad; mSimDrive = simDrive; } protected FLYAD7 mflyad7; protected SimDrive mSimDrive; } public class Order_Runto : Order { public int destpos=0; public double Velocity; public override void Start() { mflyad7.mPosGrid.Start(); base.Start(); mSimDrive.Velocity = Velocity; mSimDrive.Runto(destpos); } public override STATE OnPoll() { switch (mSimDrive.state) { case SimDrive.STATE.STOPPING: { mflyad7.mPosGrid.End(); State = STATE.STOP; } break; case SimDrive.STATE.STOP_BY_LIMIT: { State = STATE.STOP_BY_LIMIT; } break; } return State; } } public class Order_Forward : Order { public double Velocity; public override void Start() { State = STATE.RUNNING; mSimDrive.Velocity = Velocity; mSimDrive.Forw(); } public override STATE OnPoll() { switch (mSimDrive.state) { case SimDrive.STATE.STOPPING: State = STATE.STOP; break; case SimDrive.STATE.STOP_BY_LIMIT: State = STATE.STOP_BY_LIMIT; break; } return State; } } public class Order_Backward : Order_Forward { public override void Start() { State = STATE.RUNNING; mSimDrive.Velocity = Velocity; mSimDrive.Backw(); } } public class Order_Org : Order { private int order_adv_state = 0; public double Velocity1; public double Velocity2; public override void Start() { State = STATE.RUNNING; order_adv_state = 0; } public override STATE OnPoll() { switch (order_adv_state) { case 0: if (!mSimDrive.IsOrg) { mSimDrive.Velocity = Velocity1; mSimDrive.Backw(); } order_adv_state = 1; break; case 1: if (mSimDrive.IsOrg) { mSimDrive.Stop(); order_adv_state = 2; } break; case 2: if (mSimDrive.state != SimDrive.STATE.RUNNING) { mSimDrive.Velocity = Velocity2; mSimDrive.Forw(); order_adv_state = 3; } break; case 3: if (!mSimDrive.IsOrg) { mSimDrive.Stop(); order_adv_state = 4; } break; case 4: if (mSimDrive.state != SimDrive.STATE.RUNNING) { mSimDrive.Reset(); //归0完成 State = STATE.STOP; } break; } return State; } } public class Order_Stop : Order_Forward { public override void Start() { State = STATE.RUNNING; mSimDrive.Stop(); } } public class Order_Sync : Order { public List mSyncOrderList; public override STATE OnPoll() { if (mSyncOrderList.Count() > 0) { ASyncOrder o = mSyncOrderList.First(); if (o.State == STATE.INIT) { o.Init(mflyad7, mSimDrive); o.Start(); if (CurrSyncOrderChangedEvent != null) { CurrSyncOrderChangedEvent(this); } } o.OnPoll(); if (mflyad7.Position <= -500) { } if (o.State != STATE.RUNNING) { //完成一个 mSyncOrderList.RemoveAt(0); } } return STATE.RUNNING; } public override string ToString() { if (mSyncOrderList.Count > 0) return "Sync (" + mSyncOrderList.Count.ToString()+") " + mSyncOrderList.First().ToString(); else return "Sync (0)"; } public event Action CurrSyncOrderChangedEvent; } public abstract class ASyncOrder : Order { public Int32 marker; public override void Start() { base.Start(); mflyad7.Marker = marker; } } public class SyncOrder_RunAtLC : ASyncOrder { public int pos2_begin; public int pos2_end; public int pos1lc_end; public bool hasDataGrid; private int pos1lc_begin; private double p; public override void Start() { base.Start(); pos1lc_begin = mflyad7.Position + mflyad7.Pos1LCShift; if (hasDataGrid) mflyad7.mPosGrid.Start(); p = ((double)(pos1lc_end - pos1lc_begin)) / (pos2_end - pos2_begin); } public override STATE OnPoll() { if (mflyad7.Position2 < pos2_begin) { } else if(mflyad7.Position2 <= pos2_end) { int pos = (int)((mflyad7.Position2 - pos2_begin) * p)+ (pos1lc_begin - mflyad7.Pos1LCShift); mSimDrive.QuickRunto(pos); } else { State = STATE.STOP; if (hasDataGrid) mflyad7.mPosGrid.End(); } return State; } public override string ToString() { return "RunAtLC (" + pos2_begin.ToString() + "," + pos2_end.ToString() + ") pos1lc=" + pos1lc_end.ToString() + "|" + marker.ToString(); } } public class SyncOrder_Origin : ASyncOrder { private int order_adv_state = 0; public override void Start() { base.Start(); order_adv_state = 0; } public override STATE OnPoll() { switch (order_adv_state) { case 0: if (!mSimDrive.IsOrg) mSimDrive.Backw(); order_adv_state = 1; break; case 1: if (mSimDrive.IsOrg) { mSimDrive.Stop(); order_adv_state = 2; } break; case 2: if (mSimDrive.state != SimDrive.STATE.RUNNING) { mSimDrive.Forw(); order_adv_state = 3; } break; case 3: if (!mSimDrive.IsOrg) { mSimDrive.Stop(); order_adv_state = 4; } break; case 4: if (mSimDrive.state != SimDrive.STATE.RUNNING) { mSimDrive.Reset(); //归0完成 State = STATE.STOP; } break; } return State; } public override string ToString() { return "Origin |" + marker.ToString(); } } public class SyncOrder_RunTo : ASyncOrder { public int pos1; public UInt32 velocity; public bool hasDataGrid; public override void Start() { mSimDrive.Velocity = velocity; mSimDrive.Runto(pos1); base.Start(); if (hasDataGrid) mflyad7.mPosGrid.Start(); } public override STATE OnPoll() { if (mSimDrive.state != SimDrive.STATE.RUNNING) { if (hasDataGrid) mflyad7.mPosGrid.End(); State = STATE.STOP; } return State; } public override string ToString() { return "RunTo pos1=" + pos1.ToString() + "|" + marker.ToString(); } } public class SyncOrder_RunToLC : ASyncOrder { public int pos1lc; public UInt32 velocity; public bool hasDataGrid; public override void Start() { mSimDrive.Velocity = velocity; mSimDrive.Runto(pos1lc - mflyad7.Pos1LCShift); base.Start(); if (hasDataGrid) mflyad7.mPosGrid.Start(); } public override STATE OnPoll() { if (mSimDrive.state != SimDrive.STATE.RUNNING) { if (hasDataGrid) mflyad7.mPosGrid.End(); State = STATE.STOP; } return State; } public override string ToString() { return "RunToLC pos1lc=" + pos1lc.ToString() + " pos1lcshift="+ mflyad7.Pos1LCShift.ToString()+" |" + marker.ToString(); } } public class SyncOrder_Wait : ASyncOrder { public int ms; DateTime dtstart; public override void Start() { dtstart = mflyad7.Now; base.Start(); } public override STATE OnPoll() { if ((mflyad7.Now - dtstart).TotalMilliseconds >= ms) { State = STATE.STOP; } return State; } public override string ToString() { return "Wait ms=" + ms.ToString() + "|" + marker.ToString(); } } }