BowlerKernel
MobileBaseCadManager.java
Go to the documentation of this file.
1 package com.neuronrobotics.bowlerstudio.creature;
2 
3 import java.io.File;
4 import java.io.IOException;
5 import java.nio.file.Files;
6 import java.nio.file.Paths;
7 import java.nio.file.WatchEvent;
8 import java.text.DecimalFormat;
9 import java.util.ArrayList;
10 import java.util.Collection;
11 import java.util.Comparator;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Set;
17 import java.util.stream.Collectors;
18 
19 import org.eclipse.jgit.api.errors.GitAPIException;
20 import org.eclipse.jgit.api.errors.InvalidRemoteException;
21 import org.eclipse.jgit.api.errors.TransportException;
22 
23 import com.neuronrobotics.bowlerstudio.IssueReportingExceptionHandler;
24 import com.neuronrobotics.bowlerstudio.physics.TransformFactory;
25 import com.neuronrobotics.bowlerstudio.printbed.PrintBedManager;
26 import com.neuronrobotics.bowlerstudio.scripting.ScriptingEngine;
27 import com.neuronrobotics.bowlerstudio.util.FileChangeWatcher;
28 import com.neuronrobotics.bowlerstudio.util.FileWatchDeviceWrapper;
29 import com.neuronrobotics.bowlerstudio.util.IFileChangeListener;
30 import com.neuronrobotics.bowlerstudio.vitamins.VitaminBomManager;
31 import com.neuronrobotics.bowlerstudio.vitamins.Vitamins;
32 import com.neuronrobotics.sdk.addons.kinematics.AbstractKinematicsNR;
33 import com.neuronrobotics.sdk.addons.kinematics.AbstractLink;
34 import com.neuronrobotics.sdk.addons.kinematics.DHLink;
35 import com.neuronrobotics.sdk.addons.kinematics.DHParameterKinematics;
36 import com.neuronrobotics.sdk.addons.kinematics.ILinkConfigurationChangeListener;
37 import com.neuronrobotics.sdk.addons.kinematics.ILinkListener;
38 import com.neuronrobotics.sdk.addons.kinematics.IOnMobileBaseRenderChange;
39 import com.neuronrobotics.sdk.addons.kinematics.IRegistrationListenerNR;
40 import com.neuronrobotics.sdk.addons.kinematics.ITaskSpaceUpdateListenerNR;
41 import com.neuronrobotics.sdk.addons.kinematics.LinkConfiguration;
42 import com.neuronrobotics.sdk.addons.kinematics.MobileBase;
43 import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR;
44 import com.neuronrobotics.sdk.addons.kinematics.parallel.ParallelGroup;
45 import com.neuronrobotics.sdk.common.BowlerAbstractDevice;
46 import com.neuronrobotics.sdk.common.IDeviceConnectionEventListener;
47 import com.neuronrobotics.sdk.pid.PIDLimitEvent;
48 import com.neuronrobotics.sdk.util.ThreadUtil;
49 import eu.mihosoft.vrl.v3d.CSG;
50 import eu.mihosoft.vrl.v3d.FileUtil;
51 import eu.mihosoft.vrl.v3d.parametrics.CSGDatabase;
52 import javafx.beans.property.*;
53 import javafx.scene.transform.Affine;
54 import javafx.application.Platform;
55 
56 public class MobileBaseCadManager implements Runnable {
57 
58  // static
59  private static HashMap<MobileBase, MobileBaseCadManager> cadmap = new HashMap<>();
60  // static
61  // private Object cadForBodyEngine;
62  private MobileBase base;
63  private ArrayList<MobileBaseCadManager> slaves = new ArrayList<MobileBaseCadManager>();
64  // private File cadScript;
65 
66  // private HashMap<DHParameterKinematics, Object> dhCadGen = new HashMap<>();
67  private HashMap<DHParameterKinematics, ArrayList<CSG>> DHtoCadMap = new HashMap<>();
68  private HashMap<LinkConfiguration, ArrayList<CSG>> LinktoCadMap = new HashMap<>();
69  private HashMap<MobileBase, ArrayList<CSG>> BasetoCadMap = new HashMap<>();
70 
71  private boolean cadGenerating = false;
72  private boolean showingStl = false;
73  private ArrayList<CSG> allCad = new ArrayList<>();
74 
75  private boolean bail = false;
76  private IMobileBaseUI ui = null;
77  private static ICadGenerator cadEngineConfiguration = null;
78  private boolean configMode = false;
79  private boolean autoRegen = true;
80  private DoubleProperty pi = new SimpleDoubleProperty(0);
82  // private boolean rendering = false;
83  private Thread renderWrangler = null;
84  private HashMap<String, Object> cadScriptCache = new HashMap<>();
85  private static ArrayList<Runnable> toRun = new ArrayList<Runnable>();
86  private ArrayList<IRenderSynchronizationEvent> rendersync=new ArrayList<>();
87 
89  if(rendersync.contains(ev))
90  return;
91  rendersync.add(ev);
92  }
94  if(rendersync.contains(ev))
95  rendersync.remove(ev);
96  }
98  for(int i=0;i<rendersync.size();i++)
99  try {
100  rendersync.get(i).event(this);
101  }catch(Exception e) {
102 
103  }
104  }
109  public int getCADProgressPercent() {
110  return (int)(Math.round(getProcesIndictor().get()*100));
111  }
112 
113  public boolean isCADFinished() {
114  return getCADProgressPercent()==100;
115  }
116  protected void clear() {
117  // Cad generator
118  cadScriptCache.clear();
119  // clear the csgs from the list
120  for (DHParameterKinematics key : DHtoCadMap.keySet()) {
121  ArrayList<CSG> arrayList = DHtoCadMap.get(key);
122  if (arrayList != null)
123  arrayList.clear();
124  }
125  DHtoCadMap.clear();
126  // celat csg from link conf list
127  for (LinkConfiguration key : LinktoCadMap.keySet()) {
128  ArrayList<CSG> arrayList = LinktoCadMap.get(key);
129  if (arrayList != null)
130  arrayList.clear();
131  }
132  LinktoCadMap.clear();
133  for (MobileBase key : BasetoCadMap.keySet()) {
134  ArrayList<CSG> arrayList = BasetoCadMap.get(key);
135  if (arrayList != null)
136  arrayList.clear();
137  }
138  BasetoCadMap.clear();
139  if (allCad != null)
140  allCad.clear();
141  Vitamins.clear();
142  for (MobileBaseCadManager m : slaves) {
143  m.clear();
144  }
145 
146  }
147 
148  private static class IMobileBaseUIlocal implements IMobileBaseUI {
149 
150  public ArrayList<CSG> list = new ArrayList<>();
151 
152  @Override
153  public void highlightException(File fileEngineRunByName, Throwable ex) {
154  new Exception("Caught here:").printStackTrace();
155  ex.printStackTrace();
156  }
157 
158  @Override
159  public void setAllCSG(Collection<CSG> toAdd, File source) {
160  // TODO Auto-generated method stub
161  // TODO Auto-generated method stub
162  list.clear();
163  list.addAll(toAdd);
164  }
165 
166  @Override
167  public void addCSG(Collection<CSG> toAdd, File source) {
168  // TODO Auto-generated method stub
169  list.addAll(toAdd);
170 
171  }
172 
173  @Override
174  public Set<CSG> getVisibleCSGs() {
175  // TODO Auto-generated method stub
176  return new HashSet<CSG>(list);
177  }
178 
179  @Override
180  public void setSelectedCsg(Collection<CSG> selectedCsg) {
181  // TODO Auto-generated method stub
182 
183  }
184 
185  @Override
186  public void setSelected(Affine rootListener) {
187  // TODO Auto-generated method stub
188 
189  }
190  };
191 
192  public static void runLater(Runnable r) {
193  if (r == null)
194  throw new NullPointerException();
195  toRun.add(r);
196  }
197 
198  // This is the rendering event
199  public void run() {
200  // rendering = true;
201  // String name = base.getScriptingName();
202  if (renderWrangler == null) {
203  renderWrangler = new Thread() {
204  HashMap<DHParameterKinematics, double[]> jointPoses = new HashMap<>();
205  HashMap<Affine, TransformNR> tmp = new HashMap<>();
206  boolean rendering = false;
207  boolean changed = false;
208 
210  @Override
211  public void onIOnMobileBaseRenderChange() {
212  synchronized (jointPoses) {
213  loadJointPose(base, jointPoses);
214  changed = true;
215  }
216 
217  }
218  };
220  @Override
221  public void onFiducialToGlobalUpdate(AbstractKinematicsNR source, TransformNR regestration) {
223  }
224 
225  @Override
226  public void onBaseToFiducialUpdate(AbstractKinematicsNR source, TransformNR regestration) {
228  }
229  };
231  @Override
232  public void event(LinkConfiguration newConf) {
234  }
235 
236  };
237  @Override
238  public void run() {
240 // base.addIHardwareSyncPulseReciver(() -> {
241 // base.removeIOnMobileBaseRenderChange(l);
242 // l.onIOnMobileBaseRenderChange();
243 // });
246  kin.addRegistrationListener(r);
247  }
248  // render on any configuration change
249  addConfL(base,confL);
250  setName("MobileBaseCadManager Render Thread for " + base.getScriptingName());
251  while (base.isAvailable()) {
252  try {
253  do {
254  Thread.sleep(5);
255  } while (rendering || changed == false);
256  } catch (InterruptedException e) {
257  getUi().highlightException(null, e);
258  break;
259  }
260  try {
261 // DecimalFormat df = new DecimalFormat("000.00");
262 // for(DHParameterKinematics kin:jointPoses.keySet().stream()
263 // .sorted((o1, o2) -> {
264 // return o1.getScriptingName().compareTo(o2.getScriptingName());
265 // })
266 // .collect(Collectors.toList())) {
267 // double[] joints = jointPoses.get(kin);
268 // System.err.print("\n"+kin.getScriptingName()+" \t[ ");
269 // for(int i=0;i<kin.getNumberOfLinks();i++) {
270 // System.err.print(" "+df.format(joints[i])+"\t");
271 //
272 // }
273 // System.err.print("]");
274 // }
275 // System.err.print("\n\n");
276  rendering = true;
277 
278  HashMap<DHParameterKinematics, double[]> jointPosesTmp;
279  synchronized (jointPoses) {
280  jointPosesTmp = jointPoses;
281  jointPoses = new HashMap<>();
282  }
283  changed = false;
284  updateMobileBase(base, base.getFiducialToGlobalTransform(), tmp, jointPosesTmp);
285  jointPosesTmp.clear();
286  jointPosesTmp = null;
287 
288  Affine[] iterator = tmp.keySet().stream().toArray(size->new Affine[size]);
289  TransformNR[] vals = tmp.values().stream().toArray(size->new TransformNR[size]);
290  tmp.clear();
291  if (iterator.length > 0) {
292  Platform.runLater(() -> {
293  try {
294  for (int i = 0; i < iterator.length; i++) {
295  Affine af = iterator[i];
296  TransformFactory.nrToAffine(vals[i], af);
297  }
298  } catch (Throwable t) {
299  t.printStackTrace();
300  }
301  rendering = false;
303  });
304  Thread.sleep(32);
305 
306  } else {
307  rendering = false;
308  }
309 
310  if (toRun.size() > 0) {
311  ArrayList<Runnable> t = toRun;
312  toRun = new ArrayList<Runnable>();
313  Platform.runLater(() -> {
314  try {
315  for (int i = 0; i < t.size(); i++) {
316  Runnable runnable = t.get(i);
317  if (runnable != null)
318  runnable.run();
319  }
320  t.clear();
321  } catch (Throwable tr) {
322  tr.printStackTrace();
323  }
324  });
325  Thread.sleep(32);
326  }
327  } catch (Throwable t) {
328  // rendering not availible
329  System.err.println("Exception for render engine " + base.getScriptingName());
330  t.printStackTrace();
331  try {
332  Thread.sleep(100);
333  } catch (InterruptedException e) {
334  break;
335  }
336  }
337 
338  }
339  renderWrangler = null;
340  }
341  private void addConfL(MobileBase base, ILinkConfigurationChangeListener confL2) {
342  if(base==null)
343  return;
345  for(int i=0;i<k.getNumberOfLinks();i++) {
346  k.getAbstractLink(i).addChangeListener(confL2);
347  addConfL(k.getSlaveMobileBase(i),confL2);
348  }
349  }
350  }
351 
352  };
353  renderWrangler.start();
354  }
355 
356  }
357 
358  private void loadJointPose(MobileBase base, HashMap<DHParameterKinematics, double[]> jointPoses) {
360 // ParallelGroup p = base.getParallelGroup(k);
361 // if(p==null) {
362  jointPoses.put(k, k.getCurrentJointSpaceVector());
363 // }else
364 // jointPoses.put(k, p.getCurrentJointSpaceVector(k));
365  for (int i = 0; i < k.getNumberOfLinks(); i++) {
366  MobileBase mb = k.getSlaveMobileBase(i);
367  if (mb != null) {
368  loadJointPose(mb, jointPoses);
369  }
370  }
371  }
372  }
373 
374  private void updateMobileBase(MobileBase b, TransformNR baseLoc, HashMap<Affine, TransformNR> map2,
375  HashMap<DHParameterKinematics, double[]> jointPoses) {
376  TransformNR back =updateBase(b, baseLoc, map2);
377  for (DHParameterKinematics k : b.getAllDHChains()) {
378  updateLimb(k, back, map2, jointPoses);
379  }
380 
381  }
382 
383  private void updateLimb(DHParameterKinematics k, TransformNR baseLoc, HashMap<Affine, TransformNR> map2,
384  HashMap<DHParameterKinematics, double[]> jointPoses) {
385  //updateBase(k, baseLoc, map2);
387  k.setGlobalToFiducialTransform(baseLoc, false);
388  ArrayList<TransformNR> ll = k.getChain().getChain(jointPoses.get(k));
389 
390  for (int i = 0; i < ll.size(); i++) {
391  int index = i;
392  Affine a;
393  DHLink dhLink = k.getChain().getLinks().get(index);
394  if (dhLink.getListener() == null) {
395  dhLink.setListener(new Affine());
396  }
397  try {
398  a = (Affine) dhLink.getListener();
399  } catch (java.lang.ClassCastException ex) {
400  a = new Affine();
401  dhLink.setListener(a);
402  }
403  AbstractLink abstractLink = k.getAbstractLink(i);
404  if (abstractLink.getGlobalPositionListener() == null) {
405  abstractLink.setGlobalPositionListener(a);
406  }
407 
408  Affine af = a;
409  TransformNR nr = ll.get(index);
410  if (nr != null && af != null)
411  map2.put(af, nr);
412  if (k.getSlaveMobileBase(i) != null) {
413  updateMobileBase(k.getSlaveMobileBase(i), nr, map2, jointPoses);
414  }
415  }
416  k.setGlobalToFiducialTransform(previous, false);
417  }
418 
419  private TransformNR updateBase(MobileBase base, TransformNR baseLoc, HashMap<Affine, TransformNR> map2) {
420  if (base == null)
421  return null;
423 
424  try {
425  base.setGlobalToFiducialTransform(baseLoc, false);
426  } catch (Exception e) {
427  e.printStackTrace();
428  throw new RuntimeException("MB " + base.getScriptingName() + ", " + e.getMessage());
429  }
430 
431  TransformNR forwardOffset = base.forwardOffset(new TransformNR());
432  if (base.getRootListener() == null) {
433  base.setRootListener(new Affine());
434  }
435  if (forwardOffset != null )
436  map2.put((Affine) base.getRootListener(), forwardOffset);
438  if (k.getRootListener() == null) {
439  k.setRootListener(new Affine());
440  }
441  TransformNR fo = k.forwardOffset(new TransformNR());
442  if (fo != null )
443  map2.put((Affine) k.getRootListener(), fo);
444  }
445  base.setGlobalToFiducialTransform(previous, false);
446  return forwardOffset;
447  }
448 
450  this.setUi(myUI);
452  }
453 
454 // public File getCadScript() {
455 // return cadScript;
456 // }
457 
458 // public void setCadScript(File cadScript) {
459 // if (cadScript == null)
460 // return;
461 // FileWatchDeviceWrapper.watch(base, cadScript, cadWatcher);
462 //
463 // this.cadScript = cadScript;
464 // }
465  private Object scriptFromFileInfo(String name,String[] args, Runnable r) throws Throwable{
466  String key = args[0] + ":" + args[1];
467  try {
468  File f = ScriptingEngine.fileFromGit(args[0], args[1]);
469  if (cadScriptCache.get(key) == null) {
470  try {
471  System.err.println(
472  "Building the compiled CAD script for " + key + " " + base + " " + base.getScriptingName());
474  } catch (Throwable e) {
475  getUi().highlightException(f, e);
476  throw e;
477  }
479  Exception ex = new Exception("CAD script declared here and regenerated");
481 
482  @Override
483  public void onFileChange(File fileThatChanged, WatchEvent event) {
484  if(cadGenerating)
485  return;
486  try {
487  System.err.println("Clearing the compiled CAD script for " + key);
488  cadScriptCache.remove(key);
489  ex.printStackTrace();
490  r.run();
491  } catch (Exception e) {
492  getUi().highlightException(f, e);
493  }
494  }
495 
496  @Override
497  public void onFileDelete(File fileThatIsDeleted) {
498  cadScriptCache.remove(key);
499  }
500  };
501  watcher.addIFileChangeListener(l);
503 
504  @Override
505  public void onDisconnect(BowlerAbstractDevice source) {
506  watcher.removeIFileChangeListener(l);
507  }
508 
509  @Override
510  public void onConnect(BowlerAbstractDevice source) {
511  // TODO Auto-generated method stub
512 
513  }
514  });
515  }
516  return cadScriptCache.get(key);
517  } catch (GitAPIException | IOException e) {
518  // TODO Auto-generated catch block
519  e.printStackTrace();
520  }
521  throw new RuntimeException("File Missing!");
522 
523  }
524 
525  private void closeScriptFromFileInfo(String[] args) {
526  String key = args[0] + ":" + args[1];
527  cadScriptCache.remove(key);
528  try {
529  File f = ScriptingEngine.fileFromGit(args[0], args[1]);
531 
532  } catch (InvalidRemoteException e) {
533  // TODO Auto-generated catch block
534  e.printStackTrace();
535  } catch (TransportException e) {
536  // TODO Auto-generated catch block
537  e.printStackTrace();
538  } catch (GitAPIException e) {
539  // TODO Auto-generated catch block
540  e.printStackTrace();
541  } catch (IOException e) {
542  // TODO Auto-generated catch block
543  e.printStackTrace();
544  }
545 
546  }
547 
548  private IgenerateBody getIgenerateBody(MobileBase b) throws Throwable{
549  if (configMode)
550  return getConfigurationDisplay();
551  Object cadForBodyEngine = scriptFromFileInfo(b.getScriptingName(),b.getGitCadEngine(), () -> {
552  run();
553  generateCad();
554  });
555  if (IgenerateBody.class.isInstance(cadForBodyEngine)) {
556  return (IgenerateBody) cadForBodyEngine;
557  }
558  return null;
559  }
560 
561  private IgenerateCad getIgenerateCad(DHParameterKinematics dh) throws Throwable{
562  if (configMode)
563  return getConfigurationDisplay();
564  Object cadForBodyEngine = scriptFromFileInfo(dh.getScriptingName(),dh.getGitCadEngine(), () -> {
565  run();
566  generateCad();
567  });
568  if (IgenerateCad.class.isInstance(cadForBodyEngine)) {
569  return (IgenerateCad) cadForBodyEngine;
570  }
571  return null;
572  }
573 
574  public IgenerateBed getIgenerateBed() throws Throwable{
575  Object cadForBodyEngine = scriptFromFileInfo(base.getScriptingName(),base.getGitCadEngine(), () -> {
576  run();
577  });
578  if (IgenerateBed.class.isInstance(cadForBodyEngine)) {
579  return (IgenerateBed) cadForBodyEngine;
580  }
581  return null;
582  }
583 
584  private ICadGenerator getConfigurationDisplay()throws Throwable {
585  if (cadEngineConfiguration == null) {
586  Object cadForBodyEngine = scriptFromFileInfo("ConfigDisplay",new String[] {
587  "https://github.com/CommonWealthRobotics/DHParametersCadDisplay.git", "dhcad.groovy" }, () -> {
588  MobileBaseCadManager mobileBaseCadManager = null;
589  try {
590  for (MobileBase manager : cadmap.keySet()) {
591  mobileBaseCadManager = cadmap.get(manager);
592  if (mobileBaseCadManager.autoRegen)
593  if (mobileBaseCadManager.configMode)
594  mobileBaseCadManager.generateCad();
595  }
596  } catch (Exception e) {
597  if (mobileBaseCadManager != null)
598  mobileBaseCadManager.getUi().highlightException(null, e);
599  }
600  });
601  if (ICadGenerator.class.isInstance(cadForBodyEngine))
602  cadEngineConfiguration = (ICadGenerator) cadForBodyEngine;
603  }
604  return cadEngineConfiguration;
605  }
606 
607  public ArrayList<CSG> generateBody() {
608  return generateBody(getMobileBase(), true);
609  }
610 
611  public ArrayList<CSG> generateBody(MobileBase base, boolean clear) {
612  if (!base.isAvailable())
613  throw new RuntimeException("Device " + base.getScriptingName() + " is not connected, can not generate cad");
614 
615  getProcesIndictor().set(0);
616  if (clear) {
617  getAllCad().clear();
618  setAllCad(new ArrayList<>());
619  }
620  System.gc();
621  MobileBase device = base;
622  if (getBasetoCadMap().get(device) == null) {
623  getBasetoCadMap().put(device, new ArrayList<CSG>());
624  }
625 
626  getProcesIndictor().set(0.1);
627  try {
628 
629  if (showingStl) {
630  // skip the regen
631  for (CSG c : getBasetoCadMap().get(device)) {
632  getAllCad().add(c);
633  }
634  } else {
635  if (!bail) {
636 
637  ArrayList<CSG> newcad = null;
638  try {
639  newcad = getIgenerateBody(device).generateBody(device);
640  } catch (Throwable t) {
641  getUi().highlightException(null, t);
642  }
643  if (newcad == null) {
644  newcad = new ArrayList<CSG>();
645  }
646  if (newcad.size() == 0) {
647  newcad = getConfigurationDisplay().generateBody(device);
648  }
649  if (device.isAvailable()) {
650  for (CSG c : newcad) {
651  getAllCad().add(c);
652  }
653  ui.addCSG(newcad, getCadScriptFromMobileBase(device));
654  }
655  } else
656  getUi().highlightException(null, new Exception());
657  ArrayList<CSG> arrayList = getBasetoCadMap().get(device);
658  if (clear) {
659  arrayList.clear();
660  System.gc();
661  }
662  for (CSG c : getAllCad()) {
663  arrayList.add(c);
664  }
665  new Thread(() -> {
666  Thread.currentThread().setUncaughtExceptionHandler(new IssueReportingExceptionHandler());
667 
668  localGetBaseCad(device);// load the cad union in a thread to
669  // make it ready for physics
670  }).start();
671  }
672  } catch (Throwable e) {
674  }
675  System.out.println("Displaying Body");
676  getProcesIndictor().set(0.35);
677  // clears old robot and places base
678  getUi().setAllCSG(getBasetoCadMap().get(device), getCadScriptFromMobileBase(device));
679  System.out.println("Rendering limbs");
680  getProcesIndictor().set(0.4);
681  ArrayList<DHParameterKinematics> limbs = base.getAllDHChains();
682  double numLimbs = limbs.size();
683  int i = 0;
684  for (DHParameterKinematics l : limbs) {
685  if (getDHtoCadMap().get(l) == null) {
686  getDHtoCadMap().put(l, new ArrayList<CSG>());
687  }
688  ArrayList<CSG> arrayList = getDHtoCadMap().get(l);
689  int j = 0;
690  boolean isAvailible = device.isAvailable();
691  if (showingStl || !isAvailible) {
692  for (CSG csg : arrayList) {
693  getAllCad().add(csg);
695  set(base, (int) i, (int) j);
696  j += 1;
697  }
698  } else {
699  if (clear) {
700  arrayList.clear();
701  System.gc();
702  }
703  ArrayList<CSG> linksCad = generateCad(l);
704 
705  for (CSG csg : linksCad) {
706 
707  getAllCad().add(csg);
708  arrayList.add(csg);
710  j += 1;
711 
712  }
713 
714  }
715 
716  i += 1;
717 
718  }
719  for (MobileBaseCadManager m : slaves) {
720  getAllCad().addAll(m.generateBody(m.base, false));
721  }
722  showingStl = false;
723  getProcesIndictor().set(1);
724  // PhysicsEngine.clear();
725  // MobileBasePhysicsManager m = new MobileBasePhysicsManager(base,
726  // baseCad, getSimplecad());
727  // PhysicsEngine.startPhysicsThread(50);
728  // return PhysicsEngine.getCsgFromEngine();
729  System.gc();
730  return getAllCad();
731  }
732 
734  try {
736  } catch (Exception e) {
737  // TODO Auto-generated catch block
738  e.printStackTrace();
739  }
740  return null;
741  }
742 
744  try {
745  return ScriptingEngine.fileFromGit(device.getGitCadEngine()[0], device.getGitCadEngine()[1]);
746  } catch (Exception e) {
747  // TODO Auto-generated catch block
748  e.printStackTrace();
749  }
750  return null;
751  }
752 
753  private void set(MobileBase base, int limb, int link) {
754  ArrayList<DHParameterKinematics> limbs = base.getAllDHChains();
755  int numLimbs = limbs.size();
756  if (limb >= numLimbs) {
757  limb = numLimbs - 1;
758  }
759  DHParameterKinematics dh = limbs.get(limb);
760  double partsTotal = numLimbs * dh.getNumberOfLinks();
761  double progress = ((double) ((limb * dh.getNumberOfLinks()) + link)) / partsTotal;
762  // System.out.println("Cad progress " + progress + " limb " + limb + " link " +
763  // link + " total parts " + partsTotal);
764  getProcesIndictor().set(0.333 + (2 * (progress / 3)));
765  }
766 
768  LinkConfiguration conf = null;
769  for (LinkConfiguration c : LinktoCadMap.keySet()) {
770  for (CSG cadTest : LinktoCadMap.get(c)) {
771  if (cadTest == cad) {
772  conf = c;
773  }
774  }
775  }
776  return conf;
777  }
778 
779  public ArrayList<File> generateStls(MobileBase base, File baseDirForFiles, boolean kinematic) throws Exception {
780  File dir = new File(baseDirForFiles.getAbsolutePath() + "/" + base.getScriptingName());
781  if (!dir.exists())
782  dir.mkdirs();
783  IgenerateBed bed=null;
784  String baseURL = base.getGitSelfSource()[0];
785  File baseWorkspaceFile = ScriptingEngine.getRepositoryCloneDirectory(baseURL);
786  bed = getPrintBed(dir, bed, baseWorkspaceFile);
787  if (bed == null || kinematic) {
788  return _generateStls(base, dir, kinematic);
789  }
790 
791  System.out.println("Found arrangeBed API in CAD engine");
792  List<CSG> totalAssembly = bed.arrangeBed(base);
793  getUi().setAllCSG(totalAssembly, getCadScriptFromMobileBase(base));
794 
795 
796  return new CadFileExporter(getUi()).generateManufacturingParts(totalAssembly, dir);
797  }
798  public IgenerateBed getPrintBed(File baseDirForFiles, IgenerateBed bed, File baseWorkspaceFile) throws IOException {
799  File bomCSV = new File(baseWorkspaceFile.getAbsolutePath()+"/"+VitaminBomManager.MANUFACTURING_BOM_CSV);
800  if(bomCSV.exists()) {
801 
802  File file = new File(baseDirForFiles.getAbsolutePath()+"/bom.csv");
803  if(file.exists())
804  file.delete();
805  Files.copy(bomCSV.toPath(),file.toPath());
806  }
807  File bom = new File(baseWorkspaceFile.getAbsolutePath()+"/"+VitaminBomManager.MANUFACTURING_BOM_JSON);
808  if(bom.exists()) {
809  File file = new File(baseDirForFiles.getAbsolutePath()+"/bom.json");
810  if(file.exists())
811  file.delete();
812  Files.copy(bom.toPath(),file.toPath());
813  }
814  try{
815  bed= getIgenerateBed();
816  }catch(Throwable T) {
817  throw new RuntimeException(T.getMessage());
818  }
819  if(bed == null) {
820  File printArrangment = new File(baseWorkspaceFile.getAbsolutePath()+"/"+PrintBedManager.file);
821  if(printArrangment.exists()) {
822  bed = new UserManagedPrintBed(printArrangment,this);
823  }
824  }
825  return bed;
826  }
827 
828  public ArrayList<File> _generateStls(MobileBase base, File baseDirForFiles, boolean kinematic) throws IOException {
829  ArrayList<File> allCadStl = new ArrayList<>();
830  ArrayList<DHParameterKinematics> limbs = base.getAllDHChains();
831  double numLimbs = limbs.size();
832  int i;
833  // Start by generating the legs using the DH link based generator
834  ArrayList<CSG> totalAssembly = new ArrayList<>();
835  double offset = 0;
836  for (i = 0; i < limbs.size(); i += 1) {
837 
838  double progress = (1.0 - ((numLimbs - i) / numLimbs)) / 2;
839  getProcesIndictor().set(progress);
840 
841  DHParameterKinematics l = limbs.get(i);
842  ArrayList<CSG> parts = getDHtoCadMap().get(l);
843  for (int j = 0; j < parts.size(); j++) {
844  CSG csg = parts.get(j);
845  String name = csg.getName();
846  try {
847  CSG tmp;
848  if (!kinematic)
849  csg = csg.prepForManufacturing();
850  if (csg != null) {
851  if (!kinematic) {
852  tmp = csg.toXMax().toYMax();
853  } else {
854  tmp = csg;
855  }
856  if (totalAssembly.size() > 0 && !kinematic)
857  totalAssembly.add(tmp.movey(.5 + totalAssembly.get(totalAssembly.size() - 1).getMaxY()
858  + Math.abs(csg.getMinY())));
859  else
860  totalAssembly.add(tmp);
861  LinkConfiguration conf = getLinkConfiguration(parts.get(j));
862  if(conf!=null) {
863  String linkNum = conf.getLinkIndex() + "_Link_";
864 
865  File dir = new File(baseDirForFiles.getAbsolutePath() + "/" + base.getScriptingName() + "/"
866  + l.getScriptingName());
867  if (!dir.exists())
868  dir.mkdirs();
869 
870  File stl = new File(
871  dir.getAbsolutePath() + "/" + linkNum + name + "_limb_" + i + "_Part_" + j + ".stl");
872  System.out.println("Writing STL for " + name+" to "+stl.getAbsolutePath());
873  FileUtil.write(Paths.get(stl.getAbsolutePath()), tmp.toStlString());
874  allCadStl.add(stl);
875  // totalAssembly.add(tmp);
876  getUi().setAllCSG(totalAssembly, getCadScriptFromMobileBase(base));
877  set(base, i, j);
878  }else {
879  System.err.println("ERROR "+parts.get(j).getName()+" has no link associated ");
880  }
881  }
882  } catch (Exception ex) {
884  }
885  // legAssembly.setManufactuing(new PrepForManufacturing() {
886  // public CSG prep(CSG arg0) {
887  // return null;
888  // }
889  // });
890  }
891  // offset =
892  // -2-((legAssembly.get(legAssembly.size()-1).getMaxX()+legAssembly.get(legAssembly.size()-1).getMinX())*i);
893  // legAssembly=legAssembly.movex(offset);
894 
895  }
896 
897  int link = 0;
898  // now we genrate the base pieces
899  for (CSG csg : getBasetoCadMap().get(base)) {
900  String name = csg.getName();
901  try {
902  if (!kinematic)
903  csg = csg.prepForManufacturing();
904  if (csg != null) {
905  if (!kinematic) {
906  csg = csg.toYMin().movex(-2 - csg.getMaxX() + offset);
907  }
908  File dir = new File(baseDirForFiles.getAbsolutePath() + "/" + base.getScriptingName() + "/");
909  if (!dir.exists())
910  dir.mkdirs();
911  File stl = new File(dir.getAbsolutePath() + "/" + name + "_Body_part_" + link + ".stl");
912  FileUtil.write(Paths.get(stl.getAbsolutePath()), csg.toStlString());
913  allCadStl.add(stl);
914  totalAssembly.add(csg);
915  getUi().setAllCSG(totalAssembly, getCadScriptFromMobileBase(base));
916  link++;
917  }
918  } catch (Exception ex) {
920  }
921  }
922  // ui.setCsg(BasetoCadMap.get(base),getCadScript());
923  // for(CSG c: DHtoCadMap.get(base.getAllDHChains().get(0))){
924  // ui.addCsg(c,getCadScript());
925  // }
926  showingStl = true;
927  getProcesIndictor().set(1);
928  return allCadStl;
929  }
930 
932  return base;
933  }
934 
935  public void setMobileBase(MobileBase b) {
936  for (MobileBase mb : cadmap.keySet()) {
937  if (mb == b)
938  throw new RuntimeException("Can not duplicat mobile base");
939  for (DHParameterKinematics dh : mb.getAllDHChains()) {
940  for (int i = 0; i < dh.getNumberOfLinks(); i++) {
941  if (dh.getSlaveMobileBase(i) == b)
942  throw new RuntimeException("Can not duplicat mobile base!!");
943  }
944  }
945  }
946  this.base = b;
947  cadmap.put(base, this);
948  MobileBaseLoader.get(base);// load the dependant scripts
950  base.setRenderWrangler(this);
952  k.setRenderWrangler(this);
953  }
954  run();
955  // new Exception("Adding the mysteryListener
956  // "+b.getScriptingName()).printStackTrace();
957 
959 
960  @Override
961  public void onDisconnect(BowlerAbstractDevice arg0) {
962  if (arg0 != base) {
963  new Exception("This listener called from the wrong device!! " + arg0.getScriptingName())
964  .printStackTrace();
965  return;
966  }
967  base.setRenderWrangler(null);
969  k.setRenderWrangler(null);
970  }
971  bail = true;
972  clear();
973  cadmap.remove(base);
974  slaves.clear();
975  master = null;
976  }
977 
978  @Override
979  public void onConnect(BowlerAbstractDevice arg0) {
980  // TODO Auto-generated method stub
981 
982  }
983  });
984  }
985 
992  public ArrayList<CSG> generateCad(DHParameterKinematics dh) {
993  ArrayList<CSG> dhLinks = new ArrayList<>();
994 
995  try {
996  IgenerateCad generatorToUse = getConfigurationDisplay();
997  Object object = getIgenerateCad(dh);
998  if (object != null && !configMode) {
999  if (IgenerateCad.class.isInstance(object))
1000  generatorToUse = (IgenerateCad) object;
1001  }
1002  int j = 0;
1004  if (dhtest == dh)
1005  break;
1006  j++;
1007  }
1008  for (int i = 0; i < dh.getNumberOfLinks(); i++) {
1009  set(base, (int) j, (int) i);
1010 
1011  if (!bail) {
1012  ArrayList<CSG> newcad = null;
1013  try {
1014  newcad = generatorToUse.generateCad(dh, i);
1015  } catch (Throwable t) {
1016  getUi().highlightException(null, t);
1017  }
1018  if (newcad == null) {
1019  newcad = new ArrayList<CSG>();
1020  }
1021  if (newcad.size() == 0) {
1022  newcad = getConfigurationDisplay().generateCad(dh, i);
1023  }
1024  getUi().addCSG(newcad, getCadScriptFromLimnb(dh));
1025  LinkConfiguration configuration = dh.getLinkConfiguration(i);
1026  if (getLinktoCadMap().get(configuration) == null) {
1027  getLinktoCadMap().put(configuration, new ArrayList<>());
1028  } else
1029  getLinktoCadMap().get(configuration).clear();
1030  for (CSG c : newcad) {
1031  dhLinks.add(c);
1032  getLinktoCadMap().get(configuration).add(c);// add to
1033  // the
1034  // regestration
1035  // storage
1036  }
1037  AbstractLink link = dh.getFactory().getLink(configuration);
1038  link.addLinkListener(new ILinkListener() {
1039 
1040  @Override
1041  public void onLinkPositionUpdate(AbstractLink arg0, double arg1) {
1042  // TODO Auto-generated method stub
1043 
1044  }
1045 
1046  @Override
1047  public void onLinkLimit(AbstractLink arg0, PIDLimitEvent arg1) {
1048  if (getAutoRegen())
1049  selectCsgByLimb(base, dh);
1050 
1051  }
1052  });
1053  DHLink dhl = dh.getDhLink(i);
1054  if (dhl.getSlaveMobileBase() != null) {
1055  ArrayList<CSG> slParts = generateBody(dhl.getSlaveMobileBase(), false);
1056  dhLinks.addAll(slParts);
1057  }
1058  // ArrayList<CSG> generateBody(MobileBase base)
1059  }
1060  }
1061 
1062  } catch (Throwable e) {
1063  e.printStackTrace();
1065  }
1066  return dhLinks;
1067  }
1068 
1070  try {
1071 
1072  ArrayList<CSG> csg = MobileBaseCadManager.get(base).getBasetoCadMap().get(base);
1073  getUi().setSelectedCsg(csg);
1074  } catch (Exception ex) {
1075  // getUi().highlightException(null, ex);
1076  System.err.println("Base not loaded yet");
1077  }
1078 
1079  }
1080 
1082  try {
1083 
1084 // ArrayList<CSG> limCad = MobileBaseCadManager.get(base).getDHtoCadMap().get(limb);
1085 // getUi().setSelectedCsg(limCad);
1086  getUi().setSelected((Affine) limb.getRootListener());
1087  } catch (Exception ex) {
1088  // getUi().highlightException(null, ex);
1089  System.err.println("Limb not loaded yet");
1090  }
1091  }
1092 
1094  try {
1095 
1096  ArrayList<CSG> limCad = MobileBaseCadManager.get(base).getLinktoCadMap().get(limb);
1097  getUi().setSelectedCsg(limCad);
1098  } catch (Exception ex) {
1099  System.err.println("Limb not loaded yet");
1100  }
1101  }
1102 
1103  public void generateCad() {
1104  if (cadGenerating || !getAutoRegen())
1105  return;
1106  cadGenerating = true;
1107  // new RuntimeException().printStackTrace();
1108  // new Exception().printStackTrace();
1109  new Thread() {
1110  @Override
1111  public void run() {
1112  // Thread.currentThread().setUncaughtExceptionHandler(new
1113  // IssueReportingExceptionHandler());
1114 
1115  System.out.print("\r\nGenerating CAD...\r\n");
1116  setName("MobileBaseCadManager Generating cad Thread ");
1117  // new Exception().printStackTrace();
1118  if (master != null) {
1119  for (int i = 0; i < allCad.size(); i++)
1120  master.allCad.remove(allCad.get(i));
1121  }
1122  MobileBase device = base;
1124 
1125  try {
1126  setAllCad(generateBody(device, true));
1127  } catch (Exception e) {
1128 
1130  }
1131 
1132  if (master != null) {
1133  for (int i = 0; i < allCad.size(); i++)
1134  master.allCad.add(allCad.get(i));
1136  } else
1138  cadGenerating = false;
1139  System.out.print("\r\nDone Generating CAD! num parts: " + allCad.size() + "\r\n");
1140  try {
1141  Thread.sleep(100);
1142  } catch (InterruptedException e) {
1143  // TODO Auto-generated catch block
1144  e.printStackTrace();
1145  }
1146  getProcesIndictor().set(1);
1147  // System.gc();
1148  }
1149  }.start();
1150  }
1151 
1152  public void onTabClosing() {
1153 
1154  }
1155 
1156  public void setGitCadEngine(String gitsId, String file, DHParameterKinematics dh)
1157  throws InvalidRemoteException, TransportException, GitAPIException, IOException {
1158  closeScriptFromFileInfo(dh.getGitCadEngine());
1159  dh.setGitCadEngine(new String[] { gitsId, file });
1160  }
1161 
1162  public void setGitCadEngine(String gitsId, String file, MobileBase device)
1163  throws InvalidRemoteException, TransportException, GitAPIException, IOException {
1164  closeScriptFromFileInfo(device.getGitCadEngine());
1165  device.setGitCadEngine(new String[] { gitsId, file });
1166  }
1167 
1168  public ArrayList<CSG> getAllCad() {
1169  return allCad;
1170  }
1171 
1172  public void setAllCad(ArrayList<CSG> allCad) {
1173  for (CSG part : allCad)
1174  for (String p : part.getParameters()) {
1175  CSGDatabase.addParameterListener(p, (arg0, arg1) -> {
1176  // generateCad(); //TODO Undo this after debugging
1177  });
1178  }
1179 
1180  if (this.allCad != null && this.allCad != allCad)
1181  this.allCad.clear();
1182  this.allCad = allCad;
1183  }
1184 
1185  public static MobileBaseCadManager get(MobileBase device, IMobileBaseUI ui) {
1186  if (cadmap.get(device) == null) {
1187  // new RuntimeException("No Mobile Base Cad Manager UI
1188  // specified").printStackTrace();
1189  MobileBaseCadManager mbcm = new MobileBaseCadManager(device, ui);
1190 
1191  }
1192  MobileBaseCadManager mobileBaseCadManager = cadmap.get(device);
1193  if (!IMobileBaseUIlocal.class.isInstance(ui)
1194  && IMobileBaseUIlocal.class.isInstance(mobileBaseCadManager.getUi()))
1195  mobileBaseCadManager.setUi(ui);
1196 
1197  return mobileBaseCadManager;
1198  }
1199 
1201  this.master = master;
1202  }
1203 
1204  public static MobileBaseCadManager get(MobileBase device) {
1205  if (cadmap.get(device) == null) {
1206  for (MobileBase mb : cadmap.keySet()) {
1207  for (DHParameterKinematics kin : mb.getAllDHChains()) {
1208  for (int i = 0; i < kin.getNumberOfLinks(); i++) {
1209  MobileBase m = kin.getDhLink(i).getSlaveMobileBase();
1210  if (m == device) {
1211  return get(mb);
1212  }
1213  }
1214  }
1215  }
1216  IMobileBaseUIlocal ui2 = new IMobileBaseUIlocal();
1217  device.addConnectionEventListener(new IDeviceConnectionEventListener() {
1218 
1219  @Override
1220  public void onDisconnect(BowlerAbstractDevice source) {
1221  // TODO Auto-generated method stub
1222  ui2.list.clear();
1223 
1224  }
1225 
1226  @Override
1227  public void onConnect(BowlerAbstractDevice source) {
1228  // TODO Auto-generated method stub
1229 
1230  }
1231  });
1232 
1233  return get(device, ui2);
1234  }
1235  return cadmap.get(device);
1236  }
1237 
1238  public static HashMap<LinkConfiguration, ArrayList<CSG>> getSimplecad(MobileBase device) {
1239  return get(device).LinktoCadMap;
1240  }
1241 
1242  private ArrayList<CSG> localGetBaseCad(MobileBase device) {
1243 
1244  return BasetoCadMap.get(device);
1245  }
1246 
1247  public static ArrayList<CSG> getBaseCad(MobileBase device) {
1248  return get(device).localGetBaseCad(device);
1249  }
1250 
1251  public DoubleProperty getProcesIndictor() {
1252  return pi;
1253  }
1254 
1255  public void setProcesIndictor(DoubleProperty pi) {
1256  this.pi = pi;
1257  }
1258 
1259  public HashMap<MobileBase, ArrayList<CSG>> getBasetoCadMap() {
1260  return BasetoCadMap;
1261  }
1262 
1263  public void setBasetoCadMap(HashMap<MobileBase, ArrayList<CSG>> basetoCadMap) {
1264  BasetoCadMap = basetoCadMap;
1265  }
1266 
1267  public HashMap<DHParameterKinematics, ArrayList<CSG>> getDHtoCadMap() {
1268  return DHtoCadMap;
1269  }
1270 
1271  public void setDHtoCadMap(HashMap<DHParameterKinematics, ArrayList<CSG>> dHtoCadMap) {
1272  DHtoCadMap = dHtoCadMap;
1273  }
1274 
1275  public HashMap<LinkConfiguration, ArrayList<CSG>> getLinktoCadMap() {
1276  return LinktoCadMap;
1277  }
1278 
1279  public void setLinktoCadMap(HashMap<LinkConfiguration, ArrayList<CSG>> linktoCadMap) {
1280  LinktoCadMap = linktoCadMap;
1281  }
1282 
1283  public boolean getAutoRegen() {
1284  return autoRegen;
1285  }
1286 
1287  public void setAutoRegen(boolean autoRegen) {
1288  this.autoRegen = autoRegen;
1289  for (MobileBaseCadManager m : slaves) {
1290  m.setAutoRegen(autoRegen);
1291  }
1292  }
1293 
1295  return ui;
1296  }
1297 
1298  public void setUi(IMobileBaseUI ui) {
1299  this.ui = ui;
1300  }
1301 
1302  public void setConfigurationViewerMode(boolean b) {
1303  System.out.println("Setting config mode " + b);
1304  configMode = b;
1305  for (MobileBaseCadManager m : slaves) {
1306  m.setConfigurationViewerMode(b);
1307  }
1308  }
1309  public void invalidateModelCache() {
1310  // TODO Auto-generated method stub
1311 
1312  }
1313 
1314 }
ArrayList< File > generateManufacturingParts(List< CSG > totalAssembly, File baseDirForFiles)
ArrayList< File > generateStls(MobileBase base, File baseDirForFiles, boolean kinematic)
void removeIRenderSynchronizationEvent(IRenderSynchronizationEvent ev)
HashMap< LinkConfiguration, ArrayList< CSG > > LinktoCadMap
HashMap< DHParameterKinematics, ArrayList< CSG > > DHtoCadMap
void setDHtoCadMap(HashMap< DHParameterKinematics, ArrayList< CSG >> dHtoCadMap)
void setBasetoCadMap(HashMap< MobileBase, ArrayList< CSG >> basetoCadMap)
void loadJointPose(MobileBase base, HashMap< DHParameterKinematics, double[]> jointPoses)
static MobileBaseCadManager get(MobileBase device, IMobileBaseUI ui)
HashMap< LinkConfiguration, ArrayList< CSG > > getLinktoCadMap()
TransformNR updateBase(MobileBase base, TransformNR baseLoc, HashMap< Affine, TransformNR > map2)
void selectCsgByLimb(MobileBase base, DHParameterKinematics limb)
ArrayList< CSG > generateBody(MobileBase base, boolean clear)
ArrayList< File > _generateStls(MobileBase base, File baseDirForFiles, boolean kinematic)
void setGitCadEngine(String gitsId, String file, DHParameterKinematics dh)
void updateMobileBase(MobileBase b, TransformNR baseLoc, HashMap< Affine, TransformNR > map2, HashMap< DHParameterKinematics, double[]> jointPoses)
static HashMap< LinkConfiguration, ArrayList< CSG > > getSimplecad(MobileBase device)
void setGitCadEngine(String gitsId, String file, MobileBase device)
HashMap< DHParameterKinematics, ArrayList< CSG > > getDHtoCadMap()
void selectCsgByLink(MobileBase base, LinkConfiguration limb)
void updateLimb(DHParameterKinematics k, TransformNR baseLoc, HashMap< Affine, TransformNR > map2, HashMap< DHParameterKinematics, double[]> jointPoses)
IgenerateBed getPrintBed(File baseDirForFiles, IgenerateBed bed, File baseWorkspaceFile)
void setLinktoCadMap(HashMap< LinkConfiguration, ArrayList< CSG >> linktoCadMap)
Object scriptFromFileInfo(String name, String[] args, Runnable r)
static HashMap< MobileBase, MobileBaseCadManager > cadmap
static Object inlineFileScriptRun(File f, ArrayList< Object > args)
static File fileFromGit(String remoteURI, String fileInRepo)
static FileChangeWatcher watch(File fileToWatch)
void setGlobalToFiducialTransform(TransformNR frameToBase, boolean fireUpdate)
ArrayList< TransformNR > getChain(double[] jointSpaceVector)
Definition: DHChain.java:262
void addIOnMobileBaseRenderChange(IOnMobileBaseRenderChange l)
ArrayList< DHParameterKinematics > getAllDHChains()
void addConnectionEventListener(final IDeviceConnectionEventListener l)
CSG prepForManufacturing()
Definition: CSG.java:179
CSG toYMax(CSG target)
Definition: CSG.java:348
CSG movey(Number howFarToMove)
Definition: CSG.java:429
String toStlString()
Definition: CSG.java:1370
CSG toXMax(CSG target)
Definition: CSG.java:328
static void write(Path p, String s)
Definition: FileUtil.java:63
static void addParameterListener(String key, IParameterChanged l)
default void setCsg(CSG toAdd, File source)
void setSelectedCsg(Collection< CSG > selectedCsg)
void setAllCSG(Collection< CSG > toAdd, File source)
void addCSG(Collection< CSG > toAdd, File source)
default void addCsg(CSG toAdd, File source)
void highlightException(File fileEngineRunByName, Throwable ex)
ArrayList< CSG > arrangeBed(MobileBase base)
ArrayList< CSG > generateBody(MobileBase base)
ArrayList< CSG > generateCad(DHParameterKinematics dh, int linkIndex)