AtmRobot.xaml.cs 27 KB

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