AtmRobot.xaml.cs 23 KB

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