BowlerKernel
VirtualGenericPIDDevice.java
Go to the documentation of this file.
1 package com.neuronrobotics.sdk.pid;
2 
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 
6 import com.neuronrobotics.sdk.addons.kinematics.IHardwareSyncPulseProvider;
7 import com.neuronrobotics.sdk.addons.kinematics.IHardwareSyncPulseReciver;
8 import com.neuronrobotics.sdk.common.BowlerAbstractCommand;
9 import com.neuronrobotics.sdk.common.BowlerDatagram;
10 import com.neuronrobotics.sdk.common.InvalidConnectionException;
11 import com.neuronrobotics.sdk.common.InvalidResponseException;
12 import com.neuronrobotics.sdk.common.Log;
13 import com.neuronrobotics.sdk.common.NoConnectionAvailableException;
14 import com.neuronrobotics.sdk.util.ThreadUtil;
15 
16 // TODO: Auto-generated Javadoc
21 
23  private static final long threadTime = 10;
24 
26  private HashMap<PIDConfiguration, InterpolationEngine> interpolationEngines = new HashMap<>();
27 
29  private HashMap<Integer, PIDConfiguration> configs = new HashMap<>();
30 
32  private ArrayList<PDVelocityConfiguration> PDconfigs = new ArrayList<PDVelocityConfiguration>();
33 
35  private SyncThread sync = new SyncThread();
36  private boolean runSync =true;
37 
39  private double maxTicksPerSecond;
40 
42  private int numChannels = 40;
43 
44  private float[] backs;
45 
46  private String myVirtualDevName;
47 
54  this(1000000, myVirtualDevName);
55  }
56 
64  this.setMaxTicksPerSecond(maxTicksPerSecond);
65  if (myVirtualDevName == null)
66  throw new RuntimeException("Name of virtual device can not be null");
67  this.myVirtualDevName = myVirtualDevName;
71  for (int i = 0; i < numChannels; i++) {
72  configs.put(i, new PIDConfiguration());
74  }
75 
76  sync.start();
77  // new RuntimeException("Instantiation of VirtualGenericPIDDevice
78  // "+myVirtualDevName).printStackTrace();
79  }
80 
81  /*
82  * (non-Javadoc)
83  *
84  * @see
85  * com.neuronrobotics.sdk.pid.GenericPIDDevice#ConfigurePDVelovityController(com
86  * .neuronrobotics.sdk.pid.PDVelocityConfiguration)
87  */
88  @Override
90  PDconfigs.set(config.getGroup(), config);
91 
92  return true;
93  }
94 
95  /*
96  * (non-Javadoc)
97  *
98  * @see
99  * com.neuronrobotics.sdk.pid.GenericPIDDevice#getPDVelocityConfiguration(int)
100  */
101  @Override
103  return PDconfigs.get(group);
104  }
105 
106  /*
107  * (non-Javadoc)
108  *
109  * @see com.neuronrobotics.sdk.pid.GenericPIDDevice#ConfigurePIDController(com.
110  * neuronrobotics.sdk.pid.PIDConfiguration)
111  */
112  public boolean ConfigurePIDController(PIDConfiguration config) {
113  configs.put(config.getGroup(), config);
114 
115  return true;
116  }
117 
118  /*
119  * (non-Javadoc)
120  *
121  * @see com.neuronrobotics.sdk.pid.GenericPIDDevice#getPIDConfiguration(int)
122  */
124  return configs.get(group);
125  }
126 
127  /*
128  * (non-Javadoc)
129  *
130  * @see com.neuronrobotics.sdk.common.BowlerAbstractDevice#getNamespaces()
131  */
132  @Override
133  public ArrayList<String> getNamespaces() {
134  ArrayList<String> s = new ArrayList<String>();
135  s.add("bcs.pid.*");
136  return s;
137  }
138 
139  /*
140  * (non-Javadoc)
141  *
142  * @see com.neuronrobotics.sdk.pid.GenericPIDDevice#killAllPidGroups()
143  */
144  @Override
145  public boolean killAllPidGroups() {
146  for (PIDConfiguration c : configs.values())
147  c.setEnabled(false);
148  return true;
149  }
150 
159  @Override
162  RuntimeException r = new RuntimeException("This method is never supposed to be called in the virtual PID");
163  r.printStackTrace();
164  throw r;
165  }
166 
167  /*
168  * (non-Javadoc)
169  *
170  * @see com.neuronrobotics.sdk.pid.GenericPIDDevice#ResetPIDChannel(int, int)
171  */
172  @Override
173  public boolean ResetPIDChannel(int group, float valueToSetCurrentTo) {
174  sync.setPause(true);
175  synchronized(interpolationEngines) {
176  getDriveThread(group).ResetEncoder(valueToSetCurrentTo);
177  }
178  float val = GetPIDPosition(group);
179  firePIDResetEvent(group, val);
180  sync.setPause(false);
181  return true;
182  }
183 
184  /*
185  * (non-Javadoc)
186  *
187  * @see com.neuronrobotics.sdk.pid.GenericPIDDevice#SetPIDSetPoint(int, int,
188  * double)
189  */
190  @Override
191  public boolean SetPIDSetPoint(int group, float setpoint, double seconds) {
192  long currentTimeMillis = System.currentTimeMillis();
193  sync.setPause(true);
194  synchronized(interpolationEngines) {
195  getDriveThread(group).StartLinearMotion(setpoint, seconds,currentTimeMillis);
196  }
197  sync.setPause(false);
198  return true;
199  }
200 
201  /*
202  * (non-Javadoc)
203  *
204  * @see com.neuronrobotics.sdk.pid.GenericPIDDevice#SetPDVelocity(int, int,
205  * double)
206  */
207  @Override
208  public boolean SetPDVelocity(int group, int unitsPerSecond, double seconds) throws PIDCommandException {
209  if (unitsPerSecond > getMaxTicksPerSecond())
210  throw new RuntimeException("Saturated PID on channel: " + group + " Attempted Ticks Per Second: "
211  + unitsPerSecond + ", when max is" + getMaxTicksPerSecond() + " set: " + getMaxTicksPerSecond()
212  + " sec: " + seconds);
213  if (unitsPerSecond < -getMaxTicksPerSecond())
214  throw new RuntimeException("Saturated PID on channel: " + group + " Attempted Ticks Per Second: "
215  + unitsPerSecond + ", when max is" + getMaxTicksPerSecond() + " set: " + getMaxTicksPerSecond()
216  + " sec: " + seconds);
217  if (seconds < 0.1 && seconds > -0.1) {
218  // System.out.println("Setting virtual velocity="+unitsPerSecond);
219  getDriveThread(group).SetVelocity(unitsPerSecond);
220  } else {
221  SetPIDInterpolatedVelocity(group, unitsPerSecond, seconds);
222  }
223  return true;
224  }
225 
226  /*
227  * (non-Javadoc)
228  *
229  * @see com.neuronrobotics.sdk.namespace.bcs.pid.IPidControlNamespace#
230  * flushPIDChannels
231  */
232  @Override
233  public void flushPIDChannels(double time) {
234  float[] data = new float[getChannels().size()];
235  for (int i = 0; i < data.length; i++) {
236  data[i] = getPIDChannel(i).getCachedTargetValue();
237  }
238  Log.info("Flushing in " + time + "ms");
239  SetAllPIDSetPoint(data, time);
240  }
241 
242  /*
243  * (non-Javadoc)
244  *
245  * @see com.neuronrobotics.sdk.pid.GenericPIDDevice#SetAllPIDSetPoint(int[],
246  * double)
247  */
248  @Override
249  public boolean SetAllPIDSetPoint(float[] setpoints, double seconds) {
250  long start = System.currentTimeMillis();
251  sync.setPause(true);
252  synchronized(interpolationEngines) {
253  for (int i = 0; i < setpoints.length; i++) {
254  getDriveThread(i).StartLinearMotion(setpoints[i], seconds,start);
255  }
256  }
257  sync.setPause(false);
258  return true;
259  }
260 
262  for (PIDConfiguration c : interpolationEngines.keySet()) {
263  if (c.getGroup() == i) {
264  return interpolationEngines.get(c);
265  }
266  }
267  for (PIDConfiguration c : interpolationEngines.keySet()) {
268  System.err.println(c);
269  }
270 
271  throw new RuntimeException("Device is missing, id " + i);
272  }
273 
274  /*
275  * (non-Javadoc)
276  *
277  * @see com.neuronrobotics.sdk.pid.GenericPIDDevice#GetPIDPosition(int)
278  */
279  @Override
280  public float GetPIDPosition(int group) {
281  // TODO Auto-generated method stub
282  return (float) getDriveThread(group).getPosition();
283  }
284 
285  /*
286  * (non-Javadoc)
287  *
288  * @see com.neuronrobotics.sdk.common.BowlerAbstractDevice#isAvailable()
289  */
290  @Override
291  public boolean isAvailable() {
292  return true;
293  }
294 
295  /*
296  * (non-Javadoc)
297  *
298  * @see com.neuronrobotics.sdk.pid.GenericPIDDevice#GetAllPIDPosition()
299  */
300  @Override
301  public float[] GetAllPIDPosition() {
302  if (backs == null) {
303  backs = new float[numChannels];
304 
305  setChannels(new ArrayList<PIDChannel>());
306  // lastPacketTime = new long[back.length];
307  synchronized(interpolationEngines) {
308  for (int i = 0; i < backs.length; i++) {
309  backs[i] = 0;
310  PIDChannel c = new PIDChannel(this, i);
312  getChannels().add(c);
313  PIDConfiguration conf = new PIDConfiguration();
314  conf.setGroup(i);
315  conf.setEnabled(true);
317  interpolationEngines.put(conf, d);
318  configs.put(i, conf);
319  }
320  }
321  }
322  synchronized(interpolationEngines) {
323  for (int i = 0; i < backs.length; i++)
324  backs[i] = GetPIDPosition(i);
325  }
326  return backs;
327  }
328 
335  this.maxTicksPerSecond = maxTicksPerSecond;
336  }
337 
343  public double getMaxTicksPerSecond() {
344  return maxTicksPerSecond;
345  }
346 
353  private class SyncThread extends Thread {
354 
356  private boolean sync = false;
357  private Boolean pause = false;
358 
359  /*
360  * (non-Javadoc)
361  *
362  * @see java.lang.Thread#run()
363  */
364  public void run() {
365  setName("Bowler Platform Virtual PID sync thread");
366  PIDEvent e = new PIDEvent();
367  PIDConfiguration[] toUpdate = new PIDConfiguration[numChannels] ;
368  int updateIndex=0;
369  long time;
370  while (runSync) {
371  try {
372  Thread.sleep(threadTime);
373  } catch (InterruptedException ex) {
374  }
375  if(!pause) {
376  sync = false;
377  time = System.currentTimeMillis();
378  synchronized(interpolationEngines) {
379  for (PIDConfiguration key : interpolationEngines.keySet()) {
381  if (key.isEnabled()) {
382  if (dr.update(time)) {
383  toUpdate[updateIndex++]=key;
384  }
385  } else {
386  //System.err.println("Virtual Device " + key.getGroup() + " is disabled");
387  }
388  }
389  }
390  for(int i=0;i<updateIndex;i++) {
391  PIDConfiguration key=toUpdate[i];
392  toUpdate[i]=null;
393  try {
394  e.set(key.getGroup(), (float) interpolationEngines.get(key).getTicks(), time, 0);
395  firePIDEvent(e);
396  sync = true;
397  } catch (NullPointerException ex) {
398  // initialization issue, let it work itself out
399  } catch (Exception ex) {
400  ex.printStackTrace();
401  }
402  }
403  updateIndex=0;
404 
405  }else
406  while (isPause())
407  try {
408  Thread.sleep(1);
409  } catch (InterruptedException e1) {
410  // TODO Auto-generated catch block
411  e1.printStackTrace();
412  }
413  if (sync)
414  doSync();
415  }
416  }
417 
418  public boolean isPause() {
419  return pause;
420  }
421 
422  public void setPause(boolean pause) {
423  this.pause = pause;
424 
425  }
426  }
427 
428  /*
429  * (non-Javadoc)
430  *
431  * @see com.neuronrobotics.sdk.pid.GenericPIDDevice#connect()
432  */
433  @Override
434  public boolean connect() {
436  return true;
437  }
438 
443  @Override
444  public void disconnect() {
446  runSync=false;
447  }
448 
449 }
static void info(String message)
Definition: Log.java:110
void setChannels(ArrayList< PIDChannel > channels)
boolean SetPIDInterpolatedVelocity(int group, int unitsPerSecond, double seconds)
void StartLinearMotion(double setpoint, double seconds, long startTimeMs)
void setCachedTargetValue(float targetValue)
void set(int chan, float tick, long time, int velocity)
Definition: PIDEvent.java:50
HashMap< PIDConfiguration, InterpolationEngine > interpolationEngines
PDVelocityConfiguration getPDVelocityConfiguration(int group)
BowlerDatagram send(BowlerAbstractCommand command)
VirtualGenericPIDDevice(double maxTicksPerSecond, String myVirtualDevName)
boolean SetAllPIDSetPoint(float[] setpoints, double seconds)
boolean ResetPIDChannel(int group, float valueToSetCurrentTo)
boolean SetPIDSetPoint(int group, float setpoint, double seconds)
boolean SetPDVelocity(int group, int unitsPerSecond, double seconds)
boolean ConfigurePDVelovityController(PDVelocityConfiguration config)