ATMDualArmRobot.xaml.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. using MECF.Framework.Common.CommonData;
  2. using VirgoUI.Controls.Common;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.ComponentModel;
  6. using System.Linq;
  7. using System.Windows;
  8. using System.Windows.Controls;
  9. using System.Windows.Input;
  10. using System.Windows.Media;
  11. using System.Windows.Media.Animation;
  12. using OpenSEMI.ClientBase;
  13. using MECF.Framework.Common.Equipment;
  14. using Aitex.Core.UI.MVVM;
  15. using MECF.Framework.Common.DataCenter;
  16. namespace VirgoUI.Controls.Parts
  17. {
  18. /// <summary>
  19. /// ATMDualArmRobot.xaml 的交互逻辑
  20. /// </summary>
  21. public partial class ATMDualArmRobot : UserControl, INotifyPropertyChanged
  22. {
  23. public Visibility LowerArmVisibility
  24. {
  25. get
  26. {
  27. try
  28. {
  29. var armTypeConfig = QueryDataClient.Instance.Service.GetConfig("EFEM.EfemRobotArmType");
  30. if (armTypeConfig == null || !int.TryParse(armTypeConfig.ToString(), out int armType) || armType != 2)
  31. return Visibility.Visible;
  32. var lowerBladeConfig = QueryDataClient.Instance.Service.GetConfig("EFEM.EfemRobot.LowerBladeEnable");
  33. if (lowerBladeConfig != null && bool.TryParse(lowerBladeConfig.ToString(), out bool lowerEnabled))
  34. {
  35. return lowerEnabled ? Visibility.Visible : Visibility.Collapsed;
  36. }
  37. return Visibility.Collapsed;
  38. }
  39. catch
  40. {
  41. return Visibility.Visible;
  42. }
  43. }
  44. }
  45. public Visibility UpperArmVisibility
  46. {
  47. get
  48. {
  49. try
  50. {
  51. var armTypeConfig = QueryDataClient.Instance.Service.GetConfig("EFEM.EfemRobotArmType");
  52. if (armTypeConfig == null || !int.TryParse(armTypeConfig.ToString(), out int armType) || armType != 2)
  53. return Visibility.Visible;
  54. var upperBladeConfig = QueryDataClient.Instance.Service.GetConfig("EFEM.EfemRobot.UpperBladeEnable");
  55. if (upperBladeConfig != null && bool.TryParse(upperBladeConfig.ToString(), out bool upperEnabled))
  56. {
  57. return upperEnabled ? Visibility.Visible : Visibility.Collapsed;
  58. }
  59. return Visibility.Collapsed;
  60. }
  61. catch
  62. {
  63. return Visibility.Visible;
  64. }
  65. }
  66. }
  67. protected readonly int MoveTime = 300;
  68. private const int AnimationTimeout = 3000; // seconds
  69. public int TranslateX
  70. {
  71. get { return (int)GetValue(TranslateXProperty); }
  72. set { SetValue(TranslateXProperty, value); }
  73. }
  74. // Using a DependencyProperty as the backing store for RotateAngel. This enables animation, styling, binding, etc...
  75. public static readonly DependencyProperty TranslateXProperty =
  76. DependencyProperty.Register("TranslateX", typeof(int), typeof(ATMDualArmRobot), new PropertyMetadata(0));
  77. public ModuleName Station
  78. {
  79. get { return (ModuleName)GetValue(StationProperty); }
  80. set { SetValue(StationProperty, value); }
  81. }
  82. // Using a DependencyProperty as the backing store for Station. This enables animation, styling, binding, etc...
  83. public static readonly DependencyProperty StationProperty =
  84. DependencyProperty.Register("Station", typeof(ModuleName), typeof(ATMDualArmRobot), new PropertyMetadata(ModuleName.Robot));
  85. public ICommand Command
  86. {
  87. get { return (ICommand)GetValue(CommandProperty); }
  88. set { SetValue(CommandProperty, value); }
  89. }
  90. // Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
  91. public static readonly DependencyProperty CommandProperty =
  92. DependencyProperty.Register("Command", typeof(ICommand), typeof(ATMDualArmRobot), new PropertyMetadata(null));
  93. public RobotMoveInfo RobotMoveInfo
  94. {
  95. get { return (RobotMoveInfo)GetValue(RobotMoveInfoProperty); }
  96. set { SetValue(RobotMoveInfoProperty, value); }
  97. }
  98. public static readonly DependencyProperty RobotMoveInfoProperty =
  99. DependencyProperty.Register("RobotMoveInfo", typeof(RobotMoveInfo), typeof(ATMDualArmRobot), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
  100. public VTMRobotPosition StationPosition
  101. {
  102. get { return (VTMRobotPosition)GetValue(StationPositionProperty); }
  103. set { SetValue(StationPositionProperty, value); }
  104. }
  105. // Using a DependencyProperty as the backing store for StationPosition. This enables animation, styling, binding, etc...
  106. public static readonly DependencyProperty StationPositionProperty =
  107. DependencyProperty.Register("StationPosition", typeof(VTMRobotPosition), typeof(ATMDualArmRobot), new PropertyMetadata(null, PropertyChangedCallback));
  108. public WaferInfo[] RobotWafers
  109. {
  110. get { return (WaferInfo[])GetValue(RobotWafersProperty); }
  111. set { SetValue(RobotWafersProperty, value); }
  112. }
  113. // Using a DependencyProperty as the backing store for RobotWafers. This enables animation, styling, binding, etc...
  114. public static readonly DependencyProperty RobotWafersProperty =
  115. DependencyProperty.Register("RobotWafers", typeof(WaferInfo[]), typeof(ATMDualArmRobot), new PropertyMetadata(null, PropertyChangedCallback));
  116. public WaferInfo Wafer1
  117. {
  118. get { return (WaferInfo)GetValue(Wafer1Property); }
  119. set { SetValue(Wafer1Property, value); }
  120. }
  121. // Using a DependencyProperty as the backing store for Wafer1. This enables animation, styling, binding, etc...
  122. public static readonly DependencyProperty Wafer1Property =
  123. DependencyProperty.Register("Wafer1", typeof(WaferInfo), typeof(ATMDualArmRobot), new PropertyMetadata(null));
  124. public WaferInfo Wafer2
  125. {
  126. get { return (WaferInfo)GetValue(Wafer2Property); }
  127. set { SetValue(Wafer2Property, value); }
  128. }
  129. // Using a DependencyProperty as the backing store for Wafer2. This enables animation, styling, binding, etc...
  130. public static readonly DependencyProperty Wafer2Property =
  131. DependencyProperty.Register("Wafer2", typeof(WaferInfo), typeof(ATMDualArmRobot), new PropertyMetadata(null));
  132. private string CurrentPosition;
  133. //private string CurrentArmA;
  134. //private string CurrentArmB;
  135. private RobotAction CurrentAction
  136. {
  137. get; set;
  138. }
  139. private List<MenuItem> menu;
  140. public List<MenuItem> Menu
  141. {
  142. get
  143. {
  144. return menu;
  145. }
  146. set
  147. {
  148. menu = value;
  149. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Menu"));
  150. }
  151. }
  152. public ICommand MoveCommand
  153. {
  154. get
  155. {
  156. return new DelegateCommand<object>(MoveTo);
  157. }
  158. }
  159. // private AnimationQueue queue;
  160. public event PropertyChangedEventHandler PropertyChanged;
  161. static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  162. {
  163. var self = (ATMDualArmRobot)d;
  164. switch (e.Property.Name)
  165. {
  166. case "StationPosition":
  167. if (e.NewValue != null)
  168. {
  169. var positions = ((VTMRobotPosition)e.NewValue).Rotations;
  170. var menus = new List<MenuItem>();
  171. foreach (var position in positions)
  172. {
  173. var m = new MenuItem() { Header = position.Key };
  174. Enum.TryParse(position.Key.Split('.')[0], out RobotArm arm);
  175. m.Items.Add(new MenuItem() { Header = "Pick", Command = self.MoveCommand, CommandParameter = new RobotMoveInfo() { BladeTarget = position.Key, Action = RobotAction.Picking, ArmTarget = arm } });
  176. m.Items.Add(new MenuItem() { Header = "Place", Command = self.MoveCommand, CommandParameter = new RobotMoveInfo() { BladeTarget = position.Key, Action = RobotAction.Placing, ArmTarget = arm } });
  177. m.Items.Add(new MenuItem() { Header = "Move", Command = self.MoveCommand, CommandParameter = new RobotMoveInfo() { BladeTarget = position.Key, Action = RobotAction.Moving, ArmTarget = arm } });
  178. menus.Add(m);
  179. }
  180. self.Menu = menus;
  181. self.MoveTo(new RobotMoveInfo() { BladeTarget = positions.First().Key, Action = RobotAction.None });
  182. }
  183. break;
  184. case "RobotWafers":
  185. //if (e.NewValue == null)
  186. //{
  187. // self.Wafer1 = null;
  188. // self.Wafer2 = null;
  189. //}
  190. //else
  191. //{
  192. // if (self.RobotWafers.Length > 1)
  193. // {
  194. // self.Wafer1 = self.RobotWafers[0];
  195. // self.Wafer2 = self.RobotWafers[1];
  196. // }
  197. //}
  198. break;
  199. default:
  200. break;
  201. }
  202. }
  203. Dictionary<string, int> CanvasRotates = new Dictionary<string, int>
  204. {
  205. {"System",90},{"EfemRobot",90 },{"LP1",90 },{"LP2",90},{"Buffer",0},
  206. {"Flipper",180 },{"PMA",270},{"PMB",270},
  207. {"Aligner1",0 },{"Aligner2",0},{"Cooling1",180},{"Cooling2",180},
  208. };
  209. public ATMDualArmRobot()
  210. {
  211. #if DEBUG
  212. System.Diagnostics.PresentationTraceSources.DataBindingSource.Switch.Level = System.Diagnostics.SourceLevels.Critical;
  213. #endif
  214. InitializeComponent();
  215. root.DataContext = this;
  216. canvasRoot.Rotate(90);
  217. canvas1.Rotate(200);
  218. canvas2.Rotate(260);
  219. canvas3.Rotate(-100);
  220. canvas21.Rotate(140);
  221. canvas22.Rotate(100);
  222. canvas23.Rotate(120);
  223. StationPosition = new VTMRobotPosition()
  224. {
  225. Rotations = new Dictionary<string, int>()
  226. {
  227. { "Both.System", -40 },
  228. { "ArmA.System", -40 }
  229. , { "ArmA.LP1", -147 }
  230. , { "ArmA.LP2", 38 }
  231. , { "ArmA.Flipper", -85 }
  232. , { "ArmA.Buffer", 24 }
  233. , { "ArmA.Aligner1", 74 }
  234. , { "ArmA.Aligner2", 14 }
  235. , { "ArmA.Cooling1", -90 }
  236. , { "ArmA.Cooling2", -135 }
  237. , { "ArmA.PMA", -145 }
  238. , { "ArmA.PMB", 100 }
  239. , { "ArmB.System", -68 }
  240. , { "ArmB.LP1", -122 }
  241. , { "ArmB.LP2", 60 }
  242. , { "ArmB.Flipper", -85 }
  243. , { "ArmB.Buffer", 44 }
  244. , { "ArmB.Aligner1", 24 }
  245. , { "ArmB.Aligner2", 44 }
  246. , { "ArmB.Cooling1", -105 }
  247. , { "ArmB.Cooling2", -105 }
  248. , { "ArmB.PMA", -170 }
  249. , { "ArmB.PMB", 75 }
  250. },
  251. Home = new int[8] { 0, 180, 180, 0, 0, 180, 180, 0 },
  252. //Arm1Extend = new int[8] { 140, 180, -50, 40, 100, 260, 50, -180 },
  253. //Arm2Extend = new int[8] { 220, 100, -50, -50, 180, 180, 50, -85 },
  254. //Flipper
  255. Arm1Extend = new int[8] { 4, 180, 180, 0, 4, 360, 0, 0 },
  256. Arm2Extend = new int[8] { -4, 360, 0, 0, -4, 180, 180, 0, },
  257. //Buffer
  258. Arm3Extend = new int[8] { -30, 210, 180, 0, -30, 390, 0, 0 },
  259. Arm31Extend = new int[8] { -60, 60, 0, 0, 0, 180, 180, 0 },
  260. //Aligner
  261. //Arm4Extend = new int[8] { 0, 180, 180, 0, 90, 270, 0, 0, },
  262. Arm4Extend = new int[8] { 44, 136, 180, 0, 90, 270, 0, 0, },
  263. Arm41Extend = new int[8] { 36, 324, 0, 0, 37, 143, 180, 0, },
  264. //LP,PM
  265. Arm5Extend = new int[8] { 0, 180, 180, 0, 0, 360, 0, 0 },
  266. Arm6Extend = new int[8] { 0, 360, 0, 0, 0, 180, 180, 0, },
  267. // Cooling1
  268. Arm7Extend = new int[8] { -35, 35, 180, 0, -30, 30, 0, 0 },
  269. Arm71Extend = new int[8] { -50, 50, 0, 0, -40, 220, 180, 0 },
  270. // Cooling2
  271. Arm8Extend = new int[8] { 80, 100, 180, 0, 80, -80, 0, 0 },
  272. Arm81Extend = new int[8] { 44, 316, 0, 0, 44, 140, 180, 0 },
  273. };
  274. CurrentPosition = ModuleName.System.ToString();
  275. //CurrentArmA = CurrentArmB = RobotConstant.RobotRetract;
  276. }
  277. protected override void OnRender(DrawingContext drawingContext)
  278. {
  279. base.OnRender(drawingContext);
  280. if (DesignerProperties.GetIsInDesignMode(this))
  281. {
  282. return;
  283. }
  284. if (RobotMoveInfo != null)
  285. {
  286. var needMove = CurrentPosition != RobotMoveInfo.BladeTarget || CurrentAction != RobotMoveInfo.Action;
  287. if (needMove || CurrentPosition == "Both.System")
  288. {
  289. //LogMsg($" RobotMoveInfo, action:{RobotMoveInfo.Action} armTarget:{RobotMoveInfo.ArmTarget} bladeTarget:{RobotMoveInfo.BladeTarget}");
  290. Invoke(() => MoveRobot(RobotMoveInfo));
  291. CurrentAction = RobotMoveInfo.Action;
  292. CurrentPosition = RobotMoveInfo.BladeTarget;
  293. }
  294. }
  295. }
  296. private void UpdateWafer(RobotMoveInfo moveInfo)
  297. {
  298. /*
  299. bool waferPresent = false;
  300. switch (moveInfo.Action)
  301. {
  302. case RobotAction.None:
  303. case RobotAction.Moving:
  304. return;
  305. case RobotAction.Picking:
  306. waferPresent = true;
  307. break;
  308. case RobotAction.Placing:
  309. waferPresent = false;
  310. break;
  311. default:
  312. break;
  313. }*/
  314. switch (moveInfo.ArmTarget)
  315. {
  316. case RobotArm.ArmA:
  317. // WaferPresentA = waferPresent;
  318. break;
  319. case RobotArm.ArmB:
  320. // WaferPresentB = waferPresent;
  321. break;
  322. case RobotArm.Both:
  323. // WaferPresentA = waferPresent;
  324. // WaferPresentB = waferPresent;
  325. break;
  326. default:
  327. break;
  328. }
  329. }
  330. private void Action(int[] angles, Action onComplete = null)
  331. {
  332. var storyboard = new Storyboard();
  333. storyboard.Completed += (s, e) => onComplete?.Invoke();
  334. var needRotate = new List<bool>
  335. {
  336. canvas1.Rotate(storyboard, angles[0], true, MoveTime),
  337. canvas2.Rotate(storyboard,angles[1], true, MoveTime),
  338. canvas3.Rotate(storyboard, angles[2], true, MoveTime),
  339. canvas21.Rotate(storyboard, angles[4], true, MoveTime),
  340. canvas22.Rotate(storyboard, angles[5], true, MoveTime),
  341. canvas23.Rotate(storyboard, angles[6], true, MoveTime),
  342. };
  343. if (needRotate.Any(x => x))
  344. {
  345. storyboard.Begin();
  346. }
  347. else
  348. {
  349. onComplete?.Invoke();
  350. }
  351. }
  352. private void Translate(string station, Action onComplete = null)
  353. {
  354. if (station == null)
  355. return;
  356. if (CanvasRotates.Keys.Any(s => s.Contains(station.Split('.')[1])))
  357. {
  358. canvasRoot.Rotate(CanvasRotates[station.Split('.')[1]]);
  359. }
  360. var translateX = StationPosition.Rotations[station];
  361. TranslateX = translateX;
  362. TranslateTo(onComplete);
  363. }
  364. private void TranslateTo(Action onComplete)
  365. {
  366. if (translate.X != TranslateX)
  367. {
  368. var animation = new DoubleAnimation(translate.X, TranslateX, new Duration(TimeSpan.FromMilliseconds(MoveTime)));
  369. animation.Completed += (s, e) => onComplete?.Invoke();
  370. translate.BeginAnimation(TranslateTransform.XProperty, animation);
  371. }
  372. else
  373. {
  374. onComplete?.Invoke();
  375. }
  376. }
  377. private void MoveRobot(RobotMoveInfo moveInfo)
  378. {
  379. var updateWafer = new Action(() => UpdateWafer(moveInfo));
  380. canvas1.Stop();
  381. canvas2.Stop();
  382. canvas3.Stop();
  383. canvas2.Stop();
  384. canvas21.Stop();
  385. canvas22.Stop();
  386. canvas23.Stop();
  387. var target = moveInfo.BladeTarget;
  388. var arm = moveInfo.ArmTarget;
  389. Action(StationPosition.Home, () => Translate(moveInfo.BladeTarget, () =>
  390. {
  391. var moved = false;
  392. string modulename = moveInfo.BladeTarget.Split('.')[1];
  393. if (moveInfo.ArmTarget == RobotArm.ArmA)
  394. {
  395. switch (moveInfo.Action)
  396. {
  397. case RobotAction.None:
  398. break;
  399. case RobotAction.Picking:
  400. case RobotAction.Placing:
  401. if (modulename == "Flipper")
  402. {
  403. Action(StationPosition.Arm1Extend, updateWafer);
  404. }
  405. else if (modulename == "Buffer" || modulename == "Aligner2")
  406. {
  407. Action(StationPosition.Arm3Extend, updateWafer);
  408. }
  409. else if ( modulename == "Aligner1")
  410. {
  411. Action(StationPosition.Arm4Extend, updateWafer);
  412. }
  413. else if(modulename == "Cooling1")
  414. {
  415. Action(StationPosition.Arm7Extend, updateWafer);
  416. }
  417. else if(modulename == "Cooling2")
  418. {
  419. Action(StationPosition.Arm8Extend, updateWafer);
  420. }
  421. else
  422. {
  423. Action(StationPosition.Arm5Extend, updateWafer);
  424. }
  425. moved = true;
  426. break;
  427. case RobotAction.Moving:
  428. break;
  429. default:
  430. break;
  431. }
  432. }
  433. else if (moveInfo.ArmTarget == RobotArm.ArmB)
  434. {
  435. switch (moveInfo.Action)
  436. {
  437. case RobotAction.None:
  438. break;
  439. case RobotAction.Picking:
  440. case RobotAction.Placing:
  441. if (modulename == "Flipper")
  442. {
  443. Action(StationPosition.Arm2Extend, updateWafer);
  444. }
  445. else if (modulename == "Buffer" || modulename == "Aligner2")
  446. {
  447. Action(StationPosition.Arm31Extend, updateWafer);
  448. }
  449. else if (modulename == "Aligner1" )
  450. {
  451. Action(StationPosition.Arm41Extend, updateWafer);
  452. }
  453. else if (modulename == "Cooling1")
  454. {
  455. Action(StationPosition.Arm71Extend, updateWafer);
  456. }
  457. else if (modulename == "Cooling2")
  458. {
  459. Action(StationPosition.Arm81Extend, updateWafer);
  460. }
  461. else
  462. {
  463. Action(StationPosition.Arm6Extend, updateWafer);
  464. }
  465. moved = true;
  466. break;
  467. case RobotAction.Moving:
  468. break;
  469. default:
  470. break;
  471. }
  472. }
  473. if (!moved && updateWafer != null)
  474. {
  475. updateWafer();
  476. }
  477. }));
  478. }
  479. private void MoveTo(object obj)
  480. {
  481. MoveRobot((RobotMoveInfo)obj);
  482. }
  483. private void Invoke(Action action)
  484. {
  485. Dispatcher.Invoke(action);
  486. }
  487. private void LogMsg(string msg)
  488. {
  489. var source = "ATMRobot";
  490. Console.WriteLine("{0} {1}", source, msg);
  491. }
  492. }
  493. //public class RobotPosition
  494. //{
  495. // public int? X;
  496. // public int Root;
  497. // public int Arm;
  498. // public int Hand;
  499. //}
  500. //public class StationPosition
  501. //{
  502. // public RobotPosition StartPosition;
  503. // public RobotPosition EndPosition;
  504. //}
  505. public class VTMRobotPosition
  506. {
  507. public Dictionary<string, int> Rotations;
  508. public int[] Arm1Extend;
  509. public int[] Arm2Extend;
  510. public int[] Home;
  511. public int[] Arm3Extend;
  512. public int[] Arm4Extend;
  513. public int[] Arm5Extend;
  514. public int[] Arm6Extend;
  515. internal int[] Arm31Extend;
  516. internal int[] Arm41Extend;
  517. public int[] Arm7Extend;
  518. public int[] Arm71Extend;
  519. public int[] Arm8Extend;
  520. public int[] Arm81Extend;
  521. }
  522. public class RobotPosition
  523. {
  524. public int X;
  525. public int Z;
  526. public int Root;
  527. public int Arm;
  528. public int Hand;
  529. }
  530. public class StationPosition
  531. {
  532. public RobotPosition StartPosition;
  533. public RobotPosition EndPosition;
  534. }
  535. public class RobotConstant
  536. {
  537. public const string RobotRetract = "0";
  538. public const string RobotExtend = "1";
  539. public const string UnknownTarget = "Unknown";
  540. }
  541. }