The VisAO Camera
frameselector.cpp
Go to the documentation of this file.
1 /************************************************************
2  * frameselector.cpp
3  *
4  * Author: Jared R. Males (jrmales@email.arizona.edu)
5  *
6  * Definitions for the real time frame selector
7  *
8  * Developed as part of the Magellan Adaptive Optics system.
9  ************************************************************/
10 
11 /** \file frameselector.cpp
12  * \author Jared R. Males
13  * \brief Definitions for the real time frame selector
14  *
15  *
16  */
17 
18 #include "frameselector.h"
19 #define SELECTOR_PING_CH 0
20 #define SHUTTER_AUTO_CH 1
21 
22 namespace VisAO
23 {
24 
25 ///For the auto command handler, which live in the main thread.
27 
28 frameselector::frameselector(int argc, char **argv) throw (AOException) : VisAOApp_standalone(argc, argv)
29 {
30  Create();
31 }
32 
33 frameselector::frameselector(std::string name, const std::string &conffile) throw (AOException) : VisAOApp_standalone(name, conffile)
34 {
35  Create();
36 }
37 
38 int frameselector::Create()
39 {
40  std::string pathtmp;
41 
42  std::string visao_root = getenv("VISAO_ROOT");
43 
44  //block_sigio();
45  signal(SIGIO, SIG_IGN);
46 
47  //Set up the ping_fifo_path
48  try
49  {
50  pathtmp = (std::string)(ConfigDictionary())["ping_fifo_path"];
51  }
52  catch(Config_File_Exception)
53  {
54  pathtmp = "fifos";
55  }
56  ping_fifo_path = visao_root + "/" + pathtmp +"/";
57  _logger->log(Logger::LOG_LEV_INFO, "Set ping_fifo_path: %s", ping_fifo_path.c_str());
58 
59  std::string shutter_fifo_path = visao_root + "/fifos/shuttercontrol_com_auto";
60 
61  _logger->log(Logger::LOG_LEV_INFO, "Set shutter_fifo_path: %s", shutter_fifo_path.c_str());
62 
63  std::string sf_in = shutter_fifo_path + "_in";
64  std::string sf_out = shutter_fifo_path + "_out";
65 
66  setup_fifo_list(5);
67  setup_baseApp(0, 1, 1, 1, false);
68  //setup_baseApp();
69 
70  set_fifo_list_channel(&fl, SELECTOR_PING_CH, RWBUFF_SZ, (char *)std::string(ping_fifo_path + MyName()+"_ping_in").c_str(), (char *)std::string(ping_fifo_path + MyName()+"_ping_out").c_str(), 0, (void *)this);
71 
72  set_fifo_list_channel(&fl, SHUTTER_AUTO_CH, RWBUFF_SZ, sf_out.c_str(), sf_in.c_str(), 0, 0);
73 
74  try
75  {
76  shmem_key = (int)(ConfigDictionary())["shmem_key"];
77  }
78  catch(Config_File_Exception)
79  {
80  _logger->log(Logger::LOG_LEV_FATAL, "shmem_key is a required config parameter.");
81  throw;
82  }
83  attached_to_shmem = false;
84 
85 
87 
89  {
90  if(create_statusboard(sizeof(basic_status_board)) != 0)
91  {
93  _logger->log(Logger::LOG_LEV_ERROR, "Could not create status board.");
94  }
95  else
96  {
98  strncpy(bsb->appname, MyFullName().c_str(), 25);
99  bsb->max_update_interval = pause_time;
100  }
101  }
102 
103  frame_select = false;
104  thresh = 0.;
105  pthread_mutex_init(&select_mutex, NULL);
106  pthread_cond_init(&strehl_ready_cond, NULL);
107  pthread_mutex_init(&strehl_ready_mutex, NULL);
108 
109  return 0;
110 }
111 
112 int frameselector::connect_shmem()
113 {
115  if(sis->attach_shm(shmem_key) != 0)
116  {
117  ERROR_REPORT("Error attaching to shared memory.");
118  attached_to_shmem = false;
119  delete sis;
120  return -1;
121  }
122  attached_to_shmem = true;
123  return 0;
124 }
125 
127 {
128  int totbytes;
129  connect_shmem();
130 
131  signal(SIGIO, SIG_IGN);
132  signal(RTSIGIO, SIG_IGN);
133 
134  //Install the main thread handler
136  {
137  ERROR_REPORT("Error installing main thread catcher.");
138  return -1;
139  }
140 
141  //Startup the I/O signal handling thread
142  if(start_signal_catcher(false) != 0)
143  {
144  ERROR_REPORT("Error starting signal catching thread.");
145  return -1;
146  }
147 
148  sleep(1);
149 
150  //Now Block all I/O signals in this thread.
151  if(block_sigio() != 0)
152  {
153  ERROR_REPORT("Error blocking SIGIO in main thread.");
154  return -1;
155  }
156 
157 //Setup to catch the ping in this high priority thread
158  //The low priority signal catcher will block it.
159  global_selector = this;
160 
161  fcntl(fl.fifo_ch[SELECTOR_PING_CH].fd_in, F_SETOWN, getpid());
162 
163  int rv = fcntl(fl.fifo_ch[SELECTOR_PING_CH].fd_in, F_SETSIG, RTSIGPING);
164  if(rv < 0)
165  {
166  std::cerr << "Error changing signal.\n";
167  perror("frameselector");
168  }
169 
170  struct sigaction act;
171  sigset_t sset;
172 
173  act.sa_sigaction = &strehl_ready;
174  act.sa_flags = SA_SIGINFO;
175  sigemptyset(&sset);
176  act.sa_mask = sset;
177 
178  errno = 0;
179 
180  if(sigaction(RTSIGPING, &act, 0) < 0)
181  {
182  logss.str("");
183  logss << "Error setting signal handler for RTSIGPING. Errno says: " << strerror(errno) << ".";
184  error_report(Logger::LOG_LEV_ERROR, logss.str());
185  return -1;
186  }
187 
188  LOG_INFO("starting up . . .");
189 
190  while(!TimeToDie)
191  {
192  usleep(100);
193  totbytes = 1;
194  while(totbytes)
195  {
196  totbytes = read_fifo_channel(&fl.fifo_ch[SELECTOR_PING_CH]);
197  }
198  }
199 
200  pthread_join(signal_thread, 0);
201 
202  return 0;
203 }
204 
205 int frameselector::selector()
206 {
207  static int last_image = -1;
208  int curr_image;
209 
210  if(!frame_select) return 0;
211 
212  if(pthread_mutex_trylock(&select_mutex) != 0 )
213  {
214  return 0;
215  }
216 
217  curr_image = sis->get_last_image();
218 
219  if(curr_image == last_image || curr_image < -1) return 0;
220 
221  sim = sis->get_image(curr_image);
222  last_image = curr_image;
223 
224  if(sim.imdata[7] >= thresh)
225  {
226  write_fifo_channel(SHUTTER_AUTO_CH, "1", 1, 0);
227  }
228  else
229  {
230  write_fifo_channel(SHUTTER_AUTO_CH, "0", 1, 0);
231  }
232  fl.fifo_ch[SHUTTER_AUTO_CH].timeout = 0;
233 
234 
235  pthread_mutex_unlock(&select_mutex);
236 
237  return 0;
238 }
239 
240 std::string frameselector::remote_command(std::string com)
241 {
242  std::string resp;
243  _logger->log(Logger::LOG_LEV_TRACE, "Received remote command: %s.", com.c_str());
244  resp = common_command(com, CMODE_REMOTE);
245  if(resp == "") resp = (std::string("UNKOWN COMMAND: ") + com + "\n");
246  _logger->log(Logger::LOG_LEV_TRACE, "Response to remote command: %s.", resp.c_str());
247  return resp;
248 }
249 
250 std::string frameselector::local_command(std::string com)
251 {
252  std::string resp;
253  _logger->log(Logger::LOG_LEV_TRACE, "Received local command: %s.", com.c_str());
254  resp = common_command(com, CMODE_LOCAL);
255  if(resp == "") resp = (std::string("UNKOWN COMMAND: ") + com + "\n");
256  _logger->log(Logger::LOG_LEV_TRACE, "Response to local command: %s.", resp.c_str());
257  return resp;
258 }
259 
260 std::string frameselector::script_command(std::string com)
261 {
262  std::string resp;
263  _logger->log(Logger::LOG_LEV_TRACE, "Received script command: %s.", com.c_str());
264  resp = common_command(com, CMODE_SCRIPT);
265  if(resp == "") resp = (std::string("UNKOWN COMMAND: ") + com + "\n");
266  _logger->log(Logger::LOG_LEV_TRACE, "Response to script command: %s.", resp.c_str());
267  return resp;
268 }
269 
270 std::string frameselector::auto_command(std::string com, char *seqmsg)
271 {
272  std::string resp;
273  _logger->log(Logger::LOG_LEV_TRACE, "Received auto command: %s.", com.c_str());
274  resp = common_command(com, CMODE_AUTO);
275  seqmsg = 0; //just to avoid the warning
276  if(resp == "") resp = post_auto_command(com);
277  _logger->log(Logger::LOG_LEV_TRACE, "Response to auto command: %s.", resp.c_str());
278  return resp;
279 }
280 
281 std::string frameselector::common_command(std::string com, int cmode)
282 {
283  int rv;
284 
285  char str[256];
286  std::string resp;
287 
288  if(com == "thresh?")
289  {
290  snprintf(str, 256, "%0.4f\n", thresh);
291  return str;
292  }
293 
294  if(com == "state?")
295  {
296  return get_state_str();
297  }
298 
299  if(com == "frame_select?")
300  {
301  snprintf(str, 256, "%i\n", frame_select);
302  return str;
303  }
304 
305  if(com == "start" && cmode == control_mode)
306  {
307  logss.str("");
308  logss << "start selecting - thresh: " << thresh;
309 
310  _logger->log(Logger::LOG_LEV_INFO, logss.str().c_str());
311 
312  write_fifo_channel(SHUTTER_AUTO_CH, "AUTO", 4, 0);
313  frame_select = true;
314  fl.fifo_ch[SHUTTER_AUTO_CH].timeout = 0;
315  return "0\n";
316  }
317 
318  if(com == "stop" && cmode == control_mode)
319  {
320  write_fifo_channel(SHUTTER_AUTO_CH, "1", 1, 0);
321  fl.fifo_ch[SHUTTER_AUTO_CH].timeout = 0;
322  frame_select = false;
323  sleep(1);
324  write_fifo_channel(SHUTTER_AUTO_CH, "~AUTO", 5, 0);
325 
326  logss.str("");
327  logss << "stop selecting";
328 
329  _logger->log(Logger::LOG_LEV_INFO, logss.str().c_str());
330 
331  return "0\n";
332  }
333 
334  if(com.length() > 6)
335  {
336  if(com.substr(0,6) == "thresh" && cmode == control_mode)
337  {
338  double newthresh = strtod(com.substr(6, com.length()-6).c_str(), 0);
339  if(newthresh >= 0. && newthresh < 1.0)
340  {
341  thresh = newthresh;
342  return "0\n";
343  }
344  else return "-1\n";
345  }
346 
347  }
348 
349 
350  return "";
351 }
352 
353 std::string frameselector::get_state_str()
354 {
355  std::string sstr;
356  char schr[50];
357 
358 
359  switch(control_mode)
360  {
361  case CMODE_NONE:
362  sstr = "N";
363  break;
364  case CMODE_REMOTE:
365  sstr = "R";
366  break;
367  case CMODE_LOCAL:
368  sstr = "L";
369  break;
370  case CMODE_SCRIPT:
371  sstr = "S";
372  break;
373  case CMODE_AUTO:
374  sstr = "A";
375  return sstr;
376  default:
377  sstr = "E";
378  break;
379  }
380 
381  snprintf(schr, 50, "%c %i %f", sstr[0], frame_select, thresh);
382 
383  return schr;
384 }
385 
386 
388 {
389  pthread_cond_broadcast(&strehl_ready_cond);
390  return 0;
391 }
392 
394 {
396  {
398 
400 
401  fssb->frame_select = frame_select;
402  fssb->thresh = thresh;
403 
404  }
405 
406  return 0;
407 
408 }
409 
410 void strehl_ready(int signum, siginfo_t *siginf, void *ucont)
411 {
412  if(siginf->si_code == POLL_IN)
413  {
414  global_selector->selector();
415  }
416 }
417 
418 
419 
420 
421 }//namespace VisAO
std::string common_command(std::string com, int cmode)
The common command processor for commands received by fifo.
virtual int Run()
The application main loop, to be re-implemented in derived classes.
virtual int start_signal_catcher(bool inherit_sched=true)
Starts the signal catching loop.
frameselector * global_selector
For the auto command handler, which live in the main thread.
virtual std::string script_command(std::string com)
Overridden from VisAOApp_base::script_command, here just calls common_command.
int read_fifo_channel(fifo_channel *fc)
Read data from the input fifo channel.
Definition: fifoutils.c:246
#define STATUS_frameselector
Shared memory key for the frame selector status board.
Definition: statusboard.h:74
virtual int update_statusboard()
Update the status board.
The standalone VisAO application, does not interface with the AO Supervisor.
std::ostringstream logss
Conveninence string stream for building log messages.
void * statusboard_shmemptr
The pointer to the shared memory block for the statusboard.
virtual void error_report(int LogLevel, std::string emsg)
Report an error. Also calls log_msg.
virtual int update_statusboard()
Update the status board.
virtual int setup_baseApp(bool usethreads=false)
Install fifo channels.
fifo_channel * fifo_ch
An array of fifo_channels.
Definition: fifoutils.h:207
int setup_fifo_list(int nfifos)
Allocate the fifo_list.
virtual std::string local_command(std::string com)
Overridden from VisAOApp_base::local_command, here just calls common_command.
pthread_t signal_thread
Identifier for the separate signal handling thread.
key_t statusboard_shmemkey
The key used to lookup the shared memory.
virtual int block_sigio()
Sets the signal mask to block SIGIO and RTSIGIO.
int TimeToDie
Global set by SIGTERM.
int attach_shm(key_t mkey)
Attachess the shared memory. A Reader process should start here.
fifo_list fl
The list of named-pipe fifos used for inter-process comms.
double pause_time
Time to pause during application main loop.
Definition: VisAOApp_base.h:84
sharedim< IMDATA_TYPE > get_image(int imno)
Gets an image, as a sharedim structure, with the imdata pointer properly set for the calling process...
virtual std::string remote_command(std::string com)
Overridden from VisAOApp_base::remote_command, here just calls common_command.
int create_statusboard(size_t sz)
Creates and attaches to the statusboard shared memory.
static int control_mode
The current control mode.
virtual int install_sig_mainthread_catcher()
Install the SIG_MAINTHREAD signal catcher.
std::string auto_command(std::string com, char *seqmsg)
Overridden from VisAOApp_base::auto_command, here just calls common_command.
virtual int kill_me()
Handle a timetodie condition upon exiting the signal catcher thread (e.g. tell main thread it is abou...
sharedim_stack< float > * sis
Manages a VisAO shared memory image stack.
Definition: frameselector.h:37
sharedim< float > sim
The sharedim structure retreived from the stack.
Definition: frameselector.h:43
The namespace of VisAO software.
virtual std::string post_auto_command(std::string com, char *seqmsg=0)
Processing for auto commands - not normally overriden.
int get_last_image()
Returns the value of last_image currently in the header.
Declarations for the real time frame selector.
#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.