DualArmMoveManager.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Aitex.Core.Common;
  5. using Aitex.Core.RT.Log;
  6. using Aitex.Core.RT.Routine;
  7. using EFEM.RT.Routines;
  8. using Aitex.Sorter.Common;
  9. using Aitex.Sorter.RT.Module;
  10. using MECF.Framework.Common.Equipment;
  11. using MECF.Framework.Common.SubstrateTrackings;
  12. using Aitex.Core.RT.Device;
  13. namespace EFEM.RT.Modules
  14. {
  15. public class DualArmMoveManager : IMoveManager
  16. {
  17. public event Action<MoveErrorArgument> OnMoveError;
  18. public int TaskCount { get { return tasks.Count; } }
  19. public bool IsPaused { get { return !_pause; } }
  20. public int WaferCompleted
  21. {
  22. get
  23. {
  24. int count = tasks.Count;
  25. int completed = lastTaskCount - count;
  26. lastTaskCount = count;
  27. return completed;
  28. }
  29. }
  30. private Queue<MoveTask> tasks = new Queue<MoveTask>();
  31. private Queue<MoveTask> curtasks = new Queue<MoveTask>();
  32. private Queue<IRoutine> steps = new Queue<IRoutine>();
  33. private IRoutine curStep = null;
  34. private readonly bool _isInterferencePrevent =
  35. DeviceDefineManager.Instance.GetValue<bool>("InterferencePrevent") ?? false;
  36. private IEfemPickRoutine pickRoutine1 = null;
  37. private IEfemPlaceRoutine placeRoutine1 = null;
  38. private IEfemPickRoutine pickRoutine2 = null;
  39. private IEfemPlaceRoutine placeRoutine2 = null;
  40. private SwapRoutine swaproutine1 = null;
  41. private int lastTaskCount = 0;
  42. private int handChangeCount = 0;
  43. private bool _pause;
  44. public DualArmMoveManager()
  45. {
  46. pickRoutine1 = new PickRoutine("System", "Pick");
  47. pickRoutine1.Initalize();
  48. placeRoutine1 = new PlaceRoutine("System", "Place");
  49. placeRoutine1.Initalize();
  50. pickRoutine2 = new PickRoutine("System", "Pick");
  51. pickRoutine2.Initalize();
  52. placeRoutine2 = new PlaceRoutine("System", "Place");
  53. placeRoutine2.Initalize();
  54. swaproutine1 = new SwapRoutine("System", "Swap");
  55. swaproutine1.Initalize();
  56. }
  57. public bool Initialize()
  58. {
  59. return true;
  60. }
  61. public bool Pause()
  62. {
  63. _pause = true;
  64. return true;
  65. }
  66. public bool Resume()
  67. {
  68. _pause = false;
  69. return true;
  70. }
  71. public bool Stop()
  72. {
  73. tasks.Clear();
  74. _pause = false;
  75. return true;
  76. }
  77. public bool Start(List<MoveTask> tasks)
  78. {
  79. _pause = false;
  80. //tasks = tasks.OrderBy(item =>item.SourceStaion).ThenBy(item => item.SourceSlot).ToList<MoveTask>();
  81. foreach (MoveTask task in tasks)
  82. {
  83. WaferManager.Instance.UpdateWaferProcessStatus(task.SourceStaion, task.SourceSlot, EnumWaferProcessStatus.Wait);//(task.WaferID, EnumWaferProcessStatus.Wait);
  84. task.WaferID = WaferManager.Instance.GetWaferID(task.SourceStaion, task.SourceSlot);
  85. }
  86. this.tasks.Clear();
  87. for (int i = 0; i < tasks.Count; i++)
  88. {
  89. this.tasks.Enqueue(tasks[i]);
  90. }
  91. if (!newTask())
  92. {
  93. return false;
  94. }
  95. if (steps.Count > 0)
  96. {
  97. curStep = steps.Dequeue();
  98. }
  99. if (curStep != null)
  100. {
  101. Result ret = curStep.Start();
  102. if (ret == Result.FAIL)
  103. {
  104. return false;
  105. }
  106. }
  107. lastTaskCount = tasks.Count;
  108. return true;
  109. }
  110. private bool newTask()
  111. {
  112. MoveTask[] nextTasks = new MoveTask[] { null, null };
  113. steps.Clear();
  114. curStep = null;
  115. if (tasks.Count == 0)
  116. {
  117. return true; //completed
  118. }
  119. for (int i = 0; i < nextTasks.Length && i < tasks.Count; i++)
  120. {
  121. nextTasks[i] = tasks.ElementAt(i);
  122. }
  123. if(nextTasks[1] != null && IsNeighbors(nextTasks[0], nextTasks[1], true) && IsNeighbors(nextTasks[0], nextTasks[1], false))//dual arm
  124. {
  125. ////double pick double place
  126. DPDP(nextTasks[0], nextTasks[1]);
  127. WaferManager.Instance.UpdateWaferProcessStatus(nextTasks[0].SourceStaion, nextTasks[0].SourceSlot, EnumWaferProcessStatus.Wait);//(nextTasks[0].WaferID, EnumWaferProcessStatus.InProcess);
  128. WaferManager.Instance.UpdateWaferProcessStatus(nextTasks[1].SourceStaion, nextTasks[1].SourceSlot, EnumWaferProcessStatus.Wait);//(nextTasks[1].WaferID, EnumWaferProcessStatus.InProcess);
  129. tasks.Dequeue();
  130. tasks.Dequeue();
  131. LOG.Info(string.Format("Dual transfer step 1, wafer move from {0}{1:D2} to {2}{3:D2}.",
  132. nextTasks[0].SourceStaion.ToString(), nextTasks[0].SourceSlot + 1, nextTasks[0].DestStaion.ToString(), nextTasks[0].DestSlot + 1));
  133. LOG.Info(string.Format("Dual transfer step 2, wafer move from {0}{1:D2} to {2}{3:D2}.",
  134. nextTasks[1].SourceStaion.ToString(), nextTasks[1].SourceSlot + 1, nextTasks[1].DestStaion.ToString(), nextTasks[1].DestSlot + 1));
  135. }
  136. else
  137. {
  138. Hand hand;
  139. if (handChangeCount % 2 == 0)
  140. {
  141. hand = WaferManager.Instance.CheckNoWafer(ModuleName.Robot, 0) ? Hand.Blade1 : Hand.Blade2;
  142. }
  143. else
  144. {
  145. hand = WaferManager.Instance.CheckNoWafer(ModuleName.Robot, 1) ? Hand.Blade2 : Hand.Blade1;
  146. }
  147. handChangeCount++;
  148. if (handChangeCount == int.MaxValue)
  149. handChangeCount = 0;
  150. if (!WaferManager.Instance.CheckNoWafer(ModuleName.Robot, (int)hand))
  151. {
  152. return false;
  153. }
  154. Move(nextTasks[0], hand);
  155. WaferManager.Instance.UpdateWaferProcessStatus(nextTasks[0].SourceStaion, nextTasks[0].SourceSlot, EnumWaferProcessStatus.Wait);//(nextTasks[0].WaferID, EnumWaferProcessStatus.InProcess);
  156. tasks.Dequeue();
  157. LOG.Info(string.Format("Single transfer wafer move from {0}{1:D2} to {2}{3:D2}.",
  158. nextTasks[0].SourceStaion.ToString(), nextTasks[0].SourceSlot, nextTasks[0].DestStaion.ToString(), nextTasks[0].DestSlot));
  159. }
  160. return true;
  161. }
  162. private bool IsSwap(MoveTask task)
  163. {
  164. if (task == null)
  165. return false;
  166. if ((task.DestStaion == task.SourceStaion) && (task.DestSlot == task.SourceSlot))
  167. return false;
  168. return WaferManager.Instance.CheckHasWafer(task.DestStaion, task.DestSlot);
  169. }
  170. private bool IsNeighbors(MoveTask task1, MoveTask task2, bool pick)
  171. {
  172. if (pick)
  173. {
  174. return (task1.SourceStaion == task2.SourceStaion) && (task1.SourceSlot + 1 == task2.SourceSlot);
  175. }
  176. return (task1.DestStaion == task2.DestStaion) && (task1.DestSlot + 1 == task2.DestSlot);
  177. }
  178. private void Move(MoveTask task, Hand hand)
  179. {
  180. if (task.SourceStaion != ModuleName.Robot)
  181. {
  182. pickRoutine1.Source = task.SourceStaion;
  183. pickRoutine1.Slot = task.SourceSlot;
  184. pickRoutine1.Blade = hand;
  185. steps.Enqueue(pickRoutine1);
  186. }
  187. if (task.DestStaion != ModuleName.Robot)
  188. {
  189. placeRoutine1.Station = task.DestStaion;
  190. placeRoutine1.Slot = task.DestSlot;
  191. placeRoutine1.Blade = hand;
  192. steps.Enqueue(placeRoutine1);
  193. }
  194. }
  195. private void DPDP(MoveTask task1, MoveTask task2)
  196. {
  197. if (task1.SourceStaion != ModuleName.Robot)
  198. {
  199. pickRoutine1.Source = task1.SourceStaion;
  200. pickRoutine1.Slot = task1.SourceSlot;
  201. pickRoutine1.Blade = Hand.Blade1;
  202. steps.Enqueue(pickRoutine1);
  203. }
  204. if (task2.SourceStaion != ModuleName.Robot)
  205. {
  206. pickRoutine2.Source = task2.SourceStaion;
  207. pickRoutine2.Slot = task2.SourceSlot;
  208. pickRoutine2.Blade = Hand.Blade2;
  209. steps.Enqueue(pickRoutine2);
  210. }
  211. if (task1.DestStaion != ModuleName.Robot)
  212. {
  213. placeRoutine1.Station = task1.DestStaion;
  214. placeRoutine1.Slot = task1.DestSlot;
  215. placeRoutine1.Blade = Hand.Blade1;
  216. steps.Enqueue(placeRoutine1);
  217. }
  218. if (task2.DestStaion != ModuleName.Robot)
  219. {
  220. placeRoutine2.Station = task2.DestStaion;
  221. placeRoutine2.Slot = task2.DestSlot;
  222. placeRoutine2.Blade = Hand.Blade2;
  223. steps.Enqueue(placeRoutine2);
  224. }
  225. }
  226. private void DPSP(MoveTask task1, MoveTask task2)
  227. {
  228. if (task1.SourceStaion != ModuleName.Robot)
  229. {
  230. pickRoutine1.Source = task1.SourceStaion;
  231. pickRoutine1.Slot = task1.SourceSlot;
  232. pickRoutine1.Blade = Hand.Blade1;
  233. steps.Enqueue(pickRoutine1);
  234. }
  235. if (task2.SourceStaion != ModuleName.Robot)
  236. {
  237. pickRoutine2.Source = task2.SourceStaion;
  238. pickRoutine2.Slot = task2.SourceSlot;
  239. pickRoutine2.Blade = Hand.Blade2;
  240. steps.Enqueue(pickRoutine2);
  241. }
  242. if (task1.DestStaion != ModuleName.Robot)
  243. {
  244. placeRoutine1.Station = task1.DestStaion;
  245. placeRoutine1.Slot = task1.DestSlot;
  246. placeRoutine1.Blade = Hand.Both;
  247. steps.Enqueue(placeRoutine1);
  248. }
  249. }
  250. private void SPDP(MoveTask task1, MoveTask task2)
  251. {
  252. if (task1.SourceStaion != ModuleName.Robot)
  253. {
  254. pickRoutine1.Source = task1.SourceStaion;
  255. pickRoutine1.Slot = task1.SourceSlot;
  256. pickRoutine1.Blade = Hand.Both;
  257. steps.Enqueue(pickRoutine1);
  258. }
  259. if (task1.DestStaion != ModuleName.Robot)
  260. {
  261. placeRoutine1.Station = task1.DestStaion;
  262. placeRoutine1.Slot = task1.DestSlot;
  263. placeRoutine1.Blade = Hand.Blade1;
  264. steps.Enqueue(placeRoutine1);
  265. }
  266. if (task2.DestStaion != ModuleName.Robot)
  267. {
  268. placeRoutine2.Station = task2.DestStaion;
  269. placeRoutine2.Slot = task2.DestSlot;
  270. placeRoutine2.Blade = Hand.Blade2;
  271. steps.Enqueue(placeRoutine2);
  272. }
  273. }
  274. private void SPSP(MoveTask task)
  275. {
  276. if (task.SourceStaion != ModuleName.Robot)
  277. {
  278. pickRoutine1.Source = task.SourceStaion;
  279. pickRoutine1.Slot = task.SourceSlot;
  280. pickRoutine1.Blade = Hand.Both;
  281. steps.Enqueue(pickRoutine1);
  282. }
  283. if (task.DestStaion != ModuleName.Robot)
  284. {
  285. placeRoutine1.Station = task.DestStaion;
  286. placeRoutine1.Slot = task.DestSlot;
  287. placeRoutine1.Blade = Hand.Both;
  288. steps.Enqueue(placeRoutine1);
  289. }
  290. }
  291. ///
  292. private bool CanUsedBlade2(MoveTask task1, MoveTask task2, MoveTask task3, MoveTask task4, out int handledTask)
  293. {
  294. handledTask = 0;
  295. if (task1 == null || task1.SourceSlot + 3 > 24)
  296. {
  297. return false;
  298. }
  299. if (task1 != null && task2 != null && task3 != null && task4 != null)
  300. {
  301. if ((task2.SourceSlot == task1.SourceSlot + 1) && (task2.DestSlot == task1.DestSlot + 1)
  302. && (task3.SourceSlot == task2.SourceSlot + 1) && (task3.DestSlot == task2.DestSlot + 1)
  303. && (task4.SourceSlot == task3.SourceSlot + 1) && (task4.DestSlot == task3.DestSlot + 1)
  304. )
  305. {
  306. if (CheckEmptySlot(task1))
  307. {
  308. handledTask = 4;
  309. return true;
  310. }
  311. }
  312. }
  313. return false;
  314. }
  315. private bool _CanUsedBlade2(MoveTask task1, out int handledTask)
  316. {
  317. handledTask = 0;
  318. bool[] bExists = new bool[] { true, false, false, false };
  319. if (task1.SourceSlot + 3 > 24)
  320. {
  321. return false;
  322. }
  323. if (CheckEmptySlot(task1, bExists))
  324. {
  325. handledTask = 1;
  326. return true;
  327. }
  328. return false;
  329. }
  330. private bool _CanUsedBlade2(MoveTask task1, MoveTask task2, out int handledTask)
  331. {
  332. handledTask = 0;
  333. bool[] bExists = new bool[] { true, false, false, false };
  334. int offset = task2.SourceSlot - task1.SourceSlot;
  335. if (offset > 3)
  336. {
  337. return _CanUsedBlade2(task1, out handledTask);
  338. }
  339. if (task2.SourceSlot - task1.SourceSlot == task2.DestSlot - task1.DestSlot)
  340. {
  341. bExists[task2.SourceSlot - task1.SourceSlot] = true;
  342. if (CheckEmptySlot(task1, bExists))
  343. {
  344. handledTask = 2;
  345. return true;
  346. }
  347. }
  348. return false;
  349. }
  350. private bool _CanUsedBlade2(MoveTask task1, MoveTask task2, MoveTask task3, out int handledTask)
  351. {
  352. handledTask = 0;
  353. bool[] bExists = new bool[] { true, false, false, false };
  354. int offset = task3.SourceSlot - task1.SourceSlot;
  355. if (offset > 3)
  356. {
  357. return _CanUsedBlade2(task1, task2, out handledTask);
  358. }
  359. if (task2.SourceSlot - task1.SourceSlot == task2.DestSlot - task1.DestSlot
  360. && task3.SourceSlot - task1.SourceSlot == task3.DestSlot - task1.DestSlot)
  361. {
  362. bExists[task2.SourceSlot - task1.SourceSlot] = true;
  363. bExists[task3.SourceSlot - task1.SourceSlot] = true;
  364. if (CheckEmptySlot(task1, bExists))
  365. {
  366. handledTask = 3;
  367. return true;
  368. }
  369. }
  370. return false;
  371. }
  372. private bool _CanUsedBlade2(MoveTask task1, MoveTask task2, MoveTask task3, MoveTask task4, out int handledTask)
  373. {
  374. handledTask = 0;
  375. bool[] bExists = new bool[] { true, false, false, false };
  376. int offset = task4.SourceSlot - task1.SourceSlot;
  377. if (offset > 3)
  378. {
  379. return _CanUsedBlade2(task1, task2, task3, out handledTask);
  380. }
  381. if (task2.SourceSlot - task1.SourceSlot == task2.DestSlot - task1.DestSlot
  382. && task3.SourceSlot - task1.SourceSlot == task3.DestSlot - task1.DestSlot
  383. && task4.SourceSlot - task1.SourceSlot == task4.DestSlot - task1.DestSlot)
  384. {
  385. bExists[task2.SourceSlot - task1.SourceSlot] = true;
  386. bExists[task3.SourceSlot - task1.SourceSlot] = true;
  387. bExists[task4.SourceSlot - task1.SourceSlot] = true;
  388. if (CheckEmptySlot(task1, bExists))
  389. {
  390. handledTask = 4;
  391. return true;
  392. }
  393. }
  394. return false;
  395. }
  396. /// <summary>
  397. ///
  398. /// </summary>
  399. /// <param name="objs"></param>
  400. /// <returns>如果任务全部完成,或者任务失败,返回true</returns>
  401. public bool Monitor(object[] objs)
  402. {
  403. Result ret = Result.RUN;
  404. if (tasks.Count == 0 && steps.Count == 0 && curStep == null)
  405. {
  406. return true; //completed
  407. }
  408. if (curStep != null)
  409. {
  410. ret = curStep.Monitor();
  411. }
  412. if (ret == Result.DONE || curStep == null)
  413. {
  414. if (_pause)
  415. {
  416. return false; //pause
  417. }
  418. if (steps.Count > 0)
  419. {
  420. curStep = steps.Dequeue();
  421. }
  422. else
  423. {
  424. newTask();
  425. if (steps.Count > 0)
  426. {
  427. curStep = steps.Dequeue();
  428. }
  429. else
  430. curStep = null;
  431. }
  432. if (curStep != null)
  433. {
  434. ret = curStep.Start();
  435. if (ret == Result.FAIL)
  436. {
  437. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, EnumWaferProcessStatus.Failed);
  438. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, EnumWaferProcessStatus.Failed);
  439. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 2, EnumWaferProcessStatus.Failed);
  440. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 3, EnumWaferProcessStatus.Failed);
  441. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 4, EnumWaferProcessStatus.Failed);
  442. NotifyError("Robot", "Robot Error");
  443. return true; //transition
  444. }
  445. }
  446. else
  447. {
  448. return true; //transition
  449. }
  450. return false;
  451. }
  452. else if (ret == Result.FAIL)
  453. {
  454. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, EnumWaferProcessStatus.Failed);
  455. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, EnumWaferProcessStatus.Failed);
  456. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 2, EnumWaferProcessStatus.Failed);
  457. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 3, EnumWaferProcessStatus.Failed);
  458. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 4, EnumWaferProcessStatus.Failed);
  459. NotifyError("Robot", "Robot Error");
  460. return true; //transition
  461. }
  462. return false;
  463. }
  464. /// <summary>
  465. ///
  466. /// </summary>
  467. /// <param name="objs"></param>
  468. /// <returns>如果任务全部完成,或者任务失败,返回true</returns>
  469. public Result Monitor()
  470. {
  471. Result ret = Result.RUN;
  472. if (tasks.Count == 0 && steps.Count == 0 && curStep == null)
  473. {
  474. return Result.DONE; //completed
  475. }
  476. if (curStep != null)
  477. {
  478. ret = curStep.Monitor();
  479. }
  480. if (ret == Result.DONE || curStep == null)
  481. {
  482. if (_pause)
  483. {
  484. return Result.RUN; //pause
  485. }
  486. if (steps.Count > 0)
  487. {
  488. curStep = steps.Dequeue();
  489. }
  490. else
  491. {
  492. newTask();
  493. if (steps.Count > 0)
  494. {
  495. curStep = steps.Dequeue();
  496. }
  497. else
  498. curStep = null;
  499. }
  500. if (curStep != null)
  501. {
  502. ret = curStep.Start();
  503. if (ret == Result.FAIL)
  504. {
  505. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, EnumWaferProcessStatus.Failed);
  506. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, EnumWaferProcessStatus.Failed);
  507. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 2, EnumWaferProcessStatus.Failed);
  508. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 3, EnumWaferProcessStatus.Failed);
  509. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 4, EnumWaferProcessStatus.Failed);
  510. NotifyError("Robot", "Robot Error");
  511. return Result.FAIL; //transition
  512. }
  513. }
  514. else
  515. {
  516. return Result.DONE; //transition
  517. }
  518. return Result.RUN;
  519. }
  520. else if (ret == Result.FAIL)
  521. {
  522. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 0, EnumWaferProcessStatus.Failed);
  523. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 1, EnumWaferProcessStatus.Failed);
  524. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 2, EnumWaferProcessStatus.Failed);
  525. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 3, EnumWaferProcessStatus.Failed);
  526. WaferManager.Instance.UpdateWaferProcessStatus(ModuleName.Robot, 4, EnumWaferProcessStatus.Failed);
  527. NotifyError("Robot", "Robot Error");
  528. return Result.FAIL; //transition
  529. }
  530. return Result.RUN;
  531. }
  532. private bool CheckEmptySlot(MoveTask task)
  533. {
  534. for (int i = 0; i < 4; i++)
  535. {
  536. if (!WaferManager.Instance.CheckWafer(task.SourceStaion, task.SourceSlot + i, WaferStatus.Normal))
  537. return false;
  538. if (!WaferManager.Instance.CheckNoWafer(task.DestStaion, task.DestSlot + i))
  539. return false;
  540. }
  541. return true;
  542. }
  543. private bool CheckEmptySlot(MoveTask task, bool[] exist)
  544. {
  545. for (int i = 0; i < 4; i++)
  546. {
  547. if (!exist[i])
  548. {
  549. if (!WaferManager.Instance.CheckNoWafer(task.SourceStaion, task.SourceSlot + i))
  550. return false;
  551. }
  552. if (!WaferManager.Instance.CheckNoWafer(task.DestStaion, task.DestSlot + i))
  553. return false;
  554. }
  555. return true;
  556. }
  557. private void NotifyError(string module, string message)
  558. {
  559. if (OnMoveError != null)
  560. {
  561. OnMoveError(new MoveErrorArgument(module, message));
  562. }
  563. }
  564. }
  565. }