ATMDualArmRobot.xaml.cs 21 KB

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