The VisAO Camera
GimbalMotorCtrl.cpp
1 /************************************************************
2  * GimbalMotorCtrl.cpp
3  *
4  * Author: Jared R. Males (jrmales@email.arizona.edu)
5  *
6  * Definitions for the VisAO gimbal motor controller.
7  *
8  * Developed as part of the Magellan Adaptive Optics system.
9  ************************************************************/
10 
11 /** \file GimbalMotorCtrl.h
12  * \author Jared R. Males
13  * \brief Definitions for the gimbal motor controller.
14  *
15  */
16 
17 #include "GimbalMotorCtrl.h"
18 
19 namespace VisAO
20 {
21 
22 GimbalMotorCtrl::GimbalMotorCtrl(std::string name, const std::string& conffile) throw (AOException) : ESPMotorCtrl(2), VisAOApp_standalone(name, conffile)
23 {
24  Create();
25 }
26 
27 GimbalMotorCtrl::GimbalMotorCtrl( int argc, char**argv) throw (AOException): ESPMotorCtrl(2), VisAOApp_standalone(argc, argv)
28 {
29  Create();
30 }
31 
32 GimbalMotorCtrl::~GimbalMotorCtrl()
33 {
34  return;
35 }
36 
38 {
39 
40  //Set up the base app
41 
42  setup_fifo_list(3);
43  setup_baseApp(1, 1, 1, 0, false);
44 
45  //Read the ip address from config file.
46  try
47  {
48  ip_addr = (std::string)(ConfigDictionary())["ip_addr"];
49  }
50  catch(Config_File_Exception)
51  {
52  ERROR_REPORT("ip_addr is required in configuration.");
53  throw;
54  }
55  _logger->log(Logger::LOG_LEV_INFO, "ip_addr set to %s.", ip_addr.c_str());
56 
57  //Read the ip port from config file.
58  try
59  {
60  ip_port = (int)(ConfigDictionary())["ip_port"];
61  }
62  catch(Config_File_Exception)
63  {
64  ERROR_REPORT( "ip_port is required in configuration.");
65  throw;
66  }
67  _logger->log(Logger::LOG_LEV_INFO, "ip_port set to %i.", ip_port);
68 
69  //Read the x address from config file.
70  try
71  {
72  x_addr = (int)(ConfigDictionary())["x_addr"];
73  }
74  catch(Config_File_Exception)
75  {
76  ERROR_REPORT("x_addr is required in configuration.");
77  throw;
78  }
79  _logger->log(Logger::LOG_LEV_INFO, "x_addr set to %i.", x_addr);
80 
81  //Read the y address from config file.
82  try
83  {
84  y_addr = (int)(ConfigDictionary())["y_addr"];
85  }
86  catch(Config_File_Exception)
87  {
88  ERROR_REPORT("y_addr is required in configuration.");
89  throw;
90  }
91  _logger->log(Logger::LOG_LEV_INFO, "y_addr set to %i.", y_addr);
92 
93  xAxisNo = 1;
94  yAxisNo = 2;
95 
96  //Read the scale from config file.
97  try
98  {
99  scale = (double)(ConfigDictionary())["scale"];
100  }
101  catch(Config_File_Exception)
102  {
103  scale = 1.;
104  }
105  _logger->log(Logger::LOG_LEV_INFO, "Gimbal scale set to %f arcsec/mm.", scale);
106 
107  //Read the x center from config file.
108  try
109  {
110  x_center = (double)(ConfigDictionary())["x_center"];
111  }
112  catch(Config_File_Exception)
113  {
114  ERROR_REPORT("Gimbal x_center is required in configuration.");
115  }
116  _logger->log(Logger::LOG_LEV_INFO, "Gimbal x_center set to %f.", x_center);
117 
118  //Read the y center from config file.
119  try
120  {
121  y_center = (double)(ConfigDictionary())["y_center"];
122  }
123  catch(Config_File_Exception)
124  {
125  ERROR_REPORT("Gimbal y_center is required in configuration.");
126  }
127  _logger->log(Logger::LOG_LEV_INFO, "Gimbal y_center set to %f.", y_center);
128 
129 
130  //Read the x dark location from config file.
131  try
132  {
133  x_dark = (double)(ConfigDictionary())["x_dark"];
134  }
135  catch(Config_File_Exception)
136  {
137  x_dark = 0.;
138  }
139  _logger->log(Logger::LOG_LEV_INFO, "Gimbal x_dark set to %f.", x_dark);
140 
141  //Read the y dark location from config file.
142  try
143  {
144  y_dark = (double)(ConfigDictionary())["y_dark"];
145  }
146  catch(Config_File_Exception)
147  {
148  y_dark = 0.;
149  }
150  _logger->log(Logger::LOG_LEV_INFO, "Gimbal y_dark set to %f.", y_dark);
151 
152 
153  //Init the status board
156  {
158  _logger->log(Logger::LOG_LEV_ERROR, "Could not create status board.");
159  }
160  else
161  {
163  strncpy(bsb->appname, MyFullName().c_str(), 25);
164  bsb->max_update_interval = pause_time*2.;
165  }
166 
167  //Read the power outlet from config file.
168  try
169  {
170  power_outlet = (int)(ConfigDictionary())["power_outlet"];
171  }
172  catch(Config_File_Exception)
173  {
174  _logger->log(Logger::LOG_LEV_ERROR, "Gimbal power_outlet is required in configuration.");
175  }
176  _logger->log(Logger::LOG_LEV_INFO, "Gimbal power_outlet set to %i.", power_outlet);
177 
178  //Set up power outlet monitoring
179  size_t sz;
180  psb = (VisAO::power_status_board*) attach_shm(&sz, STATUS_power, 0);
181 
182  if(psb)
183  {
184  switch(power_outlet)
185  {
186  case 1: powerOutletState = &psb->outlet1_state; break;
187  case 2: powerOutletState = &psb->outlet2_state; break;
188  case 3: powerOutletState = &psb->outlet3_state; break;
189  case 4: powerOutletState = &psb->outlet4_state; break;
190  case 5: powerOutletState = &psb->outlet5_state; break;
191  case 6: powerOutletState = &psb->outlet6_state; break;
192  case 7: powerOutletState = &psb->outlet7_state; break;
193  case 8: powerOutletState = &psb->outlet8_state; break;
194  default: powerOutletState = 0;
195  }
196  }
197 
198  isMoving = 0;
199  postHoming = 0;
200 
201  fw2sb = (VisAO::filterwheel_status_board*) attach_shm(&sz, STATUS_filterwheel2, 0);
202  fw3sb = (VisAO::filterwheel_status_board*) attach_shm(&sz, STATUS_filterwheel3, 0);
203  wsb = (VisAO::wollaston_status_board*) attach_shm(&sz, STATUS_wollaston, 0);
204  aosb = (VisAO::aosystem_status_board*) attach_shm(&sz, STATUS_aosystem, 0);
205 
206  pthread_mutex_init(&comMutex, 0);
207 }
208 
210 {
211  int stat;
212 
213  if(getPowerStatus() == 0)
214  {
215  curState = STATE_OFF;
216  return 1;
217  }
218 
219  pthread_mutex_lock(&comMutex);
220  // Close the previous connection, if any
221  SerialClose();
222  msleep(1000);
223 
224  stat = SerialInit( ip_addr.c_str(), ip_port ); // This locks if network is down or host unreachable
225 
226  pthread_mutex_unlock(&comMutex);
227  if (stat != NO_ERROR)
228  {
229  logss.str("");
230  logss << "Error attempting to connect to " << ip_addr << ":" << ip_port << ". Connect result: ";
231  logss << stat << " - errno says: " << strerror(errno);
232  ERROR_REPORT(logss.str().c_str());
233  curState = STATE_NOCONNECTION;
234 
235  return -1;
236  }
237  else
238  {
239  logss.str("");
240  logss << "Connected to " << ip_addr << ":" << ip_port;
241  LOG_INFO(logss.str().c_str());
242  //curState = STATE_CONNECTED;
243  }
244 
245  return NO_ERROR;
246 }
247 
249 {
250  int newState;
251  std::string axstate;
252 
253  if(getPowerStatus() == 0)
254  {
255  curState = STATE_OFF;
256  return 1;
257  }
258 
259  if(getCtrlState(xAxisNo, axstate) < 0)
260  {
261  if(curState != STATE_NOCONNECTION)
262  {
263  curState = STATE_ERROR; //STATE_NOCONNECTION set by sendCommand.
264  //otherwise we have a different problem.
265  ERROR_REPORT(errStr.str().c_str());
266  ERROR_REPORT("error getting x axis state");
267  }
268  return -1;
269  }
270 
271  if(axstate[0] == '0') newState = STATE_CONNECTED;
272  else if (axstate[0] == '1' && (axstate[1] == 'E' || axstate[1] == 'F'))
273  {
274  newState = STATE_HOMING;
275  postHoming = 1;
276  }
277  else if (axstate[0] == '2') newState = STATE_OPERATING;
278  else if (axstate[0] == '3' && isdigit(axstate[1])) newState = STATE_READY;
279  else
280  {
281  logss.str("");
282  logss << "Invalid x axis state:" << axstate << ".";
283  ERROR_REPORT(logss.str().c_str());
284  newState = STATE_INVALID;
285  }
286 
287  if(getCtrlState(yAxisNo, axstate)<0)
288  {
289  if(curState != STATE_NOCONNECTION) curState = STATE_ERROR; //STATE_NOCONNECTION set by sendCommand.
290  //otherwise we have a different problem.
291  ERROR_REPORT(errStr.str().c_str());
292  ERROR_REPORT("error getting y axis state");
293  return -1;
294  }
295 
296  if(axstate[0] == '0')
297  {
298  newState = STATE_CONNECTED;
299  }
300  else if ((axstate[0] == '1' && (axstate[1] == 'E' || axstate[1] == 'F')))
301  {
302  if(newState != STATE_INVALID)
303  {
304  newState = STATE_HOMING;
305  postHoming = 1;
306  }
307  }
308  else if (axstate[0] == '2')
309  {
310  if(newState != STATE_HOMING && newState != STATE_INVALID)
311  {
312  newState = STATE_OPERATING;
313  }
314  }
315  else if (axstate[0] == '3' && isdigit(axstate[1]))
316  {
317  if(newState != STATE_HOMING && newState != STATE_INVALID && newState != STATE_OPERATING)
318  {
319  newState = STATE_READY;
320  }
321  }
322  else
323  {
324  ERROR_REPORT("Invalid y axis state");
325  newState = STATE_INVALID;
326  }
327 
328  if(newState == STATE_READY)
329  {
330  if(isMoving) moveStop();
331 
332  if(postHoming)
333  {
334  int rv;
335  std::string presetf;
336  std::vector<double> preset(2);
337 
338  if( get_preset("gimbal", 0, -1, 0, 0, &preset, presetf) < 0)
339  {
340  logss.str("");
341  logss << "Found preset: " << presetf << " -> " << preset[0] << " " << preset[1] << ". Centering.";
342  LOG_INFO(logss.str().c_str());
343 
344  ERROR_REPORT("Could not get center preset for post homing.");
345  preset[0] = 0.;
346  preset[1] = 0.;
347  }
348 
349 
350 
351  rv = gotoAbsPos(xAxisNo, preset[0]);
352  if(rv < 0)
353  {
354  ERROR_REPORT(errStr.str().c_str());
355  }
356  rv += gotoAbsPos(yAxisNo, preset[1]);
357  if(rv < 0)
358  {
359  ERROR_REPORT(errStr.str().c_str());
360  }
361  postHoming = 0;
362  curState = STATE_OPERATING;
363  }
364  }
365 
366  curState = newState;
367 
368  return 0;
369 
370 }
371 
373 {
374  return getCurPos(xAxisNo)*scale;
375 }
376 
378 {
379  std::string resp;
380  getCtrlState(xAxisNo, resp);
381  if(resp.length() != 2) return -1;
382  //std::cout << s << " " << resp << "\n";
383 
384  if(resp[0] == '2' && resp[1] == '8')
385  {
386  return 1;
387  }
388 
389  if(resp[0] == '1' && (resp[1] == 'E' || resp[1] == 'F'))
390  {
391  return 1;
392  }
393 
394  return 0;
395 }
396 
398 {
399  return getCurPos(yAxisNo)*scale;
400 }
401 
403 {
404  std::string resp;
405 
406  getCtrlState(yAxisNo, resp);
407  if(resp.length() != 2) return -1;
408 
409  if(resp[0] == '2' && resp[1] == '8')
410  {
411  return 1;
412  }
413 
414  if(resp[0] == '1' && (resp[1] == 'E' || resp[1] == 'F'))
415  {
416  return 1;
417  }
418 
419  return 0;
420 }
421 
423 {
424  int powerState;
425  if(!psb)
426  {
427  size_t sz;
428  psb = (VisAO::power_status_board*) attach_shm(&sz, 13000, 0);
429 
430  if(psb)
431  {
432  switch(power_outlet)
433  {
434  case 1: powerOutletState = &psb->outlet1_state; break;
435  case 2: powerOutletState = &psb->outlet2_state; break;
436  case 3: powerOutletState = &psb->outlet3_state; break;
437  case 4: powerOutletState = &psb->outlet4_state; break;
438  case 5: powerOutletState = &psb->outlet5_state; break;
439  case 6: powerOutletState = &psb->outlet6_state; break;
440  case 7: powerOutletState = &psb->outlet7_state; break;
441  case 8: powerOutletState = &psb->outlet8_state; break;
442  default: powerOutletState = 0;
443  }
444  }
445  }
446 
447  if(psb && powerOutletState)
448  {
449  if(get_curr_time() - ts_to_curr_time(&psb->last_update) > 3.*psb->max_update_interval)
450  {
451  powerState = -1;
452  }
453  else
454  {
455  powerState = *powerOutletState;
456  }
457  }
458  else powerState = -1;
459 
460  return powerState;
461 }
462 
464 {
465  std::string presetf;
466  std::vector<double> preset(2);
467 
468  size_t sz;
469 
470  if(!fw2sb) fw2sb = (VisAO::filterwheel_status_board*) attach_shm(&sz, STATUS_filterwheel2, 0);
471  if(!fw3sb) fw3sb = (VisAO::filterwheel_status_board*) attach_shm(&sz, STATUS_filterwheel3, 0);
472  if(!wsb) wsb = (VisAO::wollaston_status_board*) attach_shm(&sz, STATUS_wollaston, 0);
473  if(!aosb) aosb = (VisAO::aosystem_status_board*) attach_shm(&sz, STATUS_aosystem, 0);
474 
475  if(!aosb || !wsb || !fw2sb || !fw3sb)
476  {
477  ERROR_REPORT("Not connected to status boards for center preset.");
478  return -1;
479  }
480 
481  //Check if there is a specific preset for this combo. If not, then use the BS only.
482  if( get_preset("gimbal", aosb->filter1_reqpos, (int) wsb->cur_pos, fw2sb->req_pos, fw3sb->req_pos, &preset, presetf) < 0)
483  {
484  if( get_preset("gimbal", aosb->filter1_reqpos, (int) wsb->cur_pos, 0, 0, &preset, presetf) < 0)
485  {
486  ERROR_REPORT("Could not get exact center preset.");
487  return -1;
488  }
489  }
490 
491  logss.str("");
492  logss << "Found preset: " << presetf << " -> " << preset[0] << " " << preset[1] << ". Centering.";
493  LOG_INFO(logss.str().c_str());
494 
495  if(gotoAbsPos(xAxisNo, preset[0]/scale) < 0)
496  {
497  ERROR_REPORT(errStr.str().c_str());
498  return -1;
499  }
500  if(gotoAbsPos(yAxisNo, preset[1]/scale) < 0)
501  {
502  ERROR_REPORT(errStr.str().c_str());
503  return -1;
504  }
505 
506  return 0;
507 }
508 
509 
511 {
512 
513 
514  if(gotoAbsPos(xAxisNo, x_dark/scale) < 0)
515  {
516  ERROR_REPORT(errStr.str().c_str());
517  return -1;
518  }
519  if(gotoAbsPos(yAxisNo, y_dark/scale) < 0)
520  {
521  ERROR_REPORT(errStr.str().c_str());
522  return -1;
523  }
524 
525  logss.str("");
526  logss << "moved to dark position " << x_dark << " " << y_dark << ".";
527  LOG_INFO(logss.str().c_str());
528 
529  return 0;
530 }
531 
533 {
534  std::vector<double> preset(2);
535 
536  size_t sz;
537 
538  if(!fw2sb) fw2sb = (VisAO::filterwheel_status_board*) attach_shm(&sz, STATUS_filterwheel2, 0);
539  if(!fw3sb) fw3sb = (VisAO::filterwheel_status_board*) attach_shm(&sz, STATUS_filterwheel3, 0);
540  if(!wsb) wsb = (VisAO::wollaston_status_board*) attach_shm(&sz, STATUS_wollaston, 0);
541  if(!aosb) aosb = (VisAO::aosystem_status_board*) attach_shm(&sz, STATUS_aosystem, 0);
542 
543  if(!aosb || !wsb || !fw2sb || !fw3sb)
544  {
545  ERROR_REPORT("Not connected to status boards for saving preset.");
546  return -1;
547  }
548 
549  double fw3pos;
550 
551  if(fw3sb->type == 2)
552  {
553  fw3pos = fw3sb->pos;
554  }
555  else
556  {
557  fw3pos = 0.;
558  }
559 
560  preset[0] = get_x_pos();
561  preset[1] = get_y_pos();
562 
563 /* //We save presets for each combo of fw2 and fw3, since these should have only small effect on center location.
564  for(int i =0;i<5;i++)
565  {
566  for(int j=0;j<6;j++)
567  {*/
568  if( save_preset("gimbal", aosb->filter1_pos, (int) wsb->cur_pos, 0., fw3pos, &preset) < 0)
569  {
570  logss.str("");
571  logss << "Could not save center preset: " << (int) aosb->filter1_pos << " " << (int) wsb->cur_pos << " " << 0 << " " << fw3sb << " " << preset[0] << " " << preset[1] << "\n";
572  ERROR_REPORT(logss.str().c_str());
573  return -1;
574  }
575 /* }
576  }*/
577 
578 
579  logss.str("");
580  logss << "Saved preset " << preset[0] << " " << preset[1] << ".";
581  LOG_INFO(logss.str().c_str());
582 
583  return 0;
584 }
585 
586 int GimbalMotorCtrl::sendCommand(std::string &com, std::string &resp, int timeout)
587 {
588  pthread_mutex_lock(&comMutex);
589 
590  char answer[256];
591  //char term[3] = "\r\n";
592 
593  #ifdef _debug
594  std::cout << "Sending " << com << "\n";
595  #endif
596 
597  std::string termcom = com + "\r\n";
598 
599  if(SerialOut(termcom.c_str(), termcom.length()) != 0)
600  {
601  ERROR_REPORT("Communication send error in sendCommand");
602  curState = STATE_NOCONNECTION;
603  pthread_mutex_unlock(&comMutex);
604  return -1;
605  }
606 
607  #ifdef _debug
608  std::cout << "Sent. Getting response.\n";
609  #endif
610 
611  if(SerialInString(answer, 256, timeout, '\n') < 0)
612  {
613  resp = "";
614  ERROR_REPORT("Communication receive error in sendCommand");
615  curState = STATE_NOCONNECTION;
616  pthread_mutex_unlock(&comMutex);
617  return -1;
618  }
619 
620  #ifdef _debug
621  std::cout << "Response got.\n";
622  #endif
623 
624  pthread_mutex_unlock(&comMutex);
625 
626  resp = answer;
627 
628  int cr = resp.find("\r", 0);
629 
630  #ifdef _debug
631  std::cout << "CR pos = " << cr << ".\n";
632  #endif
633 
634  if(cr > 0) resp.erase(cr, resp.length()-cr);
635 
636 
637  #ifdef _debug
638  std::cout << "Received " << resp << "\n";
639  #endif
640 
641  return 0;
642 }
643 
644 int GimbalMotorCtrl::sendCommand(std::string &com)
645 {
646  pthread_mutex_lock(&comMutex);
647  #ifdef _debug
648  std::cout << "Sending " << com << "\n";
649  #endif
650 
651  std::string termcom = com + "\r\n";
652 
653  if(SerialOut(termcom.c_str(), termcom.length()) != 0)
654  {
655  ERROR_REPORT("Communication send error in sendCommand");
656  curState = STATE_NOCONNECTION;
657  pthread_mutex_unlock(&comMutex);
658  return -1;
659  }
660 
661  pthread_mutex_unlock(&comMutex);
662  return 0;
663 }
664 
666 {
667  int sleep_time = 1;
668  signal(SIGIO, SIG_IGN);
669  signal(RTSIGIO, SIG_IGN);
670 
671  //Install the main thread handler
673  {
674  ERROR_REPORT("Error installing main thread catcher.");
675  return -1;
676  }
677 
678  //Startup the I/O signal handling thread
679  if(start_signal_catcher() != 0)
680  {
681  ERROR_REPORT("Error starting signal catching thread.");
682  return -1;
683  }
684 
685  //Now Block all I/O signals in this thread.
686  if(block_sigio() != 0)
687  {
688  ERROR_REPORT("Error blicking SIGIO.");
689  return -1;
690  }
691 
692  LOG_INFO("starting up . . .");
693 
694  sleep(1); //let signal thread get started
695 
696  curState = STATE_NOCONNECTION;
697 
698  while(!TimeToDie)
699  {
700 
701  if(curState == STATE_NOCONNECTION || curState == STATE_OFF)
702  {
703  setupNetwork();
704  if(checkConnStat() == 0)
705  {
706  curState = STATE_CONNECTED;
707  }
708  }
709  else if(curState != STATE_OFF)
710  {
711  if(checkConnStat() < 0) curState = STATE_NOCONNECTION;
712  }
713 
714  switch(curState)
715  {
716  case STATE_CONNECTED:
717  #ifdef _debug
718  std::cout << "STATE_CONNECTED\n";
719  #endif
720  if(powerOnInit() < 0)
721  {
722  ERROR_REPORT("Error in power on init:");
723  ERROR_REPORT(errStr.str().c_str());
724  curState = STATE_ERROR;
725  }
726  break;
727  case STATE_HOMING:
728  #ifdef _debug
729  std::cout << "STATE_HOMING\n";
730  #endif
731  break;
732  case STATE_OPERATING:
733  #ifdef _debug
734  std::cout << "STATE_OPERATING\n";
735  #endif
736  break;
737  case STATE_READY:
738  #ifdef _debug
739  std::cout << "STATE_READY\n";
740  #endif
741  break;
742  case STATE_NOCONNECTION:
743  #ifdef _debug
744  std::cout << "STATE_NOCONNECTION\n";
745  #endif
746  break;
747  case STATE_OFF:
748  #ifdef _debug
749  std::cout << "STATE_OFF\n";
750  #endif
751  break;
752  default:
753  #ifdef _debug
754  std::cout << "STATE_?\n";
755  #endif
756  logss.str("");
757  logss << "Bad state in main loop " << curState;
758  ERROR_REPORT(logss.str().c_str());
759  }
760 
761  sleep(sleep_time);
762 
763  }
764 
765  pthread_join(signal_thread, 0);
766 
767  return 0;
768 
769 }
770 
771 std::string GimbalMotorCtrl::remote_command(std::string com)
772 {
773  return common_command(com, CMODE_REMOTE);
774 }
775 
776 std::string GimbalMotorCtrl::local_command(std::string com)
777 {
778  return common_command(com, CMODE_LOCAL);
779 }
780 
781 std::string GimbalMotorCtrl::script_command(std::string com)
782 {
783  return common_command(com, CMODE_SCRIPT);
784 }
785 
786 std::string GimbalMotorCtrl::common_command(std::string com, int cmode)
787 {
788  int rv;
789  double val;
790  char str[256];
791  std::string resp;
792 
793  #ifdef _debug
794  std::cout << "Common Command " << com << "\n";
795  #endif
796 
797  if(com == "stop")
798  {
799  rv = stop();
800  snprintf(str, 256, "%i\n", rv);
801  return str;
802  }
803 
804  if(com == "stopx")
805  {
806  rv = stop(xAxisNo);
807  snprintf(str, 256, "%i\n", rv);
808  return str;
809  }
810 
811  if(com == "stopy")
812  {
813  rv = stop(yAxisNo);
814  snprintf(str, 256, "%i\n", rv);
815  return str;
816  }
817 
818  if(com == "state?")
819  {
820  return get_state_str();
821  }
822 
823  if(com == "scale?")
824  {
825  snprintf(str, 256, "%f\n", scale);
826  return str;
827  }
828 
829  if(com == "xpos?")
830  {
831  val = get_x_pos()*scale;
832  snprintf(str, 256, "%f\n", val);
833  return str;
834  }
835 
836  if(com == "xmoving?")
837  {
838  snprintf(str, 256, "%i\n", getXMoving());
839  return str;
840  }
841 
842  if(com == "ypos?")
843  {
844  val = get_y_pos()*scale;
845  snprintf(str, 256, "%f\n", val);
846  return str;
847  }
848 
849  if(com == "ymoving?")
850  {
851  snprintf(str, 256, "%i\n", getYMoving());
852  return str;
853  }
854 
855  if(com.length() > 3 && cmode == control_mode)
856  {
857  if(com.substr(0,4) == "xrel" && com.length() > 4)
858  {
859  val = strtod(com.substr(5, com.length()-5).c_str(), 0);
860  rv = gotoRelPos(xAxisNo, val/scale);
861  if(rv < 0)
862  {
863  ERROR_REPORT(errStr.str().c_str());
864  }
865  snprintf(str, 256, "%i\n", rv);
866  return str;
867  }
868 
869  if(com.substr(0,4) == "xabs" && com.length() > 4)
870  {
871  val = strtod(com.substr(5, com.length()-5).c_str(), 0);
872  rv = gotoAbsPos(xAxisNo, val/scale);
873  if(rv < 0)
874  {
875  ERROR_REPORT(errStr.str().c_str());
876  }
877  snprintf(str, 256, "%i\n", rv);
878  return str;
879  }
880 
881  if(com.substr(0,4) == "yrel" && com.length() > 4)
882  {
883  val = strtod(com.substr(5, com.length()-5).c_str(), 0);
884  rv = gotoRelPos(yAxisNo, val/scale);
885  if(rv < 0)
886  {
887  ERROR_REPORT(errStr.str().c_str());
888  }
889  snprintf(str, 256, "%i\n", rv);
890  return str;
891  }
892 
893  if(com.substr(0,4) == "yabs" && com.length() > 4)
894  {
895  val = strtod(com.substr(5, com.length()-5).c_str(), 0);
896  rv = gotoAbsPos(yAxisNo, val/scale);
897  if(rv < 0)
898  {
899  ERROR_REPORT(errStr.str().c_str());
900  }
901  snprintf(str, 256, "%i\n", rv);
902  return str;
903  }
904 
905  if(com == "center")
906  {
907  rv = center();
908 
909  if(rv < 0) return "-1\n";
910  return "1\n";
911  }
912 
913  if(com == "dark")
914  {
915  rv = dark();
916 
917  if(rv < 0) return "-1\n";
918  return "1\n";
919  }
920 
921  if(com == "savepreset")
922  {
923  rv = savepreset();
924  if(rv < 0) return "-1\n";
925  return "1\n";
926  }
927 
928  }
929  else
930  {
931  if(cmode!= control_mode)
932  {
933  return control_mode_response();
934  }
935  }
936 
937  return "UNKOWN COMMAND";
938 }
939 
941 {
942  double xp=-1, yp=-1;
943  int xm=-1, ym=-1;
944 
945  if(curState == STATE_HOMING || curState == STATE_OPERATING || curState == STATE_READY)
946  {
947  xp = get_x_pos();
948  yp = get_y_pos();
949  xm = getXMoving();
950  ym = getYMoving();
951  }
952 
953  char tmp[100];
954  snprintf(tmp, 100, "%c,%i,%i,%i,%f,%i,%f,%f\n", control_mode_response()[0],curState,getPowerStatus(),xm, xp, ym, yp, scale);
955  return tmp;
956 }
957 
959 {
960  isMoving = 1;
961  timeval tv;
962  gettimeofday(&tv, 0);
963  dataLogger(tv);
964 }
965 
967 {
968  isMoving = 0;
969  timeval tv;
970  gettimeofday(&tv, 0);
971  dataLogger(tv);
972 }
973 
974 
976 {
978  {
980 
982 
983  gsb->power = getPowerStatus();
984 
985  if(curState == STATE_CONNECTED || curState == STATE_HOMING || curState == STATE_OPERATING || curState == STATE_READY)
986  {
987  gsb->xpos = get_x_pos();
988 
989  gsb->ypos = get_y_pos();
990  }
991  else
992  {
993  gsb->xpos = -1;
994  gsb->ypos = -1;
995  }
996  }
997 
998  return 0;
999 }
1000 
1002 {
1003 
1004  checkDataFileOpen();
1005 
1006  dataof << tv.tv_sec << " " << tv.tv_usec << " " << get_x_pos() << " " << get_y_pos() << std::endl;
1007 
1008  if(!dataof.good())
1009  {
1010  Logger::get()->log(Logger::LOG_LEV_ERROR, "Error in Gimbal data file. Gimbal data may not be logged correctly");
1011  }
1012 
1013 }
1014 
1015 
1016 
1017 }//namespace VisAO
int center()
Read the preset center position for current board conditions, and gimbal to it.
int x_addr
The controller address of the x axis.
int y_addr
The controller address of the y axis.
double get_curr_time(void)
Gets the current CLOCK_REALTIME time, returns it in seconds to double precision.
Definition: libvisaoc.c:40
virtual std::string script_command(std::string com)
Overridden from VisAOApp_base::script_command, here just calls common_command.
int * powerOutletState
The power strip outlet controlling shutter power.
virtual int start_signal_catcher(bool inherit_sched=true)
Starts the signal catching loop.
int getXMoving()
Get the moving status of the x axis.
double x_dark
The configurable location of the x dark location.
int xAxisNo
The axis number of x, e.g. 0.
int postHoming
When 1, the gimbal will center after homing.
pthread_mutex_t comMutex
Mutex for communicating with the controllers.
The standalone VisAO application, does not interface with the AO Supervisor.
std::string common_command(std::string com, int cmode)
The common command processor for commands received by fifo.
std::ostringstream logss
Conveninence string stream for building log messages.
void * statusboard_shmemptr
The pointer to the shared memory block for the statusboard.
double get_x_pos()
Get the x position.
virtual int update_statusboard()
Update the status board.
virtual int setup_baseApp(bool usethreads=false)
Install fifo channels.
VisAO::filterwheel_status_board * fw2sb
pointer to status board of F/W 2 (for presets)
virtual int sendCommand(std::string &com, std::string &resp, int timeout)
Implementation of ESPMotorCtrl sendCommand.
int setup_fifo_list(int nfifos)
Allocate the fifo_list.
bool isMoving
True if moving - set when move starts and updating data logger.
int savepreset()
Save the current position as the preset for this board setup.
The ESP motor controller class.
Definition: ESPMotorCtrl.h:37
int powerOnInit()
Checks the controllers for current errors, and populates the stageName vector.
pthread_t signal_thread
Identifier for the separate signal handling thread.
key_t statusboard_shmemkey
The key used to lookup the shared memory.
double scale
The conversion scale from encoder mm to arcsec on the CCD47, i.e. arcsec/mm.
Definitions for the gimbal motor controller.
virtual int block_sigio()
Sets the signal mask to block SIGIO and RTSIGIO.
int ip_port
ip port on which the motor controllers are connected
virtual int update_statusboard()
Update the gimbal status board.
int TimeToDie
Global set by SIGTERM.
std::string control_mode_response()
Convenience function to return the control type response string, e.g. "A\n".
int getYMoving()
Get the moving status of the y axis.
void * attach_shm(size_t *sz, key_t mkey, int shmemid)
Attach to a shared memory buffer and get its size.
Definition: libvisaoc.c:90
int setupNetwork()
Establish the serial-over-ip connection.
virtual void dataLogger(timeval tv)
Write gimbal positions to the data log.
int getPowerStatus()
Get the status of the power outlet.
double get_y_pos()
Get the y position.
void moveStop()
Called when a move stops, for data logging.
double pause_time
Time to pause during application main loop.
Definition: VisAOApp_base.h:84
#define STATUS_gimbal
Shared memory key for the Gimbal mirror status board.
Definition: statusboard.h:65
double y_center
The configurable location of the default x-center.
int power_outlet
Configuration variable, setting which power outlet to monitor.
VisAO::wollaston_status_board * wsb
pointer to status board of wollaston (for presets)
VisAO::aosystem_status_board * aosb
pointer to status board of VisAOI (for presets)
virtual void moveStart()
Called when a move starts, for data logging. Overriden from ESPMotorCtrl.
virtual std::string remote_command(std::string com)
Overridden from VisAOApp_base::remote_command, here just calls common_command.
power_status_board * psb
This is for monitoring power outlet state.
int checkConnStat()
Check connection status by querying the status of each controller. Changes curState.
int curState
The current controller state (READY, etc.)
int create_statusboard(size_t sz)
Creates and attaches to the statusboard shared memory.
virtual int Run()
The main loop.
double x_center
The configurable location of the default x-center.
double y_dark
The configurable location of the y dark location.
double ts_to_curr_time(struct timespec *tsp)
Convert a timespec structure to double seconds.
Definition: libvisaoc.c:30
static int control_mode
The current control mode.
int yAxisNo
The axis number of y, e.g. 1.
virtual int install_sig_mainthread_catcher()
Install the SIG_MAINTHREAD signal catcher.
virtual std::string local_command(std::string com)
Overridden from VisAOApp_base::local_command, here just calls common_command.
VisAO::filterwheel_status_board * fw3sb
pointer to status board of F/W 3 (for presets)
void Create()
Initialization common to both constructors.
std::string ip_addr
ip address of the serial converter
The namespace of VisAO software.
int dark()
Gimbal to the dark position.
GimbalMotorCtrl(std::string name, const std::string &conffile)
Standard constructor with a config file.
std::string get_state_str()
Get the state string.