The VisAO Camera
VisAOIClient.cpp
1 #include "VisAOIClient.h"
2 
3 //#define _debug
4 
5 namespace VisAO
6 {
7 
8 pthread_mutex_t threadMutex;
9 
10 VisAOIClient::VisAOIClient(int argc, char **argv) throw(AOException) : MagAOIClient(argc, argv), VisAOApp_base()
11 {
12  Create();
13 }
14 
15 VisAOIClient::VisAOIClient( std::string name, const std::string &conffile) throw (AOException): MagAOIClient(name, conffile), VisAOApp_base()
16 {
17  Create();
18 }
19 
20 void VisAOIClient::Create() throw (AOException)
21 {
22  std::string visao_root, fifoin, fifoout;
23 
24  LoadConfig();
25 
26  setup_fifo_list(3);
27 
28  wait_to = 1.0;
29  visao_root = getenv("VISAO_ROOT");
30 
31  //Wollaston remote fifo.
32  fifoin = visao_root + "/" + fifo_path + "/" + wollaston_process + "_com_remote_in";
33  fifoout = visao_root + "/" + fifo_path + "/" + wollaston_process + "_com_remote_out";
34  set_fifo_list_channel(&fl, WOLL_FIFO, RWBUFF_SZ, fifoout.c_str(),fifoin.c_str(), 0, 0);
35 
36  //Focus remote fifo
37  fifoin = visao_root + "/" + fifo_path + "/" + focus_process + "_com_remote_in";
38  fifoout = visao_root + "/" + fifo_path + "/" + focus_process + "_com_remote_out";
39  set_fifo_list_channel(&fl, FOC_FIFO, RWBUFF_SZ, fifoout.c_str(),fifoin.c_str(), 0, 0);
40 
41  //Gimbal remote fifo
42  fifoin = visao_root + "/" + fifo_path + "/" + gimbal_process + "_com_remote_in";
43  fifoout = visao_root + "/" + fifo_path + "/" + gimbal_process + "_com_remote_out";
44  set_fifo_list_channel(&fl, GIMB_FIFO, RWBUFF_SZ, fifoout.c_str(),fifoin.c_str(), 0, 0);
45 
46  //Init the status board
47  statusboard_shmemkey = STATUS_aosystem;
48  if(create_statusboard(sizeof(aosystem_status_board)) != 0)
49  {
51  _logger->log(Logger::LOG_LEV_ERROR, "Could not create status board.");
52  aosb = 0;
53  }
54  else
55  {
57  strncpy(bsb->appname, MyFullName().c_str(), 25);
58  bsb->max_update_interval = pause_time;
60  }
61 
62  //Initialize reconstructor database
63  rsb = 0;
64 
65  try
66  {
67  data_log_time_length = (double)(ConfigDictionary())["data_log_time_length"];
68  }
69  catch(Config_File_Exception)
70  {
71  data_log_time_length = 120.;
72  }
73  _logger->log(Logger::LOG_LEV_INFO, "Set logger file length to (data_log_time_length): %f secs", data_log_time_length);
74 
75  try
76  {
77  data_save_path = (std::string)(ConfigDictionary())["data_save_path"];
78  }
79  catch(Config_File_Exception)
80  {
81  data_save_path = "data/syslogs";
82  }
83  _logger->log(Logger::LOG_LEV_INFO, "Set data save path to (data_save_path): %s", data_save_path.c_str());
84 
85  data_file_prefix = "aosys";
86 
87  pthread_mutex_init(&threadMutex, 0);
88 }
89 
91 {
92  //Get the fifo path
93  try
94  {
95  fifo_path = (std::string) ConfigDictionary()["fifo_path"];
96  }
97  catch (Config_File_Exception &e)
98  {
99  fifo_path = "fifos";
100  }
101 
102  //Read wollaston process name from config file
103  try
104  {
105  wollaston_process = (std::string)(ConfigDictionary())["wollaston_process"];
106  _logger->log(Logger::LOG_LEV_INFO, "Wollaston process name (wollaston_process) set to %s.", wollaston_process.c_str());
107  }
108  catch(Config_File_Exception)
109  {
110  wollaston_process = "wollastonstatus";
111  _logger->log(Logger::LOG_LEV_INFO, "Wollaston process name (wollaston_process) set to default %s.",
112  wollaston_process.c_str());
113  }
114 
115 
116  //Read focus process name from config file
117  try
118  {
119  focus_process = (std::string)(ConfigDictionary())["focus_process"];
120  _logger->log(Logger::LOG_LEV_INFO, "Focus control name (focus_process) set to %s.", focus_process.c_str());
121  }
122  catch(Config_File_Exception)
123  {
124  focus_process = "focusmotor";
125  _logger->log(Logger::LOG_LEV_INFO, "Focus control process name (focus_process) set to default %s.",
126  focus_process.c_str());
127  }
128 
129  //Read gimbal process name from config file
130  try
131  {
132  gimbal_process = (std::string)(ConfigDictionary())["gimbal_process"];
133  _logger->log(Logger::LOG_LEV_INFO, "Gimbal control name (gimbal_process) set to %s.", gimbal_process.c_str());
134  }
135  catch(Config_File_Exception)
136  {
137  gimbal_process = "gimbal";
138  _logger->log(Logger::LOG_LEV_INFO, "Gimbal control process name (gimbal_process) set to default %s.",
139  gimbal_process.c_str());
140  }
141 
142  try
143  {
144  orient_useel = (int)(ConfigDictionary())["orient_useel"];
145  orient_usepa = (int)(ConfigDictionary())["orient_usepa"];
146  }
147  catch(Config_File_Exception)
148  {
149  orient_useel = -1;
150  orient_useel = -1;
151  _logger->log(Logger::LOG_LEV_INFO, "Orientation params set to defaults.");
152  }
153 
154  return 0;
155 }
156 
157 void VisAOIClient::SetupVars()
158 {
159  MagAOIClient::SetupVars();
160 
161 
162  try
163  {
164  wollaston_status = RTDBvar( wollaston_process, "L.STATUS", NO_DIR, INT_VARIABLE, 1,1);
165  wollaston_cmode_cur = RTDBvar( wollaston_process, "L.ConMode", CUR_VAR, INT_VARIABLE, 1,1);
166  wollaston_cmode_req = RTDBvar( wollaston_process, "L.ConMode", REQ_VAR, INT_VARIABLE, 1,1);
167  Notify(wollaston_cmode_req, WollCModeReqChanged);
168 
169  wollaston_state_cur = RTDBvar( wollaston_process, "L.state", CUR_VAR, INT_VARIABLE, 1,1);
170  wollaston_state_req = RTDBvar( wollaston_process, "L.state", REQ_VAR, INT_VARIABLE, 1,1);
171  Notify(wollaston_state_req, WollStateReqChanged);
172  }
173  catch(...)
174  {
175  _logger->log(Logger::LOG_LEV_FATAL, "Error creating wollaston status variables.");
176  throw;
177  }
178 
179 
180  try
181  {
182  focus_cmode_cur = RTDBvar( focus_process, "L.ConMode", CUR_VAR, INT_VARIABLE, 1,1);
183  focus_cmode_req = RTDBvar( focus_process, "L.ConMode", REQ_VAR, INT_VARIABLE, 1,1);
184  Notify(focus_cmode_req, FocusCModeReqChanged);
185 
186  focus_pos_cur = RTDBvar( focus_process, "L.pos", CUR_VAR, REAL_VARIABLE, 1,1);
187  focus_pos_req = RTDBvar( focus_process, "L.pos", REQ_VAR, REAL_VARIABLE, 1,1);
188  Notify(focus_pos_req, FocusPosReqChanged);
189 
190  focus_abort_req = RTDBvar( focus_process, "L.abort", REQ_VAR, INT_VARIABLE, 1,1);
191  Notify(focus_abort_req, FocusAbortReqChanged);
192 
193  focus_preset_req = RTDBvar( focus_process, "L.preset", REQ_VAR, INT_VARIABLE, 1,1);
194  Notify(focus_preset_req, FocusPresetReqChanged);
195 
196  focus_status = RTDBvar( focus_process, "L.STATUS", NO_DIR, INT_VARIABLE, 1,1);
197  focus_limsw_cur = RTDBvar( focus_process, "L.limsw", CUR_VAR, INT_VARIABLE, 1,1);
198  }
199  catch(...)
200  {
201  _logger->log(Logger::LOG_LEV_FATAL, "Error creating focus status variables.");
202  throw;
203  }
204 
205 
206  try
207  {
208  gimbal_xpos_cur = RTDBvar( gimbal_process, "L.xpos", CUR_VAR, REAL_VARIABLE, 1,1);
209  gimbal_ypos_cur = RTDBvar( gimbal_process, "L.ypos", CUR_VAR, REAL_VARIABLE, 1,1);
210  gimbal_cmode_cur = RTDBvar( gimbal_process, "L.ConMode", CUR_VAR, INT_VARIABLE, 1,1);
211  gimbal_cmode_req = RTDBvar( gimbal_process, "L.ConMode", REQ_VAR, INT_VARIABLE, 1,1);
212  Notify(gimbal_cmode_req, GimbalCModeReqChanged);
213 
214  gimbal_center_req = RTDBvar( gimbal_process, "L.center", REQ_VAR, INT_VARIABLE, 1,1);
215  gimbal_dark_req = RTDBvar( gimbal_process, "L.dark", REQ_VAR, INT_VARIABLE, 1,1);
216  Notify(gimbal_center_req, GimbalCenterReqChanged);
217  Notify(gimbal_dark_req, GimbalDarkReqChanged);
218 
219  gimbal_status = RTDBvar( gimbal_process, "L.STATUS", NO_DIR, INT_VARIABLE, 1,1);
220  }
221  catch(...)
222  {
223  _logger->log(Logger::LOG_LEV_FATAL, "Error creating gimbal status variables.");
224  throw;
225  }
226 
227 
228  try
229  {
230  var_masterremote_req = RTDBvar( MyFullName(), "Master.Remote", REQ_VAR, INT_VARIABLE, 1,1);
231  //var_masterremote_cur = RTDBvar( MyFullName(), "Master.Remote", CUR_VAR, INT_VARIABLE, 1,1);
232  Notify(var_masterremote_req, MasterRemoteReqChanged);
233 
234  ccd47_cmode_req = RTDBvar( "ccd47.L", "ConMode", REQ_VAR, INT_VARIABLE, 1,1);
235  shutter_cmode_req = RTDBvar( "shutterremote.L", "ConMode", REQ_VAR, INT_VARIABLE, 1, 1);
236  fw2_cmode_req = RTDBvar( "filterwheel2.L", "ConMode", REQ_VAR, INT_VARIABLE, 1,1);
237  fw3_cmode_req = RTDBvar( "filterwheel3.L", "ConMode", REQ_VAR, INT_VARIABLE, 1,1);
238 
239  var_avgwfe = RTDBvar( "visao", "avgwfe", NO_DIR, REAL_VARIABLE, 1,1);
240  var_stdwfe = RTDBvar( "visao", "stdwfe", NO_DIR, REAL_VARIABLE, 1,1);
241  var_instwfe = RTDBvar( "visao", "instwfe", NO_DIR, REAL_VARIABLE, 1,1);
242  }
243  catch(...)
244  {
245  _logger->log(Logger::LOG_LEV_FATAL, "Error creating Master Remote variables.");
246  throw;
247  }
248 }
249 
250 int VisAOIClient::WollStateReqChanged(void *pt, Variable *msgb __attribute__((unused)))
251 {
252  int stat = -1;
253  int newstate;
254  pthread_mutex_lock(&threadMutex);
255 
256  newstate = msgb->Value.Lv[0];
257 
258  if(newstate == 1) stat = ((VisAOIClient *)pt)->send_wollaston_command("up");
259  if(newstate == -1) stat = ((VisAOIClient *)pt)->send_wollaston_command("down");
260  if(newstate == -2) stat = ((VisAOIClient *)pt)->send_wollaston_command("ignore");
261 
262  pthread_mutex_unlock(&threadMutex);
263  return stat;
264 }
265 
266 int VisAOIClient::WollCModeReqChanged(void *pt, Variable *msgb)
267 {
268  int stat = -1;
269  int newcmode;
270  pthread_mutex_lock(&threadMutex);
271 
272  newcmode = msgb->Value.Lv[0];
273 
274  if(newcmode == 1) stat = ((VisAOIClient *)pt)->send_wollaston_command("REMOTE");
275  if(newcmode == 10) stat = ((VisAOIClient *)pt)->send_wollaston_command("XREMOTE");
276  if(newcmode == 0) stat = ((VisAOIClient *)pt)->send_wollaston_command("~REMOTE");
277 
278  pthread_mutex_unlock(&threadMutex);
279  return stat;
280 }
281 
282 int VisAOIClient::send_wollaston_command(std::string com)
283 {
284  std::string resp;
285  write_fifo_channel(WOLL_FIFO, com.c_str(), com.length()+1, &resp);
286 
287  if(resp[0] != 0) return -1;
288 
289  return 0;
290 }
291 
292 int VisAOIClient::update_wollaston()
293 {
294  std::string resp;
295 
296 
297  pthread_mutex_lock(&threadMutex);
298  write_fifo_channel(WOLL_FIFO, "state?", 6, &resp);
299  pthread_mutex_unlock(&threadMutex);
300 
301  int status, cmode, pos, prompt;
302  if(resp == "" || resp.length() <= 2)
303  {
304  status = STATE_NOCONNECTION;
305  cmode = -1;
306  pos = -2;
307  prompt = 0;
308  }
309 
310  if(resp.length() > 2)
311  {
312  status = STATE_READY;
313  switch(resp[0])
314  {
315  case 'N':
316  cmode = 0;
317  break;
318  case 'R':
319  cmode = 1;
320  break;
321  case 'L':
322  cmode = 2;
323  break;
324  case 'S':
325  cmode = 3;
326  break;
327  case 'A':
328  cmode = 4;
329  break;
330  default:
331  cmode = -1;
332  }
333 
334  pos = atoi(resp.substr(2,2).c_str());
335 
336  prompt = atoi(resp.substr(4,resp.length()-4).c_str());
337  }
338 
339  wollaston_status.Set(status, 0, CHECK_SEND);
340  wollaston_cmode_cur.Set(cmode, 0, CHECK_SEND);
341 
342  if(prompt) pos += 10;
343 
344  wollaston_state_cur.Set(pos, 0, CHECK_SEND);
345  return 0;
346 
347 }
348 
349 int VisAOIClient::FocusPosReqChanged(void *pt, Variable *msgb)
350 {
351  int stat;
352  double newpos;
353  char posstr[20];
354 
355 
356 
357  newpos = msgb->Value.Dv[0];
358 
359  snprintf(posstr, 20, "pos %0.4f\n", newpos);
360 
361  pthread_mutex_lock(&threadMutex);
362 
363  stat = ((VisAOIClient *)pt)->send_focus_command(posstr);
364 
365  pthread_mutex_unlock(&threadMutex);
366  return stat;
367 }
368 
369 int VisAOIClient::FocusAbortReqChanged(void *pt, Variable *msgb __attribute__((unused)))
370 {
371  int stat;
372 
373  pthread_mutex_lock(&threadMutex);
374 
375  stat = ((VisAOIClient *)pt)->send_focus_command("abort");
376 
377  pthread_mutex_unlock(&threadMutex);
378 
379  return stat;
380 }
381 
382 int VisAOIClient::FocusCModeReqChanged(void *pt, Variable *msgb)
383 {
384  int stat = -1;
385  int newcmode;
386  pthread_mutex_lock(&threadMutex);
387 
388  newcmode = msgb->Value.Lv[0];
389 
390  if(newcmode == 1) stat = ((VisAOIClient *)pt)->send_focus_command("REMOTE");
391  if(newcmode == 10) stat = ((VisAOIClient *)pt)->send_focus_command("XREMOTE");
392  if(newcmode == 0) stat = ((VisAOIClient *)pt)->send_focus_command("~REMOTE");
393 
394  pthread_mutex_unlock(&threadMutex);
395  return stat;
396 }
397 
398 int VisAOIClient::FocusPresetReqChanged(void *pt, Variable *msgb __attribute__((unused)))
399 {
400  int stat;
401  pthread_mutex_lock(&threadMutex);
402 
403  stat = ((VisAOIClient *)pt)->send_focus_command("preset");
404 
405  pthread_mutex_unlock(&threadMutex);
406  return stat;
407 }
408 
409 int VisAOIClient::send_focus_command(std::string com)
410 {
411  std::string resp;
412  write_fifo_channel(FOC_FIFO, com.c_str(), com.length()+1, &resp);
413 
414  if(resp[0] != 0) return -1;
415 
416  return 0;
417 }
418 
419 int VisAOIClient::update_focus()
420 {
421  std::string resp;
422 
423 
424  pthread_mutex_lock(&threadMutex);
425  write_fifo_channel(FOC_FIFO, "state?", 6, &resp);
426  pthread_mutex_unlock(&threadMutex);
427 
428  int connected, cmode, enabled, is_moving, homing, neg_limit, pos_limit, power, pos_limit_disabled;
429  double pos, remaining;
430 
431  if(resp.length() < 16)
432  {
433  connected = 0;
434  cmode = -1;
435  pos = -1e12;
436  is_moving = -2;
437  remaining = -1e-12;
438  power = 0;
439  }
440  else
441  {
442  connected = 1;
443  switch(resp[0])
444  {
445  case 'N':
446  cmode = 0;
447  break;
448  case 'R':
449  cmode = 1;
450  break;
451  case 'L':
452  cmode = 2;
453  break;
454  case 'S':
455  cmode = 3;
456  break;
457  case 'A':
458  cmode = 4;
459  break;
460  default:
461  cmode = -1;
462  }
463 
464  pos = strtod(resp.substr(2,12).c_str(),0);
465 
466  enabled = atoi(resp.substr(15,1).c_str());
467 
468  power = atoi(resp.substr(17,1).c_str());
469 
470  is_moving = atoi(resp.substr(19,1).c_str());
471 
472  homing = atoi(resp.substr(21,1).c_str());
473 
474  neg_limit = atoi(resp.substr(23,1).c_str());
475  pos_limit = atoi(resp.substr(27,1).c_str());
476 
477  remaining = strtod(resp.substr(29,12).c_str(),0);
478 
479  pos_limit_disabled = atoi(resp.substr(42,1).c_str());
480 
481  }
482 
483  focus_cmode_cur.Set(cmode, 0, CHECK_SEND);
484 
485  if(power == 0)
486  {
487  if(connected)
488  {
489  focus_status.Set(STATE_OFF, 0, CHECK_SEND);
490  }
491  else focus_status.Set(STATE_NOCONNECTION, 0, CHECK_SEND);
492 
493  focus_pos_cur.Set(pos, 0, CHECK_SEND);
494  focus_limsw_cur.Set(0, 0, CHECK_SEND);
495  }
496  else
497  {
498  if(is_moving && !homing) focus_status.Set(STATE_OPERATING, 0, CHECK_SEND);
499  else if(homing) focus_status.Set(STATE_HOMING, 0, CHECK_SEND);
500  else focus_status.Set(STATE_READY, 0, CHECK_SEND);
501 
502  if(neg_limit && pos_limit) focus_limsw_cur.Set(-10, 0, CHECK_SEND); //Send an error condition first
503  else if(pos_limit_disabled) focus_limsw_cur.Set(-5, 0, CHECK_SEND); //Then send pos_limit_disabled
504  else //otherwise normal limit switch logic.
505  {
506  if(neg_limit && !pos_limit) focus_limsw_cur.Set(-1, 0, CHECK_SEND);
507  else if(!neg_limit && pos_limit) focus_limsw_cur.Set(1, 0, CHECK_SEND);
508  else focus_limsw_cur.Set(0, 0, CHECK_SEND);
509  }
510 
511  focus_pos_cur.Set(pos, 0, CHECK_SEND);
512  }
513  return 0;
514 
515 }
516 
517 int VisAOIClient::GimbalCModeReqChanged(void *pt, Variable *msgb)
518 {
519  int stat = -1;
520  int newcmode;
521  pthread_mutex_lock(&threadMutex);
522 
523  newcmode = msgb->Value.Lv[0];
524 
525  if(newcmode == 1) stat = ((VisAOIClient *)pt)->send_gimbal_command("REMOTE");
526  if(newcmode == 10) stat = ((VisAOIClient *)pt)->send_gimbal_command("XREMOTE");
527  if(newcmode == 0) stat = ((VisAOIClient *)pt)->send_gimbal_command("~REMOTE");
528 
529  pthread_mutex_unlock(&threadMutex);
530  return stat;
531 }
532 
533 int VisAOIClient::GimbalCenterReqChanged(void *pt, Variable *msgb __attribute__((unused)))
534 {
535  int stat;
536  pthread_mutex_lock(&threadMutex);
537 
538  stat = ((VisAOIClient *)pt)->send_gimbal_command("center");
539 
540  pthread_mutex_unlock(&threadMutex);
541  return stat;
542 }
543 
544 int VisAOIClient::GimbalDarkReqChanged(void *pt, Variable *msgb __attribute__((unused)))
545 {
546  int stat;
547  pthread_mutex_lock(&threadMutex);
548 
549  stat = ((VisAOIClient *)pt)->send_gimbal_command("dark");
550 
551  pthread_mutex_unlock(&threadMutex);
552  return stat;
553 }
554 
555 int VisAOIClient::send_gimbal_command(std::string com)
556 {
557  std::string resp;
558  write_fifo_channel(GIMB_FIFO, com.c_str(), com.length()+1, &resp);
559 
560  if(resp[0] != 0) return -1;
561 
562  return 0;
563 }
564 
565 int VisAOIClient::update_gimbal()
566 {
567  std::string resp, tmp;
568 
569 
570  pthread_mutex_lock(&threadMutex);
571  write_fifo_channel(GIMB_FIFO, "state?", 6, &resp);
572  pthread_mutex_unlock(&threadMutex);
573 
574  int epos, spos;
575 
576  int connected, cmode, is_moving, curState, pwrState, xMoving, yMoving;
577  double xPos, yPos;
578 
579 
580 
581  if(resp != "" && resp.length() < 5)
582  {
583  return 0; //This means we got somebody elses response on a fifo.
584  //This happens in the GUI, but probably not here.
585  }
586 
587 
588  if(resp == "" || resp.length()<5)
589  {
590  connected = 0;
591  cmode = -1;
592 
593  return 0;
594 
595  }
596  else
597  {
598  connected = 1;
599  switch(resp[0])
600  {
601  case 'N':
602  cmode = 0;
603  break;
604  case 'R':
605  cmode = 1;
606  break;
607  case 'L':
608  cmode = 2;
609  break;
610  case 'S':
611  cmode = 3;
612  break;
613  case 'A':
614  cmode = 4;
615  break;
616  default:
617  cmode = -1;
618  }
619 
620 
621 
622  spos = resp.find(',', 0);
623  epos = resp.find(',', spos+1);
624 
625  tmp = resp.substr(spos+1, epos-spos-1);
626 
627 
628 
629  curState = atoi(tmp.c_str());
630 
631  spos = resp.find(',', epos);
632  epos = resp.find(',', spos+1);
633 
634  pwrState = atoi(tmp.c_str());
635 
636  spos = resp.find(',', epos);
637  epos = resp.find(',', spos+1);
638 
639  tmp = resp.substr(spos+1, epos-spos-1);
640 
641 
642 
643  xMoving = atoi(tmp.c_str());
644 
645  spos = resp.find(',', epos);
646  epos = resp.find(',', spos+1);
647 
648  tmp = resp.substr(spos+1, epos-spos-1);
649 
650 
651  xPos = strtod(tmp.c_str(),0);
652 
653  //** y moving **//
654  spos = resp.find(',', epos);
655  epos = resp.find(',', spos+1);
656 
657  tmp = resp.substr(spos+1, epos-spos-1);
658 
659  yMoving = atoi(tmp.c_str());
660 
661  is_moving = yMoving + xMoving;
662 
663  //** y position **//
664  spos = resp.find(',', epos);
665  epos = resp.find(',', spos+1);
666  if(epos == -1) epos = resp.length();
667 
668  tmp = resp.substr(spos+1, epos-spos-1);
669 
670  yPos = strtod(tmp.c_str(),0);
671 
672  //** Scale ** //
673  spos = resp.find(',', epos);
674  epos = resp.find(',', spos+1);
675  if(epos == -1) epos = resp.length();
676 
677  tmp = resp.substr(spos+1, epos-spos-1);
678 
679 
680  }
681 
682 
683 
684  gimbal_cmode_cur.Set(cmode, 0, CHECK_SEND);
685 
686 
687  if(!connected)
688  {
689 
690  gimbal_status.Set(STATE_NOCONNECTION, 0, CHECK_SEND);
691 
692  }
693  else
694  {
695  if(is_moving) gimbal_status.Set(STATE_OPERATING, 0, CHECK_SEND);
696  else gimbal_status.Set(STATE_READY, 0, CHECK_SEND);
697 
698  gimbal_xpos_cur.Set(xPos, 0, CHECK_SEND);
699  gimbal_ypos_cur.Set(yPos, 0, CHECK_SEND);
700 
701  }
702 
703  return 0;
704 
705 }
706 
707 int VisAOIClient::MasterRemoteReqChanged(void *pt, Variable *msgb)
708 {
709 
710  int stat, newcmode;
711  pthread_mutex_lock(&threadMutex);
712 
713  newcmode = msgb->Value.Lv[0];
714 
715 
716  stat = ((VisAOIClient *)pt)->setMasterRemote(newcmode);
717 
718  pthread_mutex_unlock(&threadMutex);
719  return stat;
720 }
721 
723 {
724  if(cmode == 1)
725  {
726  send_gimbal_command("REMOTE");
727  send_focus_command("REMOTE");
728  }
729  else if(cmode == 10)
730  {
731  send_gimbal_command("XREMOTE");
732  send_focus_command("XREMOTE");
733  }
734  else if(cmode == 0)
735  {
736  send_gimbal_command("~REMOTE");
737  send_focus_command("~REMOTE");
738  }
739 
740  ccd47_cmode_req.Set(cmode, 0, FORCE_SEND);
741  shutter_cmode_req.Set(cmode, 0, FORCE_SEND);
742  fw2_cmode_req.Set(cmode, 0, FORCE_SEND);
743  fw3_cmode_req.Set(cmode, 0, FORCE_SEND);
744 
745  return 0;
746 }
747 
748 void VisAOIClient::Run()
749 {
750  _logger->log( Logger::LOG_LEV_INFO, "Running...");
751 
752  init_DD(); //strtod(aoi.side.ao.loop_gains.substr(p+4, 4).c_str(), 0);
753 
754  init_statusboard();
755 
756  signal(SIGIO, SIG_IGN);
758 
759  global_fifo_list = &fl;
760 
761  while(!TimeToDie())
762  {
763 
764  try
765  {
766  sleep(1);
767 
769  update_wollaston();
770  update_focus();
771  update_gimbal();
772  update_recon();
773 
774  }
775  catch (AOException &e)
776  {
777  _logger->log( Logger::LOG_LEV_ERROR, "Caught exception (at %s:%d): %s", __FILE__, __LINE__, e.what().c_str());
778 
779  sleep(1);
780  }
781 
782  }
783 }
784 
785 void VisAOIClient::post_update_DD_var(DD_RTDBVar &var)
786 {
787 
789  {
790 // if(var.RTVar.complete_name() == "ADSEC.L.G_GAIN_A@M_ADSEC")
791 // {
792 //
793 // std::cout << "-------> " << aoi.side.ao.loop_gains << std::endl;
794 //
795 // int p = aoi.side.ao.loop_gains.find("g_tt_", 0);
796 // if(p < 0 || p > (int)aoi.side.ao.loop_gains.length() - 4)
797 // {
798 // aosb->loop_gain_tt = 0.;
799 // }
800 // else
801 // {
802 //
803 // aosb->loop_gain_tt = strtod(aoi.side.ao.loop_gains.substr(p+5, 4).c_str(), 0);
804 //
805 //
806 //
807 // p = aoi.side.ao.loop_gains.find("_ho1_", 0);
808 // std::cout << "p: " << p << "\n";
809 // if(p < 0 || p > (int)aoi.side.ao.loop_gains.length() - 5)
810 // {
811 // aosb->loop_gain_ho1 = 0.;
812 // }
813 // else
814 // {
815 // aosb->loop_gain_ho1 = strtod(aoi.side.ao.loop_gains.substr(p+5, 4).c_str(), 0);
816 // }
817 //
818 // p = aoi.side.ao.loop_gains.find("_ho2_", p);
819 // if(p < 0 || p > (int)aoi.side.ao.loop_gains.length() - 5)
820 // {
821 // aosb->loop_gain_ho2 = 0.;
822 // }
823 // else
824 // {
825 // aosb->loop_gain_ho2 = strtod(aoi.side.ao.loop_gains.substr(p+5, 4).c_str(), 0);
826 // }
827 // }
828 /*
829  return;
830  }//"ADSEC.L.G_GAIN_A@M_ADSEC"*/
831 
832  if(var.RTVar.complete_name() == "optloopdiag.L.COUNTS")
833  {
834  aosb->wfs_counts = aoi.side.wfs1.counts;
835 
836  return;
837  }//"optloopdiag.L.COUNTS"
838 
839  if(var.RTVar.complete_name() == "wfsarb.L.FSM_STATE")
840  {
841  update_loopon();
842  }//"wfsarb.L.FSM_STATE"
843 
844  if(var.RTVar.complete_name() == "MagAOI.cmds.NodRaDec.InProgress@M_ADSEC")
845  {
846  aosb->nodInProgress = aoi.nodInProgress;
847  std::cout << "nodInProgress: " << aosb->nodInProgress << "\n";
848  }
849  }// if(statusboard_shmemptr)
850 }
851 
852 void VisAOIClient::update_loopon()
853 {
854  int old_loop_on = aosb->loop_on;
855 
856  if(aoi.side.wfs1.status == "LoopClosed") aosb->loop_on = 1;
857  else if(aoi.side.wfs1.status == "LoopPaused") aosb->loop_on = 2;
858  else aosb->loop_on = 0;
859 
860  if (aosb->loop_on == 1)
861  {
862  //Check gains
863  if(aosb->loop_gain_tt == 0.0000) aosb->loop_on = 2;
864  }
865 
866  if(old_loop_on == 1 && aosb->loop_on != 1) aosb->loop_open_counter++;
867 
868  timeval tv;
869  gettimeofday(&tv, 0);
870  dataLogger(tv);
871 
872 }
873 
874 void VisAOIClient::init_statusboard()
875 {
877  {
878 
879 
880  aosb->dateobs[0] = '\0';
881  aosb->ut = 0;
882  aosb->epoch = 0;
883  aosb->ra = aoi.ra;
884  aosb->dec = aoi.dec;
885  aosb->az = aoi.az.position;
886  aosb->el = aoi.el.position;
887  aosb->am = aoi.am;
888  aosb->pa = aoi.pa;
889  aosb->ha = aoi.ha;
890  aosb->zd = aoi.zd;
891  aosb->st = aoi.st;
892  aosb->filter1_pos = 0.;
893  aosb->filter1_reqpos = 0.;
894 
895  aosb->correctedmodes = aoi.side.ao.correctedmodes;
896  strncpy(aosb->filter1_name, aoi.side.wfs1.filter1.c_str(), 256);
897 
898  for(int i=0;i<3;i++)
899  {
900  aosb->tt_amp[i] = aoi.side.ao.tt_amp[i];
901  aosb->tt_freq[i] = aoi.side.ao.tt_freq[i];
902  aosb->tt_offset[i] = aoi.side.ao.tt_offset[i];
903  }
904 
905 
906 
907 
908 
909  aosb->ccd39_freq = aoi.side.wfs1.ccdfreq;
910  aosb->ccd39_bin = aoi.side.wfs1.ccdbin;
911  std::cout << "-------> " << aoi.side.ao.loop_gains << std::endl;
912  int p = aoi.side.ao.loop_gains.find("g_tt_", 0);
913  if(p < 0 || p > (int)aoi.side.ao.loop_gains.length() - 4)
914  {
915  aosb->loop_gain_tt = 0.;
916  }
917  else
918  {
919  aosb->loop_gain_tt = strtod(aoi.side.ao.loop_gains.substr(p+5, 4).c_str(), 0);
920  p = aoi.side.ao.loop_gains.find("_ho1_", p);
921  if(p < 0 || p > (int) aoi.side.ao.loop_gains.length() - 4)
922  {
923  aosb->loop_gain_ho1 = 0.;
924  }
925  else
926  {
927  aosb->loop_gain_ho1 = strtod(aoi.side.ao.loop_gains.substr(p+5, 4).c_str(), 0);
928  }
929  p = aoi.side.ao.loop_gains.find("_ho2_", p);
930  if(p < 0 || p > (int) aoi.side.ao.loop_gains.length() - 5)
931  {
932  aosb->loop_gain_ho2 = 0.;
933  }
934  else
935  {
936  aosb->loop_gain_ho2 = strtod(aoi.side.ao.loop_gains.substr(p+5, 4).c_str(), 0);
937  }
938  }
939 
940  update_loopon();
941 
942  aosb->wfs_counts = aoi.side.wfs1.counts;
943 
944  aosb->loop_open_counter = 0;
945 
946  }
947 }
948 
949 //Parse the reconstructor file name.
950 std::string parse_for_fits(std::string & path)
951 {
952  int fitstart = path.rfind(".fits");
953 
954  int slash = path.rfind("/", fitstart);
955  std::cout << path << "\n";
956  std::cout << fitstart << " " << slash << "\n";
957 
958  if(slash > -1) return path.substr(slash+1);
959  else return "none";
960 }
961 
963 {
965  {
967 
968  strncpy(aosb->dateobs, aoi.dateobs.c_str(), 256);
969  aosb->ut = aoi.ut;
970  aosb->epoch = aoi.epoch;
971  aosb->ra = aoi.ra;
972  aosb->dec = aoi.dec;
973  aosb->az = aoi.az.position;
974  aosb->el = aoi.el.position;
975  aosb->am = aoi.am;
976  aosb->pa = aoi.pa;
977  aosb->ha = aoi.ha;
978  aosb->zd = aoi.zd;
979  aosb->st = aoi.st;
980 
981  aosb->istracking = aoi.istracking;
982  aosb->isguiding = aoi.isguiding;
983  aosb->isslewing = aoi.isslewing;
984  aosb->guider_ismoving = aoi.guider_ismoving;
985 
986  aosb->catra = aoi.cat.ra;
987  aosb->catdec = aoi.cat.dec;
988  aosb->catep = aoi.cat.epoch;
989  aosb->catro = aoi.cat.rotOff;
990 
991  strncpy(aosb->catrm, aoi.cat.rotMode.c_str(), 256);
992  strncpy(aosb->catobj, aoi.cat.obj.c_str(), 256);
993 
994  strncpy(aosb->obsinst, aoi.cat.obsinst.c_str(), 256);
995  strncpy(aosb->obsname, aoi.cat.obsname.c_str(), 256);
996 
997  aosb->rotang = aoi.rotator.angle;
998  aosb->rotoffset = aoi.rotator.offset;
999  aosb->rotfollowing = aoi.rotator.following;
1000 
1001  aosb->wxtemp = aoi.environ.wxtemp;
1002  aosb->wxpres = aoi.environ.wxpres;
1003  aosb->wxhumid = aoi.environ.wxhumid;
1004  aosb->wxwind = aoi.environ.wxwind;
1005  aosb->wxwdir = aoi.environ.wxwdir;
1006  aosb->wxdewpoint = aoi.environ.wxdewpoint;
1007  aosb->wxpwvest = aoi.environ.wxpwvest;
1008  aosb->ttruss = aoi.environ.ttruss;
1009  aosb->tcell = aoi.environ.tcell;
1010  aosb->tseccell = aoi.environ.tseccell;
1011  aosb->tambient = aoi.environ.tambient;
1012  aosb->dimmfwhm = aoi.environ.dimmfwhm;
1013  aosb->dimmtime = aoi.environ.dimmtime;
1014  aosb->mag1fwhm = aoi.environ.mag1fwhm;
1015  aosb->mag1time = aoi.environ.mag1time;
1016 
1017  aosb->baysidex = aoi.side.wfs1.baysidex;
1018  aosb->baysidex_enabled = aoi.side.wfs1.baysidex_enabled;
1019  aosb->baysidey = aoi.side.wfs1.baysidey;
1020  aosb->baysidey_enabled = aoi.side.wfs1.baysidey_enabled;
1021  aosb->baysidez = aoi.side.wfs1.baysidez;
1022  aosb->baysidez_enabled = aoi.side.wfs1.baysidez_enabled;
1023 
1024  aosb->filter1_pos = aoi.side.wfs1.filter1_pos;
1025 
1026  if(aoi.side.wfs1.filter1_reqpos == aoi.side.wfs1.filter1_homingpos)
1027  {
1028  aosb->filter1_reqpos = aoi.side.wfs1.filter1_startpos;
1029  }
1030  else if(aoi.side.wfs1.filter1_reqpos == aoi.side.wfs1.filter1_abortpos)
1031  {
1032  aosb->filter1_reqpos = aoi.side.wfs1.filter1_pos;
1033  }
1034  else
1035  {
1036  aosb->filter1_reqpos = aoi.side.wfs1.filter1_reqpos;
1037  }
1038 
1039 
1040  strncpy(aosb->filter1_name, aoi.side.wfs1.filter1.c_str(), 256);
1041 
1042 
1043  aosb->correctedmodes = aoi.side.ao.correctedmodes;
1044  strncpy(aosb->filter1_name, aoi.side.wfs1.filter1.c_str(), 256);
1045 
1046  aosb->n_modes = aoi.side.ao.nmodes;
1047  aosb->homiddle = aoi.side.ao.homiddle;
1048  aosb->loop_gain_tt = aoi.side.ao.gain_tt;
1049  aosb->loop_gain_ho1 = aoi.side.ao.gain_ho1;
1050  aosb->loop_gain_ho2 = aoi.side.ao.gain_ho2;
1051 
1052  for(int i=0;i<3;i++)
1053  {
1054  aosb->tt_amp[i] = aoi.side.ao.tt_amp[i];
1055  aosb->tt_freq[i] = aoi.side.ao.tt_freq[i];
1056  aosb->tt_offset[i] = aoi.side.ao.tt_offset[i];
1057  }
1058 
1059 
1060  aosb->ccd39_freq = aoi.side.wfs1.ccdfreq;
1061  aosb->ccd39_bin = aoi.side.wfs1.ccdbin;
1062 
1063  strncpy(aosb->reconstructor,parse_for_fits(aoi.side.ao.reconstructor).c_str(), 256);
1064 
1065  aosb->orient_useel = orient_useel;
1066  aosb->orient_usepa = orient_usepa;
1067 
1068  update_loopon();
1069 
1070  //#ifdef _debug
1071  dump_statusboard();
1072  //#endif
1073  }
1074  return 0;
1075 }//int VisAOIClient::update_statusboard()
1076 
1077 void VisAOIClient::dump_statusboard()
1078 {
1079 
1081  std::cout << "VisAOIClient ao status board\n";
1082  std::cout << "Tgt:\t" << aosb->catobj << "\n";
1083  std::cout << "Tracking:\t" << aosb->istracking << "\n";
1084  std::cout << "Guiding:\t" << aosb->isguiding << "\n\n";
1085  std::cout << "DATEOBS:\t" << aosb->dateobs << "\n";
1086  std::cout << "UT:\t" << aosb->ut << "\n";
1087  std::cout << "EPOCH:\t" << aosb->epoch << "\n";
1088  std::cout << "RA:\t" << aosb->ra << "\n";
1089  std::cout << "DEC:\t" << aosb->dec << "\n";
1090  std::cout << "AZ:\t" << aosb->az << "\n";
1091  std::cout << "EL:\t" << aosb->el << "\n";
1092  std::cout << "AM:\t" << aosb->am << "\n";
1093  std::cout << "PA:\t" << aosb->pa << "\n";
1094  std::cout << "HA:\t" << aosb->ha << "\n";
1095  std::cout << "ZD:\t" << aosb->zd << "\n";
1096  std::cout << "ST:\t" << aosb->st << "\n";
1097 
1098  std::cout << "Rot-ang:\t" << aosb->rotang << "\n";
1099  std::cout << "Rot-offset:\t" << aosb->rotoffset << "\n";
1100  std::cout << "Rot-following:\t" << aosb->rotfollowing << "\n";
1101 
1102  std::cout << "obsinst:\t" << aosb->obsinst << "\n";
1103  std::cout << "obsname:\t" << aosb->obsname << "\n";
1104 
1105  std::cout << "wxtemp:\t" << aosb->wxtemp << "\n";
1106  std::cout << "wxpres:\t" << aosb->wxpres << "\n";
1107  std::cout << "wxhumid:\t" << aosb->wxhumid << "\n";
1108  std::cout << "wxwind:\t" << aosb->wxwind << "\n";
1109  std::cout << "wxwdir:\t" << aosb->wxwdir << "\n";
1110  std::cout << "ttruss:\t" << aosb->ttruss << "\n";
1111  std::cout << "tcell:\t" << aosb->tcell << "\n";
1112  std::cout << "tseccell:\t" << aosb->tseccell << "\n";
1113  std::cout << "tambient:\t" << aosb->tambient << "\n";
1114  std::cout << "dimmfwhm:\t" << aosb->dimmfwhm << "\n";
1115 
1116  std::cout << "baysidex:\t" << aosb->baysidex << "\n";
1117  std::cout << "baysidex_enabled:\t" << aosb->baysidex_enabled << "\n";
1118  std::cout << "baysidey:\t" << aosb->baysidey << "\n";
1119  std::cout << "baysidey_enabled:\t" << aosb->baysidey_enabled << "\n";
1120  std::cout << "baysidez:\t" << aosb->baysidez << "\n";
1121  std::cout << "baysidez_enabled:\t" << aosb->baysidez_enabled << "\n";
1122 
1123  std::cout << "FW 1:\t" << aosb->filter1_pos << " " << aosb->filter1_name << "\n";
1124  std::cout << "FW 1 REQ:\t" << aosb->filter1_reqpos << "\n";
1125 
1126  std::cout << "Reconstructor:\t" << aosb->reconstructor << "\n";
1127  std::cout << "Modes:\t" << aosb->correctedmodes << "\n";
1128  std::cout << "TT offset\t freq \t amp\n";
1129  for(int i=0;i<3;i++) std::cout << "\t" << aosb->tt_offset[i] << "\t" << aosb->tt_freq[i] << "\t" << aosb->tt_amp[i] << "\n";
1130  std::cout << "Loop: " << aosb->loop_on << "\n";
1131  std::cout << "Modes: " << aosb->correctedmodes << "\n";
1132  std::cout << "Speed: " << aosb->ccd39_freq << "\n";
1133  std::cout << "Bin: " << aosb->ccd39_bin << "\n";
1134  std::cout << "Gainset nmodes: " << aosb->n_modes << "\n";
1135  std::cout << "Gainset homiddle: " << aosb->homiddle << "\n";
1136  std::cout << "Gains: " << aosb->loop_gain_tt << " " << aosb->loop_gain_ho1 << " " << aosb->loop_gain_ho2 << "\n";
1137  std::cout << "Counts: " << aosb->wfs_counts << "\n";
1138 
1139  std::cout << std::endl;
1140 }//int VisAOIClient::dump_statusboard()
1141 
1142 void VisAOIClient::update_recon()
1143 {
1144  size_t sz;
1145 
1146  if(!rsb)
1147  {
1149  }
1150 
1151  if(rsb)
1152  {
1153  if((get_curr_time() - ts_to_curr_time(&rsb->last_update)) < 2.*rsb->max_update_interval)
1154  {
1155  var_avgwfe.Set(rsb->avgwfe_1_sec,0, FORCE_SEND);
1156  var_stdwfe.Set(rsb->stdwfe_1_sec,0, FORCE_SEND);
1157  var_instwfe.Set(rsb->inst_wfe,0, FORCE_SEND);
1158  }
1159  else
1160  {
1161  var_avgwfe.Set(-1.,0, FORCE_SEND);
1162  var_stdwfe.Set(-1.,0, FORCE_SEND);
1163  var_instwfe.Set(-1.,0, FORCE_SEND);
1164 
1165  }
1166 
1167  }
1168 }
1169 
1170 
1171 
1173 {
1174  checkDataFileOpen();
1175 
1176  dataof << tv.tv_sec << " " << tv.tv_usec << " " << aosb->loop_on;
1177 
1178  if(rsb) dataof << " " << rsb->avgwfe_1_sec << " " << rsb->stdwfe_1_sec;
1179  else dataof << " " << -1.0 << " " << -1.0;
1180  dataof << "\n";
1181 
1182  if(!dataof.good())
1183  {
1184  Logger::get()->log(Logger::LOG_LEV_ERROR, "Error in AOsystem data file. AO system data may not be logged correctly");
1185  }
1186 
1187 
1188 }
1189 
1190 } //namespace VisAO
int update_statusboard()
Update the status board.
fifo_list * global_fifo_list
The global fifo_list, for signal handling.
Definition: dioserver.cpp:19
double get_curr_time(void)
Gets the current CLOCK_REALTIME time, returns it in seconds to double precision.
Definition: libvisaoc.c:40
double inst_wfe
Instantaneous WFE.
Definition: statusboard.h:145
double wait_to
The timeout for waiting on responses from FIFOs in seconds.
#define STATUS_reconstructor
Shared memory key for the reconstructor status board.
Definition: statusboard.h:49
void * statusboard_shmemptr
The pointer to the shared memory block for the statusboard.
virtual int update_statusboard()
Update the status board.
int setup_fifo_list(int nfifos)
Allocate the fifo_list.
double stdwfe_1_sec
1 second std dev of WFE
Definition: statusboard.h:144
key_t statusboard_shmemkey
The key used to lookup the shared memory.
virtual void dataLogger(timeval tv)
Log data at intervals.
int TimeToDie
Global set by SIGTERM.
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
fifo_list fl
The list of named-pipe fifos used for inter-process comms.
The base class for VisAO applications.
Definition: VisAOApp_base.h:48
double pause_time
Time to pause during application main loop.
Definition: VisAOApp_base.h:84
static int MasterRemoteReqChanged(void *pt, Variable *msgb)
When notified, VisAOIClient changes the control mode of the entire VisAO Camera.
int create_statusboard(size_t sz)
Creates and attaches to the statusboard shared memory.
std::string fifo_path
The path to the fifos, relative to VISAO_ROOT.
Definition: VisAOIClient.h:26
pthread_mutex_t threadMutex
Mutex to lock out other threads during complex operations.
Definition: VisAOIClient.cpp:8
int connect_fifo_list()
Connect the fifo_list with exclusive locking.
double ts_to_curr_time(struct timespec *tsp)
Convert a timespec structure to double seconds.
Definition: libvisaoc.c:30
int LoadConfig()
Load the configuration details from the file.
The namespace of VisAO software.
int setMasterRemote(int cmode)
Change control of Gimbal, Focus, F/W2, F/W3, CCD47.
double avgwfe_1_sec
1 second average WFE
Definition: statusboard.h:143
#define RWBUFF_SZ
The size of the i/o buffer.
Definition: fifoutils.h:43
int set_fifo_list_channel(fifo_list *fl, int nch, int buffsz, const char *fin, const char *fout, int(*inp_hand)(fifo_channel *), void *adata)
Set the details of one channel in the list.
Definition: fifoutils.c:373
int write_fifo_channel(int ch, const char *com, int comlen, std::string *resp)
Write data to a fifo_channel, and get a response if desired.