00001 /*!@file Beobot/BeobotLauncher.C File template for developing a new class */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003 // 00005 // by the University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Beobot/BeobotLauncher.C $ 00035 // $Id: BeobotLauncher.C 13712 2010-07-28 21:00:40Z itti $ 00036 // 00037 00038 #include "Component/ModelManager.H" 00039 #include "Devices/BeoChip.H" 00040 00041 #include <fcntl.h> 00042 #include <stdio.h> 00043 #include <sys/stat.h> 00044 #include <sys/types.h> 00045 #include <unistd.h> 00046 00047 //! Description of applications which we handle: 00048 struct BeobotLauncherApp { 00049 char *descrip1, *descrip2; // 20-char max each (one LCD line) 00050 char *name; // name to display at launch 00051 char *cmd; // command to run 00052 }; 00053 00054 //! List of applications which we handle 00055 BeobotLauncherApp apps[100]; 00056 int napps = 0; 00057 00058 //! Our own little BeoChipListener 00059 class BeobotLauncherListener : public BeoChipListener 00060 { 00061 public: 00062 BeobotLauncherListener(nub::soft_ref<BeoChip> beoc) : 00063 keepgoing(true), action(-1), idx(0), beochip(beoc) { } 00064 00065 virtual ~BeobotLauncherListener() { } 00066 00067 virtual void event(const BeoChipEventType t, const int valint, 00068 const float valfloat) 00069 { 00070 if (t == KBD) 00071 { 00072 if ((valint & 0x1) == 0 && idx > 0) // leftmost key pressed 00073 display(--idx); 00074 if ((valint & 0x10) == 0 && idx < napps-1) // rtmost key pressed 00075 display(++idx); 00076 if ((valint & 0x4) == 0) { // middle key pressed 00077 LINFO("Launching: %s", apps[idx].cmd); 00078 // Tell user about what we are launching: 00079 beochip->lcdClear(); 00080 beochip->lcdPrintf(0, 0, " Launching: "); 00081 beochip->lcdPrintf(0, 2, "%s", apps[idx].name); 00082 usleep(800000); 00083 action = idx; // main program will take it from here 00084 } 00085 } 00086 } 00087 00088 virtual void display(const int i) 00089 { 00090 beochip->lcdPrintf(0, 1, "%s", apps[i].descrip1); 00091 beochip->lcdPrintf(0, 2, "%s", apps[i].descrip2); 00092 beochip->lcdPrintf(0, 3, "%s Start! %s", 00093 i > 0 ? "<<<<" : " ", 00094 i < napps-1 ? ">>>>" : " "); 00095 } 00096 00097 volatile bool keepgoing; 00098 volatile int action; 00099 volatile int idx; 00100 nub::soft_ref<BeoChip> beochip; 00101 }; 00102 00103 //! Launch various programs on the Beobot 00104 /*! This launcher should be placed in a cron or init script so that it 00105 will permanently be running. To prevent multiple copies of it from 00106 running at the same time, we use an flock on a file in /tmp, as 00107 suggested on a linuxquestions.org post (so even if the launcher dies 00108 badly, which may leave the temp file behind, it will be unlocked and 00109 will not prevent a new instance from starting). Here we use the 00110 BeoChip to let the user decide what to run. Just before we launch 00111 and monitor a new program, we clear and release the BeoChip so that 00112 the launched program can use it. Once the launched program 00113 terminates, we take the BeoChip over again and show our launch 00114 menu. */ 00115 int main(const int argc, const char **argv) 00116 { 00117 MYLOGVERB = LOG_INFO; 00118 00119 // obtain a lock and check whether other instances of BeobotLauncher 00120 // are running; if so, abort: 00121 int fdlock; struct flock fl; 00122 fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; 00123 fl.l_start = 0; fl.l_len = 1; 00124 00125 if ( (fdlock = open("/tmp/BeobotLauncher.lock", 00126 O_WRONLY | O_CREAT, 0666)) == -1 ) 00127 PLFATAL("Cannot open /tmp/BeobotLauncher.lock"); 00128 if (fcntl(fdlock, F_SETLK, &fl) == -1) 00129 PLFATAL("Cannot lock /tmp/BeobotLauncher.lock"); 00130 00131 // load our config file (list of possible actions): 00132 char buf[1000]; 00133 FILE *f = fopen("/etc/BeobotLauncher.conf", "r"); 00134 if (f == NULL) PLFATAL("Cannot open /etc/BeobotLauncher.conf"); 00135 while(fgets(buf, 999, f)) { 00136 if (buf[0] == '#') continue; 00137 char *data = new char[strlen(buf)+1]; 00138 strcpy(data, buf); 00139 apps[napps].descrip1 = data; data[20] = '\0'; 00140 apps[napps].descrip2 = &data[21]; data[41] = '\0'; 00141 apps[napps].name = &data[42]; data[62] = '\0'; 00142 apps[napps].cmd = &data[63]; 00143 napps ++; 00144 } 00145 fclose(f); 00146 00147 // instantiate a model manager: 00148 ModelManager manager("Beobot Launcher"); 00149 00150 // Instantiate our various ModelComponents: 00151 nub::soft_ref<BeoChip> b(new BeoChip(manager)); 00152 manager.addSubComponent(b); 00153 00154 // Parse command-line: 00155 if (manager.parseCommandLine(argc, argv, "<serdev>", 1, 1) == false) 00156 return(1); 00157 00158 // let's configure our serial device: 00159 b->setModelParamVal("BeoChipDeviceName", manager.getExtraArg(0)); 00160 00161 // let's register our listener: 00162 rutz::shared_ptr<BeobotLauncherListener> lis(new BeobotLauncherListener(b)); 00163 rutz::shared_ptr<BeoChipListener> lis2; lis2.dynCastFrom(lis); // cast down 00164 b->setListener(lis2); 00165 bool blinkon = false; 00166 00167 // let's get all our ModelComponent instances started: 00168 manager.start(); 00169 b->lcdClear(); 00170 b->lcdPrintf(0, 0, "-- BeobotLauncher --"); 00171 b->debounceKeyboard(true); 00172 b->captureKeyboard(true); 00173 lis->display(0); 00174 00175 // main loop: 00176 while(lis->keepgoing) 00177 { 00178 // wait for an action code or a termination condition while we 00179 // blink out tail lights: 00180 while(lis->action == -1 && lis->keepgoing == true) 00181 { 00182 if (blinkon) 00183 { b->setDigitalOut(2, false); b->setDigitalOut(3, false); 00184 blinkon = false; } 00185 else 00186 { b->setDigitalOut(2, true); b->setDigitalOut(3, true); 00187 blinkon = true; } 00188 00189 usleep(250000); 00190 } 00191 00192 // if it's an action, let's execute it: 00193 if (lis->action != -1) 00194 { 00195 // first stop the manager to release the beochip: 00196 b->lcdClear(); 00197 b->setDigitalOut(2, false); b->setDigitalOut(3, false); 00198 manager.stop(); 00199 lis->idx = 0; 00200 00201 // now execute: 00202 if (system(apps[lis->action].cmd)) LERROR("Error in system()"); 00203 00204 // let's get all our ModelComponent instances re-started: 00205 manager.start(); 00206 b->lcdClear(); 00207 b->lcdPrintf(0, 0, " Done with: "); 00208 b->lcdPrintf(0, 2, "%s", apps[lis->action].name); 00209 00210 usleep(800000); 00211 00212 b->lcdClear(); 00213 b->lcdPrintf(0, 0, "-- BeobotLauncher --"); 00214 b->debounceKeyboard(true); 00215 b->captureKeyboard(true); 00216 lis->display(0); 00217 00218 // done with this action: 00219 lis->action = -1; 00220 } 00221 } 00222 00223 // release our lock: 00224 fl.l_type = F_UNLCK; 00225 if (fcntl(fdlock, F_SETLK, &fl) == -1) 00226 PLERROR("Error unlocking /tmp/BeobotLauncher.lock"); 00227 if (close(fdlock) == -1) 00228 PLERROR("Error closing /tmp/BeobotLauncher.lock"); 00229 if (unlink("/tmp/BeobotLauncher.lock") == -1) 00230 PLERROR("Error deleting /tmp/BeobotLauncher.lock"); 00231 return 0; 00232 } 00233 00234 // ###################################################################### 00235 /* So things look consistent in everyone's emacs... */ 00236 /* Local Variables: */ 00237 /* indent-tabs-mode: nil */ 00238 /* End: */