BrooksMag7RobotSimulator.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. using System.Timers;
  9. using Aitex.Core.Util;
  10. using MECF.Framework.Simulator.Core.Driver;
  11. using MECF.Framework.Simulator.Core.SubstrateTrackings;
  12. namespace MECF.Framework.Simulator.Core.Robots
  13. {
  14. public class BrooksMag7RobotSimulator : RobotSimulator
  15. {
  16. protected Random _rd = new Random();
  17. public bool Failed { get; set; }
  18. public string ResultValue { get; set; }
  19. public override Dictionary<string, double> MoveTimes
  20. {
  21. get { return moveTimes; }
  22. set { moveTimes = value; }
  23. }
  24. public override ReadOnlyCollection<string> Arms
  25. {
  26. get { return arms; }
  27. }
  28. //private static string source = "BrooksMag7";
  29. private static string msgDone = "_RDY";
  30. private static string msgError = "_ERR";
  31. private readonly string armAPan1 = "VTM.ArmA.Left";
  32. private readonly string armAPan2 = "VTM.ArmA.Right";
  33. private readonly string armBPan1 = "VTM.ArmB.Left";
  34. private readonly string armBPan2 = "VTM.ArmB.Right";
  35. private System.Timers.Timer timer;
  36. private string currentStation;
  37. private string newLocation;
  38. private string currentArm;
  39. private string newArm = "";
  40. private string lastMsg;
  41. private string armTargetMaterialMap; //jms changed from "picking" for CR#7576.
  42. private Dictionary<string, double> moveTimes;
  43. private ReadOnlyCollection<string> arms;
  44. //private bool lidClosed;
  45. public BrooksMag7RobotSimulator( ):base(1102, 0, "\r", ' ')
  46. {
  47. List<string> armsList = new List<string>();
  48. armsList.Add(armAPan1);
  49. armsList.Add(armAPan2);
  50. armsList.Add(armBPan1);
  51. armsList.Add(armBPan2);
  52. arms = new ReadOnlyCollection<string>(armsList);
  53. //WaferTrack.Instance.UpdateMaterialMap(armAPan1, WaferTrackStateEnum.Unoccupied);
  54. //WaferTrack.Instance.UpdateMaterialMap(armAPan2, WaferTrackStateEnum.Unoccupied);
  55. //WaferTrack.Instance.UpdateMaterialMap(armBPan1, WaferTrackStateEnum.Unoccupied);
  56. //WaferTrack.Instance.UpdateMaterialMap(armBPan2, WaferTrackStateEnum.Unoccupied);
  57. // create the message handling dictionary
  58. AddCommandHandler("HOME", HandleHome);
  59. AddCommandHandler("PICK", HandlePick);
  60. AddCommandHandler("PLACE", HandlePlace);
  61. AddCommandHandler("GOTO", HandleGoto);
  62. AddCommandHandler("SWAP", HandleExchange);
  63. AddCommandHandler("RQ", HandleRequest);
  64. AddCommandHandler("Unknown", HandleUnknown);
  65. timer = new System.Timers.Timer();
  66. timer.Enabled = false;
  67. timer.AutoReset = false;
  68. timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
  69. // Default move times based on Brooks spreadsheet
  70. moveTimes = new Dictionary<string, double>();
  71. moveTimes["PickPlace"] = 2.8;
  72. moveTimes["Move90Degrees"] = 1.69;
  73. moveTimes["Move180Degrees"] = 2.11;
  74. moveTimes["HeightAdjust"] = 0.9;
  75. moveTimes["ExtendRetract"] = 1.3;
  76. moveTimes["WaferFactor"] = 1.0;
  77. moveTimes["SwapAtPM"] = 7.3;
  78. // Original default times based on Brooks log files
  79. //moveTimes["PickPlace"] = 3.2;
  80. //moveTimes["Move90Degrees"] = 1.5;
  81. //moveTimes["Move180Degrees"] = 1.9;
  82. //moveTimes["HeightAdjust"] = 0.9;
  83. //moveTimes["ExtendRetract"] = 1.2;
  84. //moveTimes["WaferFactor"] = 1.15;
  85. currentArm = "A";
  86. currentStation = "Unknown";
  87. //lidClosed = true;
  88. }
  89. public void HomeAll()
  90. {
  91. string msg = "HOME ALL";
  92. HandleHome(msg);
  93. }
  94. public void Pick()
  95. {
  96. string msg = "PICK 1 SLOT 1 ARM A";
  97. HandlePick(msg);
  98. }
  99. public void Place()
  100. {
  101. string msg = "PLACE STN 2 ARM A";
  102. HandlePlace(msg);
  103. }
  104. internal void HandleHome(string msg)
  105. {
  106. if (ErrorMessage == "Home Failed")
  107. {
  108. HandleError(ErrorMessage);
  109. return;
  110. }
  111. string[] cmdComponents = msg.Split(_msgDelimiter);
  112. if (cmdComponents.Length != 2)
  113. {
  114. // return an error
  115. HandleError("Invalid homing command (arguments)");
  116. return;
  117. }
  118. HandleMove(RobotStateEnum.Homing, cmdComponents);
  119. }
  120. internal void HandlePick(string msg)
  121. {
  122. msg = msg.Trim();
  123. if (ErrorMessage == "Pick Failed")
  124. {
  125. HandleError(ErrorMessage);
  126. return;
  127. }
  128. string[] cmdComponents = msg.Split(_msgDelimiter);
  129. if (cmdComponents.Length != 6 && cmdComponents.Length != 8 && cmdComponents.Length != 10)
  130. {
  131. //Have to check for 6 parameters (double pick) or 8 parameters (single pick)
  132. // return an error
  133. HandleError("Invalid pick command (arguments)");
  134. return;
  135. }
  136. RobotStateEnum rs = RobotStateEnum.Picking;
  137. if (cmdComponents.Length > 6 && cmdComponents[6] == "ENRT")
  138. rs = RobotStateEnum.Extending;
  139. else if (cmdComponents.Length > 6 && cmdComponents[6] == "STRT")
  140. rs = RobotStateEnum.Retracting;
  141. lastMsg = msg;
  142. armTargetMaterialMap = "pick"; //jms changed to string for CR#7576.
  143. HandleMove(rs, cmdComponents);
  144. }
  145. internal void HandlePlace(string msg)
  146. {
  147. msg = msg.Trim();
  148. if (ErrorMessage == "Place Failed")
  149. {
  150. HandleError(ErrorMessage);
  151. return;
  152. }
  153. string[] cmdComponents = msg.Split(_msgDelimiter);
  154. if (cmdComponents.Length != 6 && cmdComponents.Length != 8 && cmdComponents.Length != 10)
  155. {
  156. //Have to check for 6 parameters (double pick) or 8 parameters (single pick)
  157. // return an error
  158. // Log.WriteIfEnabled(LogCategory.Error, source, "Unrecognized place command: " + msg);
  159. HandleError("Invalid place command (arguments)");
  160. return;
  161. }
  162. RobotStateEnum rs = RobotStateEnum.Placing;
  163. if (cmdComponents.Length > 6 && cmdComponents[6] == "ENRT")
  164. rs = RobotStateEnum.Extending;
  165. else if (cmdComponents.Length > 6 && cmdComponents[6] == "STRT")
  166. rs = RobotStateEnum.Retracting;
  167. lastMsg = msg;
  168. armTargetMaterialMap = "place"; //jms changed to string for CR#7576.
  169. HandleMove(rs, cmdComponents);
  170. }
  171. internal void HandleExchange(string msg)
  172. {
  173. //jms enabled for CR#7576.
  174. if (ErrorMessage == "Swap Failed" || ErrorMessage == "Place Failed" || ErrorMessage == "Pick Failed")
  175. {
  176. HandleError(ErrorMessage);
  177. return;
  178. }
  179. string[] cmdComponents = msg.Split(_msgDelimiter);
  180. if (cmdComponents.Length != 4)
  181. {
  182. //Log.WriteIfEnabled(LogCategory.Error, source, "Unrecognized swap command: " + msg);
  183. HandleError("Invalid swap command (arguments)");
  184. return;
  185. }
  186. lastMsg = msg;
  187. armTargetMaterialMap = "swap";
  188. //Log.WriteIfEnabled(LogCategory.Error, source, "HandleExchange msg: " + msg);
  189. HandleMove(RobotStateEnum.Exchanging, cmdComponents);
  190. }
  191. internal void HandleRequest(string msg)
  192. {
  193. string[] components = msg.Split(_msgDelimiter);
  194. string reply = components[1];
  195. if (components[1] == "WAFER" && components[2] == "PRESENT")
  196. reply += " " + components[2] + GetArmStates();
  197. else if (components[1] == "ERRMSG")
  198. reply = LookupError(components[2]);
  199. //Log.WriteIfEnabled(LogCategory.Debug, source, "Writing message " + reply);
  200. OnWriteMessage(reply);
  201. //Log.WriteIfEnabled(LogCategory.Debug, source, "Writing message _RDY");
  202. OnWriteMessage(msgDone);
  203. }
  204. internal void HandleUnknown(string msg)
  205. {
  206. //Log.WriteIfEnabled(LogCategory.Debug, source, "Command " + msg + "complete. Writing message _RDY");
  207. OnWriteMessage(msgDone);
  208. }
  209. internal void HandleGoto(string msg)
  210. {
  211. string[] cmdComponents = msg.Split(_msgDelimiter);
  212. if (cmdComponents.Length != 11)
  213. {
  214. // return an error
  215. HandleError("Invalid move command (arguments)");
  216. return;
  217. }
  218. HandleMove(RobotStateEnum.Approaching, cmdComponents);
  219. }
  220. /// <summary>
  221. /// Simulates moves for move messages
  222. /// </summary>
  223. /// <param name="action">Action to perform (pick, home, place, goto)</param>
  224. /// <param name="cmdComponents">Components</param>
  225. /// <returns>True if successful, otherwise false.</returns>
  226. private bool HandleMove(RobotStateEnum action, string[] cmdComponents)
  227. {
  228. // if the robot is moving, send an error message
  229. if (robotStateArgs.State != RobotStateEnum.Idle &&
  230. (action == RobotStateEnum.Homing && robotStateArgs.State != RobotStateEnum.Errored)) // allow homes when in error, but not other moves
  231. {
  232. // return an error
  233. HandleError("Already moving");
  234. return false;
  235. }
  236. newLocation = "Unknown";
  237. switch (action)
  238. {
  239. case RobotStateEnum.Picking:
  240. case RobotStateEnum.Placing:
  241. case RobotStateEnum.Approaching:
  242. case RobotStateEnum.Extending:
  243. case RobotStateEnum.Retracting:
  244. case RobotStateEnum.Exchanging: //jms added exchanging for CR#7576.
  245. //Log.WriteIfEnabled( LogCategory.Information, source, "Robot {0}: {1} {2} {3} {4}", action, cmdComponents[2], cmdComponents[3], cmdComponents[4], cmdComponents[5] );
  246. //armIndex = Array.IndexOf(cmdComponents, "ARM");
  247. //armIndex++;
  248. //newArm = cmdComponents[armIndex]; //指定动作机械臂
  249. //int index = action == RobotStateEnum.Approaching ? 2 : 1;
  250. //newLocation = GetLocation(cmdComponents[index]);
  251. //if (RobotStateEnum.Approaching == action)
  252. //{
  253. // //Log.WriteIfEnabled(LogCategory.Debug, source, string.Format("Moving from {0} to {1}", currentStation, newLocation));
  254. //}
  255. //int slotIndex = Array.IndexOf(cmdComponents, "SLOT" ) + 1;
  256. //Log.WriteIfEnabled(LogCategory.Information, source, string.Format("VTM robot {0} {1} slot {2} arm {3}",action, newLocation, cmdComponents[slotIndex], newArm));
  257. //bool state;
  258. //if (cmdComponents[armIndex] == "A")
  259. // state = (WaferTrack.Instance.IsOccupied(armAPan1) || WaferTrack.Instance.IsOccupied(armAPan2));
  260. //else
  261. // state = (WaferTrack.Instance.IsOccupied(armBPan1) || WaferTrack.Instance.IsOccupied(armBPan2));
  262. //if (action == RobotStateEnum.Picking && state)
  263. //{
  264. // HandleError("Already holding wafer");
  265. // return false;
  266. //}
  267. //else if (action == RobotStateEnum.Placing && !state)
  268. //{
  269. // HandleError("Not holding wafer");
  270. // return false;
  271. //}
  272. break;
  273. default:
  274. //Log.WriteIfEnabled(LogCategory.Information, source, string.Format("VTM robot {0}", action));
  275. break;
  276. }
  277. //jms added swap check for CR#7576.
  278. if (ErrorMessage != "Pick Failed" && ErrorMessage != "Place Failed" && ErrorMessage != "Home Failed" &&
  279. ErrorMessage != "Swap Failed" && !string.IsNullOrEmpty(ErrorMessage))
  280. {
  281. HandleError(ErrorMessage);
  282. return false;
  283. }
  284. //SetRobotState(action); // set state to what the robot is now doing
  285. double delay = GetMoveTime(action);
  286. //Log.WriteIfEnabled(LogCategory.Debug, source, "Move delay in seconds: " + delay.ToString());
  287. timer.Interval = delay * 1000;
  288. timer.Enabled = true;
  289. return true;
  290. }
  291. private static string GetLocation(string specifier)
  292. {
  293. switch (specifier)
  294. {
  295. case "1":
  296. return "LL1";
  297. case "2":
  298. return "LL2";
  299. case "3":
  300. return "PM1";
  301. case "4":
  302. return "PM2";
  303. case "5":
  304. return "PM3";
  305. }
  306. return "Unknown";
  307. }
  308. private double GetMoveTime(RobotStateEnum action)
  309. {
  310. //if (WaferTrack.Instance.RealisticMode == false)
  311. // return 0.0;
  312. double rotationTime = 0;
  313. double zMoveTime = 0;
  314. if (newLocation != currentStation)
  315. {
  316. if (currentStation == "LL1" || currentStation == "LL2")
  317. rotationTime = newLocation == "PM2" ? moveTimes["Move180Degrees"] : moveTimes["Move90Degrees"];
  318. else
  319. rotationTime = currentStation == "PM2" ? moveTimes["Move180Degrees"] : moveTimes["Move90Degrees"];
  320. double factor = 1.0;
  321. if (WaferTrack.Instance.IsOccupied(armAPan1) || WaferTrack.Instance.IsOccupied(armAPan2) ||
  322. WaferTrack.Instance.IsOccupied(armBPan1) || WaferTrack.Instance.IsOccupied(armBPan2))
  323. {
  324. factor = moveTimes["WaferFactor"];
  325. }
  326. rotationTime *= factor;
  327. }
  328. else if (newArm != currentArm)
  329. zMoveTime = moveTimes["HeightAdjust"];
  330. switch (action)
  331. {
  332. case RobotStateEnum.Approaching:
  333. if (newLocation == currentStation)
  334. return moveTimes["HeightAdjust"];
  335. return rotationTime;
  336. case RobotStateEnum.Extending:
  337. case RobotStateEnum.Retracting:
  338. return moveTimes["ExtendRetract"] + rotationTime + zMoveTime;
  339. case RobotStateEnum.Picking:
  340. return moveTimes["PickPlace"] + zMoveTime;
  341. case RobotStateEnum.Placing:
  342. if (newLocation.StartsWith("PM"))
  343. return moveTimes["PickPlace"] + zMoveTime;
  344. else
  345. return moveTimes["ExtendRetract"] + rotationTime + zMoveTime;
  346. case RobotStateEnum.Exchanging:
  347. return moveTimes["SwapAtPM"];
  348. default:
  349. return moveTimes["Move90Degrees"];
  350. }
  351. }
  352. /// <summary>
  353. /// Method for returning error messages
  354. /// </summary>
  355. /// <param name="msg">Error message to return</param>
  356. private void HandleError(string msg)
  357. {
  358. string errorCode = string.Format("0x{0}", lastError.ToString("x8"));
  359. lastError++;
  360. errorLookup[errorCode] = msg;
  361. //Log.WriteIfEnabled(LogCategory.Debug, source, "Writing error message " + msg);
  362. OnWriteMessage(msgError + " " + errorCode);
  363. //Log.WriteIfEnabled(LogCategory.Debug, source, "Command complete. Writing message _RDY");
  364. OnWriteMessage(msgDone);
  365. }
  366. /// <summary>
  367. /// Set the state of the arm based on the message
  368. /// </summary>
  369. /// <param name="msg">Message that causes the state to change</param>
  370. /// <param name="state">New state of the arm</param>
  371. private void SetArmState(string msg, string pickPlaceSwap)
  372. {
  373. //string[] components = msg.Split(_msgDelimiter);
  374. ////jms added swap check (length == 4) for CR#7576.
  375. //if (components.Length != 6 && components.Length != 8 && components.Length != 10 && components.Length != 4)
  376. // return;
  377. //int slotIndex = Array.IndexOf(components, "SLOT" ) + 1;
  378. //bool isLL = newLocation.StartsWith("LL");
  379. //string target1 = string.Format("{0}.{1}{2}", newLocation, isLL ? "Ch2" : "Ch1", isLL ? ".Slot" + components[slotIndex] : string.Empty);
  380. //string target2 = string.Format("{0}.{1}{2}", newLocation, isLL ? "Ch1" : "Ch2", isLL ? ".Slot" + components[slotIndex] : string.Empty);
  381. //string arm = "VTM.Arm" + components[armIndex];
  382. ////jms changed pickPlaceSwap to string for CR#7576.
  383. //if (pickPlaceSwap == "pick")
  384. //{
  385. // WaferTrack.Instance.UpdateMaterialMap(arm + ".Left", WaferTrack.Instance.GetLocationState(target1));
  386. // WaferTrack.Instance.UpdateMaterialMap(arm + ".Right", WaferTrack.Instance.GetLocationState(target2));
  387. // WaferTrack.Instance.UpdateMaterialMap(target1, WaferTrackStateEnum.Unoccupied);
  388. // WaferTrack.Instance.UpdateMaterialMap(target2, WaferTrackStateEnum.Unoccupied);
  389. //}
  390. //else if (pickPlaceSwap == "place")
  391. //{
  392. // WaferTrack.Instance.UpdateMaterialMap(target1, WaferTrack.Instance.GetLocationState(arm + ".Left"));
  393. // WaferTrack.Instance.UpdateMaterialMap(target2, WaferTrack.Instance.GetLocationState(arm + ".Right"));
  394. // WaferTrack.Instance.UpdateMaterialMap(arm + ".Left", WaferTrackStateEnum.Unoccupied);
  395. // WaferTrack.Instance.UpdateMaterialMap(arm + ".Right", WaferTrackStateEnum.Unoccupied);
  396. //}
  397. ////jms added swap check for CR#7576.
  398. //else if (pickPlaceSwap == "swap")
  399. //{
  400. // if (components[armIndex] == "A")
  401. // {
  402. // WaferTrack.Instance.UpdateWaferTrackState(armAPan1, WaferTrack.Instance.GetLocationState(target1));
  403. // WaferTrack.Instance.UpdateMaterialMap(armAPan2, WaferTrack.Instance.GetLocationState(target2));
  404. // WaferTrack.Instance.UpdateMaterialMap(target1, WaferTrack.Instance.GetLocationState(armBPan1));
  405. // WaferTrack.Instance.UpdateMaterialMap(target2, WaferTrack.Instance.GetLocationState(armBPan2));
  406. // WaferTrack.Instance.UpdateMaterialMap(armBPan1, WaferTrackStateEnum.Unoccupied);
  407. // WaferTrack.Instance.UpdateMaterialMap(armBPan2, WaferTrackStateEnum.Unoccupied);
  408. // }
  409. // else
  410. // {
  411. // WaferTrack.Instance.UpdateMaterialMap(armBPan1, WaferTrack.Instance.GetLocationState(target1));
  412. // WaferTrack.Instance.UpdateMaterialMap(armBPan2, WaferTrack.Instance.GetLocationState(target2));
  413. // WaferTrack.Instance.UpdateMaterialMap(target1, WaferTrack.Instance.GetLocationState(armAPan1));
  414. // WaferTrack.Instance.UpdateMaterialMap(target2, WaferTrack.Instance.GetLocationState(armAPan2));
  415. // WaferTrack.Instance.UpdateMaterialMap(armAPan1, WaferTrackStateEnum.Unoccupied);
  416. // WaferTrack.Instance.UpdateMaterialMap(armAPan2, WaferTrackStateEnum.Unoccupied);
  417. // }
  418. //}
  419. }
  420. /// <summary>
  421. /// Get the arm state string returned in WAFER PRESENT request message
  422. /// </summary>
  423. /// <returns>Arm state string</returns>
  424. private string GetArmStates()
  425. {
  426. return " N N";
  427. //string states = " A LEFT " + (WaferTrack.Instance.IsOccupied(armAPan1) ? "Y" : "N");
  428. //states += " RIGHT " + (WaferTrack.Instance.IsOccupied(armAPan2) ? "Y" : "N");
  429. //states += " B LEFT " + (WaferTrack.Instance.IsOccupied(armBPan1) ? "Y" : "N");
  430. //states += " RIGHT " + (WaferTrack.Instance.IsOccupied(armBPan2) ? "Y" : "N");
  431. //return states;
  432. }
  433. /// <summary>
  434. /// Timer used for simulating realistic mode
  435. /// </summary>
  436. /// <param name="sender">Who sent it</param>
  437. /// <param name="e">Arguments</param>
  438. private void timer_Elapsed(object sender, ElapsedEventArgs e)
  439. {
  440. //Log.WriteIfEnabled(LogCategory.Debug, source, string.Format("Move complete to station {0}. Writing message _RDY", newLocation));
  441. currentStation = newLocation;
  442. currentArm = newArm;
  443. //jms added exchanging check for CR#7576.
  444. if (robotStateArgs.State == RobotStateEnum.Picking || robotStateArgs.State == RobotStateEnum.Placing ||
  445. robotStateArgs.State == RobotStateEnum.Extending || robotStateArgs.State == RobotStateEnum.Exchanging)
  446. {
  447. SetArmState(lastMsg, armTargetMaterialMap);
  448. lastMsg = "";
  449. }
  450. SetRobotState(RobotStateEnum.Idle);
  451. timer.Enabled = false;
  452. OnWriteMessage(msgDone);
  453. }
  454. }
  455. }