DualArmRobot.xaml.cs 24 KB

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