| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558 | using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Timers;using Aitex.Core.Util;using MECF.Framework.Simulator.Core.Driver;using MECF.Framework.Simulator.Core.SubstrateTrackings;namespace MECF.Framework.Simulator.Core.Robots{     public class BrooksMag7RobotSimulator : RobotSimulator    {        protected Random _rd = new Random();        public bool Failed { get; set; }        public string ResultValue { get; set; }        public override Dictionary<string, double> MoveTimes        {            get { return moveTimes; }            set { moveTimes = value; }        }        public override ReadOnlyCollection<string> Arms        {            get { return arms; }        }        //private static string source = "BrooksMag7";        private static string msgDone = "_RDY";        private static string msgError = "_ERR";        private readonly string armAPan1 = "VTM.ArmA.Left";        private readonly string armAPan2 = "VTM.ArmA.Right";        private readonly string armBPan1 = "VTM.ArmB.Left";        private readonly string armBPan2 = "VTM.ArmB.Right";        private System.Timers.Timer timer;         private string currentStation;        private string newLocation;        private string currentArm;        private string newArm = "";        private string lastMsg;        private string armTargetMaterialMap;        //jms changed from "picking" for CR#7576.        private Dictionary<string, double> moveTimes;        private ReadOnlyCollection<string> arms;         //private bool lidClosed;         public BrooksMag7RobotSimulator( ):base(1102, 0, "\r", ' ')        {             List<string> armsList = new List<string>();            armsList.Add(armAPan1);            armsList.Add(armAPan2);            armsList.Add(armBPan1);            armsList.Add(armBPan2);            arms = new ReadOnlyCollection<string>(armsList);            //WaferTrack.Instance.UpdateMaterialMap(armAPan1, WaferTrackStateEnum.Unoccupied);            //WaferTrack.Instance.UpdateMaterialMap(armAPan2, WaferTrackStateEnum.Unoccupied);            //WaferTrack.Instance.UpdateMaterialMap(armBPan1, WaferTrackStateEnum.Unoccupied);            //WaferTrack.Instance.UpdateMaterialMap(armBPan2, WaferTrackStateEnum.Unoccupied);             // create the message handling dictionary            AddCommandHandler("HOME",  HandleHome);            AddCommandHandler("PICK",  HandlePick);            AddCommandHandler("PLACE",  HandlePlace);            AddCommandHandler("GOTO",  HandleGoto);            AddCommandHandler("SWAP",  HandleExchange);            AddCommandHandler("RQ",  HandleRequest);            AddCommandHandler("Unknown",  HandleUnknown);            timer = new System.Timers.Timer();            timer.Enabled = false;            timer.AutoReset = false;            timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);            // Default move times based on Brooks spreadsheet            moveTimes = new Dictionary<string, double>();            moveTimes["PickPlace"] = 2.8;            moveTimes["Move90Degrees"] = 1.69;            moveTimes["Move180Degrees"] = 2.11;            moveTimes["HeightAdjust"] = 0.9;            moveTimes["ExtendRetract"] = 1.3;            moveTimes["WaferFactor"] = 1.0;            moveTimes["SwapAtPM"] = 7.3;            // Original default times based on Brooks log files            //moveTimes["PickPlace"] = 3.2;            //moveTimes["Move90Degrees"] = 1.5;            //moveTimes["Move180Degrees"] = 1.9;            //moveTimes["HeightAdjust"] = 0.9;            //moveTimes["ExtendRetract"] = 1.2;            //moveTimes["WaferFactor"] = 1.15;            currentArm = "A";            currentStation = "Unknown";             //lidClosed = true;                     }        public void HomeAll()        {            string msg = "HOME ALL";            HandleHome(msg);        }        public void Pick()        {            string msg = "PICK 1 SLOT 1 ARM A";            HandlePick(msg);        }        public void Place()        {            string msg = "PLACE STN 2 ARM A";            HandlePlace(msg);        }        internal void HandleHome(string msg)        {                 if (ErrorMessage == "Home Failed")                {                    HandleError(ErrorMessage);                    return;                }                string[] cmdComponents = msg.Split(_msgDelimiter);                if (cmdComponents.Length != 2)                {                    // return an error                    HandleError("Invalid homing command (arguments)");                    return;                }                HandleMove(RobotStateEnum.Homing, cmdComponents);         }         internal void HandlePick(string msg)        {                 msg = msg.Trim();                if (ErrorMessage == "Pick Failed")                {                    HandleError(ErrorMessage);                    return;                }                string[] cmdComponents = msg.Split(_msgDelimiter);                if (cmdComponents.Length != 6 && cmdComponents.Length != 8 && cmdComponents.Length != 10)                {                    //Have to check for 6 parameters (double pick) or 8 parameters (single pick)                    // return an error                                         HandleError("Invalid pick command (arguments)");                    return;                }                RobotStateEnum rs = RobotStateEnum.Picking;                if (cmdComponents.Length > 6 && cmdComponents[6] == "ENRT")                    rs = RobotStateEnum.Extending;                else if (cmdComponents.Length > 6 && cmdComponents[6] == "STRT")                    rs = RobotStateEnum.Retracting;                lastMsg = msg;                armTargetMaterialMap = "pick";      //jms changed to string for CR#7576.                HandleMove(rs, cmdComponents);         }         internal void HandlePlace(string msg)        {                 msg = msg.Trim();                if (ErrorMessage == "Place Failed")                {                    HandleError(ErrorMessage);                    return;                }                string[] cmdComponents = msg.Split(_msgDelimiter);                if (cmdComponents.Length != 6 && cmdComponents.Length != 8 && cmdComponents.Length != 10)                {                    //Have to check for 6 parameters (double pick) or 8 parameters (single pick)                    // return an error                   // Log.WriteIfEnabled(LogCategory.Error, source, "Unrecognized place command: " + msg);                    HandleError("Invalid place command (arguments)");                    return;                }                RobotStateEnum rs = RobotStateEnum.Placing;                if (cmdComponents.Length > 6 && cmdComponents[6] == "ENRT")                    rs = RobotStateEnum.Extending;                else if (cmdComponents.Length > 6 && cmdComponents[6] == "STRT")                    rs = RobotStateEnum.Retracting;                lastMsg = msg;                armTargetMaterialMap = "place";      //jms changed to string for CR#7576.                HandleMove(rs, cmdComponents);          }         internal void HandleExchange(string msg)        {            //jms enabled for CR#7576.                 if (ErrorMessage == "Swap Failed" || ErrorMessage == "Place Failed" || ErrorMessage == "Pick Failed")                {                    HandleError(ErrorMessage);                    return;                }                string[] cmdComponents = msg.Split(_msgDelimiter);                if (cmdComponents.Length != 4)                {                    //Log.WriteIfEnabled(LogCategory.Error, source, "Unrecognized swap command: " + msg);                    HandleError("Invalid swap command (arguments)");                    return;                }                lastMsg = msg;                armTargetMaterialMap = "swap";                //Log.WriteIfEnabled(LogCategory.Error, source, "HandleExchange msg: " + msg);                HandleMove(RobotStateEnum.Exchanging, cmdComponents);         }         internal void HandleRequest(string msg)        {            string[] components = msg.Split(_msgDelimiter);            string reply = components[1];            if (components[1] == "WAFER" && components[2] == "PRESENT")                reply += " " + components[2] + GetArmStates();            else if (components[1] == "ERRMSG")                reply = LookupError(components[2]);            //Log.WriteIfEnabled(LogCategory.Debug, source, "Writing message " + reply);            OnWriteMessage(reply);            //Log.WriteIfEnabled(LogCategory.Debug, source, "Writing message _RDY");            OnWriteMessage(msgDone);        }         internal void HandleUnknown(string msg)        {            //Log.WriteIfEnabled(LogCategory.Debug, source, "Command " + msg + "complete. Writing message _RDY");            OnWriteMessage(msgDone);        }         internal void HandleGoto(string msg)        {                 string[] cmdComponents = msg.Split(_msgDelimiter);                if (cmdComponents.Length != 11)                {                    // return an error                    HandleError("Invalid move command (arguments)");                    return;                }                HandleMove(RobotStateEnum.Approaching, cmdComponents);          }        /// <summary>        /// Simulates moves for move messages        /// </summary>        /// <param name="action">Action to perform (pick, home, place, goto)</param>        /// <param name="cmdComponents">Components</param>        /// <returns>True if successful, otherwise false.</returns>        private bool HandleMove(RobotStateEnum action, string[] cmdComponents)        {                 // if the robot is moving, send an error message                if (robotStateArgs.State != RobotStateEnum.Idle &&                    (action == RobotStateEnum.Homing && robotStateArgs.State != RobotStateEnum.Errored))  // allow homes when in error, but not other moves                {                    // return an error                    HandleError("Already moving");                    return false;                }                newLocation = "Unknown";                switch (action)                {                    case RobotStateEnum.Picking:                    case RobotStateEnum.Placing:                    case RobotStateEnum.Approaching:                    case RobotStateEnum.Extending:                    case RobotStateEnum.Retracting:                    case RobotStateEnum.Exchanging:          //jms added exchanging for CR#7576.                    //Log.WriteIfEnabled( LogCategory.Information, source, "Robot {0}: {1} {2} {3} {4}", action, cmdComponents[2], cmdComponents[3], cmdComponents[4], cmdComponents[5] );                        //armIndex = Array.IndexOf(cmdComponents, "ARM");                         //armIndex++;                        //newArm = cmdComponents[armIndex];   //指定动作机械臂                        //int index = action == RobotStateEnum.Approaching ? 2 : 1;                        //newLocation = GetLocation(cmdComponents[index]);                        //if (RobotStateEnum.Approaching == action)                        //{                        //    //Log.WriteIfEnabled(LogCategory.Debug, source, string.Format("Moving from {0} to {1}", currentStation, newLocation));                        //}                        //int slotIndex = Array.IndexOf(cmdComponents, "SLOT" ) + 1;                        //Log.WriteIfEnabled(LogCategory.Information, source, string.Format("VTM robot {0} {1} slot {2} arm {3}",action, newLocation, cmdComponents[slotIndex], newArm));                        //bool state;                        //if (cmdComponents[armIndex] == "A")                        //    state = (WaferTrack.Instance.IsOccupied(armAPan1) || WaferTrack.Instance.IsOccupied(armAPan2));                        //else                        //    state = (WaferTrack.Instance.IsOccupied(armBPan1) || WaferTrack.Instance.IsOccupied(armBPan2));                        //if (action == RobotStateEnum.Picking && state)                        //{                        //    HandleError("Already holding wafer");                        //    return false;                        //}                        //else if (action == RobotStateEnum.Placing && !state)                        //{                        //    HandleError("Not holding wafer");                        //    return false;                        //}                        break;                    default:                        //Log.WriteIfEnabled(LogCategory.Information, source, string.Format("VTM robot {0}", action));                        break;                }                //jms added swap check for CR#7576.                if (ErrorMessage != "Pick Failed" && ErrorMessage != "Place Failed" && ErrorMessage != "Home Failed" &&                    ErrorMessage != "Swap Failed" && !string.IsNullOrEmpty(ErrorMessage))                {                    HandleError(ErrorMessage);                    return false;                }                //SetRobotState(action);                 // set state to what the robot is now doing                double delay = GetMoveTime(action);                //Log.WriteIfEnabled(LogCategory.Debug, source, "Move delay in seconds: " + delay.ToString());                timer.Interval = delay * 1000;                timer.Enabled = true;             return true;          }        private static string GetLocation(string specifier)        {            switch (specifier)            {                case "1":                    return "LL1";                case "2":                    return "LL2";                case "3":                    return "PM1";                case "4":                    return "PM2";                case "5":                    return "PM3";            }            return "Unknown";        }        private double GetMoveTime(RobotStateEnum action)        {            //if (WaferTrack.Instance.RealisticMode == false)            //    return 0.0;            double rotationTime = 0;            double zMoveTime = 0;            if (newLocation != currentStation)            {                if (currentStation == "LL1" || currentStation == "LL2")                    rotationTime = newLocation == "PM2" ? moveTimes["Move180Degrees"] : moveTimes["Move90Degrees"];                else                    rotationTime = currentStation == "PM2" ? moveTimes["Move180Degrees"] : moveTimes["Move90Degrees"];                double factor = 1.0;                if (WaferTrack.Instance.IsOccupied(armAPan1) || WaferTrack.Instance.IsOccupied(armAPan2) ||                    WaferTrack.Instance.IsOccupied(armBPan1) || WaferTrack.Instance.IsOccupied(armBPan2))                {                    factor = moveTimes["WaferFactor"];                }                rotationTime *= factor;            }            else if (newArm != currentArm)                zMoveTime = moveTimes["HeightAdjust"];            switch (action)            {                case RobotStateEnum.Approaching:                    if (newLocation == currentStation)                        return moveTimes["HeightAdjust"];                    return rotationTime;                case RobotStateEnum.Extending:                case RobotStateEnum.Retracting:                    return moveTimes["ExtendRetract"] + rotationTime + zMoveTime;                case RobotStateEnum.Picking:                    return moveTimes["PickPlace"] + zMoveTime;                case RobotStateEnum.Placing:                    if (newLocation.StartsWith("PM"))                        return moveTimes["PickPlace"] + zMoveTime;                    else                        return moveTimes["ExtendRetract"] + rotationTime + zMoveTime;                case RobotStateEnum.Exchanging:                    return moveTimes["SwapAtPM"];                default:                    return moveTimes["Move90Degrees"];            }        }        /// <summary>        /// Method for returning error messages        /// </summary>        /// <param name="msg">Error message to return</param>        private void HandleError(string msg)        {            string errorCode = string.Format("0x{0}", lastError.ToString("x8"));            lastError++;            errorLookup[errorCode] = msg;            //Log.WriteIfEnabled(LogCategory.Debug, source, "Writing error message " + msg);            OnWriteMessage(msgError + " " + errorCode);            //Log.WriteIfEnabled(LogCategory.Debug, source, "Command complete. Writing message _RDY");            OnWriteMessage(msgDone);        }        /// <summary>        /// Set the state of the arm based on the message        /// </summary>        /// <param name="msg">Message that causes the state to change</param>        /// <param name="state">New state of the arm</param>        private void SetArmState(string msg, string pickPlaceSwap)        {                //string[] components = msg.Split(_msgDelimiter);                ////jms added swap check (length == 4) for CR#7576.                //if (components.Length != 6 && components.Length != 8 && components.Length != 10 && components.Length != 4)                //    return;                //int slotIndex = Array.IndexOf(components, "SLOT" ) + 1;                //bool isLL = newLocation.StartsWith("LL");                //string target1 = string.Format("{0}.{1}{2}", newLocation, isLL ? "Ch2" : "Ch1", isLL ? ".Slot" + components[slotIndex] : string.Empty);                //string target2 = string.Format("{0}.{1}{2}", newLocation, isLL ? "Ch1" : "Ch2", isLL ? ".Slot" + components[slotIndex] : string.Empty);                //string arm = "VTM.Arm" + components[armIndex];                ////jms changed pickPlaceSwap to string for CR#7576.                //if (pickPlaceSwap == "pick")                //{                //    WaferTrack.Instance.UpdateMaterialMap(arm + ".Left", WaferTrack.Instance.GetLocationState(target1));                //    WaferTrack.Instance.UpdateMaterialMap(arm + ".Right", WaferTrack.Instance.GetLocationState(target2));                //    WaferTrack.Instance.UpdateMaterialMap(target1, WaferTrackStateEnum.Unoccupied);                //    WaferTrack.Instance.UpdateMaterialMap(target2, WaferTrackStateEnum.Unoccupied);                //}                //else if (pickPlaceSwap == "place")                //{                //    WaferTrack.Instance.UpdateMaterialMap(target1, WaferTrack.Instance.GetLocationState(arm + ".Left"));                //    WaferTrack.Instance.UpdateMaterialMap(target2, WaferTrack.Instance.GetLocationState(arm + ".Right"));                //    WaferTrack.Instance.UpdateMaterialMap(arm + ".Left", WaferTrackStateEnum.Unoccupied);                //    WaferTrack.Instance.UpdateMaterialMap(arm + ".Right", WaferTrackStateEnum.Unoccupied);                //}                ////jms added swap check for CR#7576.                //else if (pickPlaceSwap == "swap")                //{                //    if (components[armIndex] == "A")                //    {                //        WaferTrack.Instance.UpdateWaferTrackState(armAPan1, WaferTrack.Instance.GetLocationState(target1));                //        WaferTrack.Instance.UpdateMaterialMap(armAPan2, WaferTrack.Instance.GetLocationState(target2));                //        WaferTrack.Instance.UpdateMaterialMap(target1, WaferTrack.Instance.GetLocationState(armBPan1));                //        WaferTrack.Instance.UpdateMaterialMap(target2, WaferTrack.Instance.GetLocationState(armBPan2));                //        WaferTrack.Instance.UpdateMaterialMap(armBPan1, WaferTrackStateEnum.Unoccupied);                //        WaferTrack.Instance.UpdateMaterialMap(armBPan2, WaferTrackStateEnum.Unoccupied);                //    }                //    else                //    {                //        WaferTrack.Instance.UpdateMaterialMap(armBPan1, WaferTrack.Instance.GetLocationState(target1));                //        WaferTrack.Instance.UpdateMaterialMap(armBPan2, WaferTrack.Instance.GetLocationState(target2));                //        WaferTrack.Instance.UpdateMaterialMap(target1, WaferTrack.Instance.GetLocationState(armAPan1));                //        WaferTrack.Instance.UpdateMaterialMap(target2, WaferTrack.Instance.GetLocationState(armAPan2));                //        WaferTrack.Instance.UpdateMaterialMap(armAPan1, WaferTrackStateEnum.Unoccupied);                //        WaferTrack.Instance.UpdateMaterialMap(armAPan2, WaferTrackStateEnum.Unoccupied);                //    }                //}        }        /// <summary>        /// Get the arm state string returned in WAFER PRESENT request message        /// </summary>        /// <returns>Arm state string</returns>        private string GetArmStates()        {            return " N N";                 //string states = " A LEFT " + (WaferTrack.Instance.IsOccupied(armAPan1) ? "Y" : "N");                //states += " RIGHT " + (WaferTrack.Instance.IsOccupied(armAPan2) ? "Y" : "N");                //states += " B LEFT " + (WaferTrack.Instance.IsOccupied(armBPan1) ? "Y" : "N");                //states += " RIGHT " + (WaferTrack.Instance.IsOccupied(armBPan2) ? "Y" : "N");                //return states;         }        /// <summary>        /// Timer used for simulating realistic mode        /// </summary>        /// <param name="sender">Who sent it</param>        /// <param name="e">Arguments</param>        private void timer_Elapsed(object sender, ElapsedEventArgs e)        {                 //Log.WriteIfEnabled(LogCategory.Debug, source, string.Format("Move complete to station {0}. Writing message _RDY", newLocation));                currentStation = newLocation;                currentArm = newArm;                //jms added exchanging check for CR#7576.                if (robotStateArgs.State == RobotStateEnum.Picking || robotStateArgs.State == RobotStateEnum.Placing ||                          robotStateArgs.State == RobotStateEnum.Extending || robotStateArgs.State == RobotStateEnum.Exchanging)                {                    SetArmState(lastMsg, armTargetMaterialMap);                    lastMsg = "";                }                SetRobotState(RobotStateEnum.Idle);                timer.Enabled = false;                OnWriteMessage(msgDone);         }     }}
 |