SchedulerRobot.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. using Aitex.Core.RT.Fsm;
  2. using Aitex.Core.RT.Log;
  3. using Aitex.Core.RT.Routine;
  4. using Aitex.Core.Util;
  5. using MECF.Framework.Common.Equipment;
  6. using MECF.Framework.Common.Schedulers;
  7. using PunkHPX8_Core;
  8. using PunkHPX8_RT.Modules;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using MECF.Framework.Common.SubstrateTrackings;
  15. using PunkHPX8_RT.Modules.SRD;
  16. using PunkHPX8_RT.Modules.VpwMain;
  17. using PunkHPX8_RT.Modules.VpwCell;
  18. using MECF.Framework.Common.RecipeCenter;
  19. using PunkHPX8_RT.Modules.PlatingCell;
  20. using Aitex.Sorter.Common;
  21. using PunkHPX8_RT.Dispatch;
  22. using MECF.Framework.Common.ToolLayout;
  23. using Aitex.Core.Common;
  24. using PunkHPX8_RT.Devices.VpwMain;
  25. namespace PunkHPX8_RT.Schedulers.EfemRobot
  26. {
  27. public class SchedulerRobot : SchedulerModule
  28. {
  29. private enum SchedulerRobotOperation
  30. {
  31. None,
  32. Pick,
  33. PickWait,
  34. Place,
  35. PlaceWait
  36. }
  37. #region 内部变量
  38. private EfemEntity _efemEntity;
  39. #endregion
  40. #region 属性
  41. /// <summary>
  42. /// 是否空闲
  43. /// </summary>
  44. public override bool IsIdle
  45. {
  46. get { return _state == RState.End; }
  47. }
  48. /// <summary>
  49. /// 是否错误
  50. /// </summary>
  51. public override bool IsError
  52. {
  53. get { return _state == RState.Failed || _state == RState.Timeout; }
  54. }
  55. #endregion
  56. /// <summary>
  57. /// 构造函数
  58. /// </summary>
  59. /// <param name="module"></param>
  60. public SchedulerRobot(ModuleName module) : base(module.ToString())
  61. {
  62. _efemEntity = Singleton<RouteManager>.Instance.EFEM;
  63. }
  64. /// <summary>
  65. /// 执行
  66. /// </summary>
  67. /// <param name="parameter"></param>
  68. /// <returns></returns>
  69. public override bool RunProcess(object recipe, object parameter, List<SchedulerSyncModuleMessage> syncMessages)
  70. {
  71. if (_efemEntity.IsBusy)
  72. {
  73. return false;
  74. }
  75. MoveItem moveItem = (MoveItem)parameter;
  76. if (moveItem.SourceModule != ModuleName.Unknown&&moveItem.DestinationModule!=ModuleName.Unknown)
  77. {
  78. SynchorinzeModuleMessages(syncMessages);
  79. _state = RState.Running;
  80. if (RobotMoveHelper.Instance.IsIdle)
  81. {
  82. RobotMoveHelper.Instance.Start(moveItem, Module.ToString());
  83. return true;
  84. }
  85. }
  86. return false;
  87. }
  88. /// <summary>
  89. /// 监控执行
  90. /// </summary>
  91. /// <returns></returns>
  92. public override bool MonitorProcess(SchedulerSequence schedulerSequence, bool hasMatchWafer)
  93. {
  94. RobotMoveHelper.Instance.Monitor(Module.ToString());
  95. if (RobotMoveHelper.Instance.IsIdle)
  96. {
  97. _state = RState.End;
  98. }
  99. return true;
  100. }
  101. /// <summary>
  102. /// 检验前置条件
  103. /// </summary>
  104. /// <param name="sequenceIndex"></param>
  105. /// <param name="parameter"></param>
  106. /// <returns></returns>
  107. public override bool CheckPrecondition(List<SchedulerSequence> schedulerSequences, int sequenceIndex, object parameter,string materialId, ref string reason)
  108. {
  109. if (parameter == null)
  110. {
  111. reason = "parameter is null";
  112. return true;
  113. }
  114. if (_state == RState.Running)
  115. {
  116. reason = "scheduler module is already running";
  117. return false;
  118. }
  119. if(_efemEntity.IsBusy)
  120. {
  121. reason = "efem is busy";
  122. return false;
  123. }
  124. if(_efemEntity.IsError)
  125. {
  126. reason = "efem is error";
  127. return false;
  128. }
  129. MoveItem moveItem = (MoveItem)parameter;
  130. if(WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)Hand.Blade1))
  131. {
  132. reason = "robot lower hand has wafer";
  133. return false;
  134. }
  135. if (WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot, (int)Hand.Blade2))
  136. {
  137. reason = "robot upper hand has wafer";
  138. return false;
  139. }
  140. if (!CheckPreTaskComplete(materialId,schedulerSequences,sequenceIndex))
  141. {
  142. reason = "last wafer task has not completed";
  143. return false;
  144. }
  145. if (moveItem.SourceModule == ModuleName.Unknown)
  146. {
  147. UpdateUnkownSourceModule(schedulerSequences, moveItem, sequenceIndex);
  148. }
  149. if (moveItem.DestinationModule == ModuleName.Unknown)
  150. {
  151. bool result= UpdateUnkownTargetModule(schedulerSequences, moveItem, sequenceIndex);
  152. if (!result)
  153. {
  154. reason = "efem robot confirm target module failed";
  155. return false;
  156. }
  157. }
  158. if (!WaferManager.Instance.CheckHasWafer(moveItem.SourceModule, moveItem.SourceSlot))
  159. {
  160. reason = $"{moveItem.SourceModule} slot {moveItem.SourceSlot} has no wafer";
  161. return false;
  162. }
  163. if (WaferManager.Instance.CheckHasWafer(moveItem.DestinationModule, moveItem.DestinationSlot))
  164. {
  165. reason = $"{moveItem.DestinationModule} slot {moveItem.DestinationSlot} has wafer";
  166. return false;
  167. }
  168. if (ModuleHelper.IsVPWCell(moveItem.DestinationModule))
  169. {
  170. return CheckVpw(moveItem, schedulerSequences, sequenceIndex, ref reason);
  171. }
  172. return true;
  173. }
  174. /// <summary>
  175. /// 检验VPW
  176. /// </summary>
  177. /// <param name="moveItem"></param>
  178. /// <param name="schedulerSequences"></param>
  179. /// <param name="sequenceIndex"></param>
  180. /// <param name="reason"></param>
  181. /// <returns></returns>
  182. private bool CheckVpw(MoveItem moveItem,List<SchedulerSequence> schedulerSequences, int sequenceIndex,ref string reason)
  183. {
  184. VpwCellEntity vpwEntity = Singleton<RouteManager>.Instance.GetModule<VpwCellEntity>(moveItem.DestinationModule.ToString());
  185. if (vpwEntity != null)
  186. {
  187. bool nextVpwRecipe = false;
  188. if (sequenceIndex + 1 < schedulerSequences.Count)
  189. {
  190. SchedulerSequence nextSequence = schedulerSequences[sequenceIndex + 1];
  191. if (nextSequence.ModuleType == ModuleType.VPW)
  192. {
  193. nextVpwRecipe = true;
  194. }
  195. }
  196. if (nextVpwRecipe)
  197. {
  198. if (vpwEntity.State == (int)VPWCellState.WaitForRunRecipe)
  199. {
  200. return true;
  201. }
  202. else
  203. {
  204. if (vpwEntity.IsIdle)
  205. {
  206. SchedulerSequence nextSequence = schedulerSequences[sequenceIndex + 1];
  207. vpwEntity.CheckToPostMessage<VPWCellState, VPWCellMsg>(eEvent.INFO_VPW, Module.ToString(),
  208. (int)VPWCellMsg.Prepare, nextSequence.Recipe);
  209. }
  210. reason = $"{vpwEntity.Module} state is not WaitForRunRecipe";
  211. return false;
  212. }
  213. }
  214. else
  215. {
  216. VpwMainEntity vpwMainEntity = Singleton<RouteManager>.Instance.GetModule<VpwMainEntity>(ModuleName.VPWMain1.ToString());
  217. if (vpwMainEntity.IsIdle)
  218. {
  219. if (vpwMainEntity.IsChamberOpened)
  220. {
  221. return true;
  222. }
  223. else
  224. {
  225. vpwMainEntity.CheckToPostMessage<VPWMainState, VPWMainMsg>(eEvent.INFO_VPW, Module.ToString(), (int)VPWMainMsg.ChamberDown);
  226. reason = $"{vpwEntity.Module} chamber is not opened";
  227. return false;
  228. }
  229. }
  230. else
  231. {
  232. reason = $"{vpwMainEntity.Module} is not idle";
  233. return false;
  234. }
  235. }
  236. }
  237. else
  238. {
  239. reason = $"{moveItem.DestinationModule} is null";
  240. }
  241. return false;
  242. }
  243. /// <summary>
  244. /// 更新未知源模块
  245. /// </summary>
  246. private void UpdateUnkownSourceModule(List<SchedulerSequence> schedulerSequences, MoveItem moveItem, int sequenceIndex)
  247. {
  248. if (moveItem.SourceModule == ModuleName.Unknown)
  249. {
  250. if (sequenceIndex >= 1 && sequenceIndex - 1 < schedulerSequences.Count)
  251. {
  252. SchedulerSequence preSchedulerSequence = schedulerSequences[sequenceIndex - 1];
  253. if (preSchedulerSequence != null && preSchedulerSequence.SchedulerModule != null)
  254. {
  255. moveItem.SourceModule = preSchedulerSequence.SchedulerModule.Module;
  256. }
  257. }
  258. }
  259. }
  260. /// <summary>
  261. /// 更新未知目标模块
  262. /// </summary>
  263. private bool UpdateUnkownTargetModule(List<SchedulerSequence> schedulerSequences, MoveItem moveItem, int sequenceIndex)
  264. {
  265. SchedulerSequence currentSchedulerSequence= schedulerSequences[sequenceIndex];
  266. if (sequenceIndex >= schedulerSequences.Count - 1)
  267. {
  268. return false;
  269. }
  270. SchedulerSequence nextSequence=schedulerSequences[sequenceIndex+1];
  271. ModuleName moduleName = ModuleName.Unknown;
  272. if (moveItem.DestinationType == ModuleType.SRD)
  273. {
  274. SRDEntity srd1Entity = Singleton<RouteManager>.Instance.GetModule<SRDEntity>(ModuleName.SRD1.ToString());
  275. if (srd1Entity != null&&srd1Entity.IsIdle&&srd1Entity.IsAuto&&WaferManager.Instance.CheckNoWafer(ModuleName.SRD1.ToString(),0))
  276. {
  277. moduleName = ModuleName.SRD1;
  278. }
  279. else
  280. {
  281. SRDEntity srd2Entity= Singleton<RouteManager>.Instance.GetModule<SRDEntity>(ModuleName.SRD2.ToString());
  282. if (srd2Entity != null && srd2Entity.IsIdle&&srd2Entity.IsAuto && WaferManager.Instance.CheckNoWafer(ModuleName.SRD2.ToString(), 0))
  283. {
  284. moduleName=ModuleName.SRD2;
  285. }
  286. }
  287. }
  288. else if (moveItem.DestinationType == ModuleType.PlatingCell)
  289. {
  290. DepRecipe depRecipe = (DepRecipe)nextSequence.Recipe;
  291. List<PlatingCellEntity> platingCellEntities= SchedulerSequenceManager.Instance.GetAvaiblePlatingCellList(depRecipe.Chemistry, nextSequence.SequenceType, nextSequence.WaferSize, true);
  292. if (platingCellEntities.Count > 0)
  293. {
  294. moduleName = platingCellEntities[0].Module;
  295. }
  296. }
  297. else
  298. {
  299. return false;
  300. }
  301. if (moduleName == ModuleName.Unknown)
  302. {
  303. return false;
  304. }
  305. else
  306. {
  307. if(WaferManager.Instance.CheckHasWafer(moduleName,0))
  308. {
  309. return false;
  310. }
  311. IModuleEntity moduleEntity = Singleton<RouteManager>.Instance.GetModule<IModuleEntity>(moduleName.ToString());
  312. if (moduleEntity==null)
  313. {
  314. return false;
  315. }
  316. if (moduleEntity.IsBusy)
  317. {
  318. return false;
  319. }
  320. moveItem.DestinationModule = moduleName;
  321. if (sequenceIndex + 1 < schedulerSequences.Count)
  322. {
  323. SchedulerSequence sequence = schedulerSequences[sequenceIndex + 1];
  324. if (sequence.SchedulerModule == null)
  325. {
  326. sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(moduleName);
  327. sequence.ModuleName = moduleName;
  328. }
  329. }
  330. }
  331. return true;
  332. }
  333. /// <summary>
  334. /// 检验上一个任务是否完成
  335. /// </summary>
  336. /// <param name="materialId"></param>
  337. /// <returns></returns>
  338. private bool CheckPreTaskComplete(string materialId, List<SchedulerSequence> schedulerSequences, int sequenceIndex)
  339. {
  340. WaferTask waferTask = WaferTaskManager.Instance.GetWaferTask(materialId);
  341. if(waferTask == null)
  342. {
  343. return true;
  344. }
  345. WaferInfo waferInfo = WaferManager.Instance.GetWaferByWaferId(materialId);
  346. if (waferInfo == null || waferInfo.IsEmpty)
  347. {
  348. return true;
  349. }
  350. if (!string.IsNullOrEmpty(waferTask.MateWaferTask))
  351. {
  352. return true;
  353. }
  354. if (sequenceIndex < 1)
  355. {
  356. return true;
  357. }
  358. SchedulerSequence preSequence=schedulerSequences[sequenceIndex-1];
  359. if (preSequence==null)
  360. {
  361. return true;
  362. }
  363. if (preSequence.ModuleName!=ModuleName.Aligner1)
  364. {
  365. return true;
  366. }
  367. List<string> platingCells = PlatingCellItemManager.Instance.InstalledModules;
  368. foreach(string item in platingCells)
  369. {
  370. PlatingCellEntity platingCellEntity = Singleton<RouteManager>.Instance.GetModule<PlatingCellEntity>(item);
  371. if (!platingCellEntity.IsAuto)
  372. {
  373. continue;
  374. }
  375. if (platingCellEntity.MetalWaferSize != (int)waferInfo.Size)
  376. {
  377. continue;
  378. }
  379. if (WaferManager.Instance.CheckHasWafer(item, 0))
  380. {
  381. return false;
  382. }
  383. }
  384. List<string> vpwCells = VpwCellItemManager.Instance.InstalledModules;
  385. foreach (string item in vpwCells)
  386. {
  387. VpwCellEntity entity = Singleton<RouteManager>.Instance.GetModule<VpwCellEntity>(item);
  388. if (!entity.IsAuto)
  389. {
  390. continue;
  391. }
  392. if (entity.VpwWaferSize != (int)waferInfo.Size)
  393. {
  394. continue;
  395. }
  396. if (WaferManager.Instance.CheckHasWafer(item, 0))
  397. {
  398. return false;
  399. }
  400. }
  401. return true;
  402. }
  403. public override void ResetTask()
  404. {
  405. base.ResetTask();
  406. RobotMoveHelper.Instance.Reset();
  407. }
  408. }
  409. }