MOOS 0.2375
|
00001 00002 // 00003 // MOOS - Mission Oriented Operating Suite 00004 // 00005 // A suit of Applications and Libraries for Mobile Robotics Research 00006 // Copyright (C) 2001-2005 Massachusetts Institute of Technology and 00007 // Oxford University. 00008 // 00009 // This software was written by Paul Newman and others 00010 // at MIT 2001-2002 and Oxford University 2003-2005. 00011 // email: pnewman@robots.ox.ac.uk. 00012 // 00013 // This file is part of a MOOS Instrument. 00014 // 00015 // This program is free software; you can redistribute it and/or 00016 // modify it under the terms of the GNU General Public License as 00017 // published by the Free Software Foundation; either version 2 of the 00018 // License, or (at your option) any later version. 00019 // 00020 // This program is distributed in the hope that it will be useful, 00021 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00023 // General Public License for more details. 00024 // 00025 // You should have received a copy of the GNU General Public License 00026 // along with this program; if not, write to the Free Software 00027 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 00028 // 02111-1307, USA. 00029 // 00031 // RelayBoard.cpp: implementation of the CRelayBoard class. 00032 // 00034 #include <MOOSLIB/MOOSLib.h> 00035 #include <iostream> 00036 using namespace std; 00037 00038 #include "RelayBoard.h" 00039 00041 // Construction/Destruction 00043 00044 CRelayBoard::CRelayBoard() 00045 { 00046 //some sensible defaults (missionfile can overwrite this) 00047 SetAppFreq(1); 00048 SetCommsFreq(5); 00049 00050 //state strings 00051 m_sRECORDING = "RECORDING"; 00052 m_sSTOPPED = "STOPPED"; 00053 m_sRECORD = "RECORD"; 00054 m_sSTOP = "STOP"; 00055 m_sLIGHT = "LIGHT"; 00056 m_sDARK = "DARK"; 00057 m_sON = "ON"; 00058 m_sOFF = "OFF"; 00059 m_sVCR_POWER = "VCR_POWER"; 00060 m_sCAMERA_POWER = "CAMERA_POWER"; 00061 m_sBOARD_POWER = "BOARD_POWER"; 00062 m_sLIGHT_POWER = "LIGHT_POWER"; 00063 00064 m_RelayToggleMap[m_sCAMERA_POWER] = RELAY0_TOGGLE; 00065 m_RelayToggleMap[m_sVCR_POWER] = RELAY1_TOGGLE; 00066 m_RelayToggleMap[m_sLIGHT_POWER] = RELAY2_TOGGLE; 00067 m_RelayToggleMap[m_sRECORD] = RELAY3_TOGGLE; 00068 m_RelayToggleMap[m_sBOARD_POWER] = RELAY7_TOGGLE; 00069 00070 m_RelayCheckMap[m_sCAMERA_POWER] = RELAY0; 00071 m_RelayCheckMap[m_sVCR_POWER] = RELAY1; 00072 m_RelayCheckMap[m_sLIGHT_POWER] = RELAY2; 00073 m_RelayCheckMap[m_sRECORD] = RELAY3; 00074 m_RelayCheckMap[m_sBOARD_POWER] = RELAY7; 00075 00076 m_InputNameMap[m_sRECORDING] = INPUT3; 00077 } 00078 00079 CRelayBoard::~CRelayBoard() 00080 { 00081 Stop(); 00082 ToggleRelaySwitch(m_sLIGHT_POWER, m_sOFF); 00083 00084 } 00085 00086 00089 bool CRelayBoard::Iterate() 00090 { 00091 00092 if(GetData()) 00093 { 00094 PublishData(); 00095 } 00096 00097 return true; 00098 } 00099 00100 00101 bool CRelayBoard::OnStartUp() 00102 { 00103 CMOOSInstrument::OnStartUp(); 00104 //here we make the variables that we are managing 00105 double dfRelayPeriod = 1.0; 00106 00107 //Register for the variable that will provide for dynamic configuration 00108 //of the Relay board 00109 //This version of the iRelay only corresponds to the Video System 00110 //the video system states 00111 AddMOOSVariable("VIDEO_STATUS", "RELAY_VIDEO_UPDATE", "RELAY_VIDEO_REPLY", dfRelayPeriod); 00112 AddMOOSVariable("RELAY_STATUS", "RELAY_UPDATE", "RELAY_UPDATE_REPLY",dfRelayPeriod); 00113 00114 00115 RegisterMOOSVariables(); 00116 00117 if(IsSimulateMode()) 00118 { 00119 SetAppFreq(2); 00120 SetCommsFreq(2); 00121 } 00122 else 00123 { 00124 //try to open 00125 if(!SetupPort()) 00126 { 00127 return false; 00128 } 00129 00130 //try 10 times to initialise sensor 00131 if(!InitialiseSensorN(10,"RELAY")) 00132 { 00133 return false; 00134 } 00135 00136 } 00137 return true; 00138 } 00139 00140 00141 00142 bool CRelayBoard::OnNewMail(MOOSMSG_LIST &NewMail) 00143 { 00144 CMOOSMsg Msg; 00145 double dfTimeNow = MOOSTime(); 00146 string sVal; 00147 00148 if(m_Comms.PeekMail(NewMail,"RELAY_VIDEO_UPDATE",Msg)) 00149 { 00150 sVal = Msg.m_sVal; 00151 MOOSTrace("..............new : %s\n", sVal.c_str()); 00152 if(sVal == m_sRECORD) 00153 return Record(); 00154 else if(sVal == m_sSTOP) 00155 return Stop(); 00156 else if(sVal == m_sLIGHT) 00157 return ToggleRelaySwitch(m_sLIGHT_POWER, m_sON); 00158 else if(sVal == m_sDARK) 00159 return ToggleRelaySwitch(m_sLIGHT_POWER, m_sOFF); 00160 else 00161 return true; 00162 } 00163 else if(m_Comms.PeekMail(NewMail,"RELAY_UPDATE",Msg)) 00164 { 00165 return UpdateRelay(Msg); 00166 } 00167 00168 else 00169 { 00170 return UpdateMOOSVariables(NewMail); 00171 } 00172 } 00173 00174 bool CRelayBoard::PublishData() 00175 { 00176 return PublishFreshMOOSVariables(); 00177 } 00178 00179 00180 00181 bool CRelayBoard::OnConnectToServer() 00182 { 00183 if(IsSimulateMode()) 00184 { 00185 RegisterMOOSVariables(); 00186 } 00187 return true; 00188 } 00189 00190 00192 // here we initialise the sensor, giving it start up values 00193 bool CRelayBoard::InitialiseSensor() 00194 { 00195 return ToggleRelaySwitch(m_sBOARD_POWER, m_sON); 00196 } 00197 00198 00199 00200 bool CRelayBoard::GetData() 00201 { 00202 if(!IsSimulateMode()) 00203 { 00204 // string sStatus; 00205 //we will publish the state of the relays 00206 // RELAY_FUNCTION_2_CHECK_MAP::iterator p; 00207 //for(p = m_RelayCheckMap.begin(); p != m_RelayCheckMap.end(); p++) 00208 //{ 00209 // string sRelay = p->first.c_str(); 00210 // sStatus += sRelay + (IsPowered(sRelay) ? ": true " : ": false "); 00211 //} 00212 //alert the DB 00213 //SetMOOSVar("RELAY_STATUS", sStatus, MOOSTime()); 00214 00215 } 00216 else 00217 { 00218 //in simulated mode there is nothing to do..all data 00219 //arrives via comms. 00220 } 00221 00222 return true; 00223 00224 } 00225 00226 bool CRelayBoard::SetRelayHi(short val) 00227 { 00228 string sRelay = "MK"; 00229 short MASK; 00230 char pChar[4]; 00231 00232 //should check the range of val 00233 if(val>255 || val < 0) 00234 { 00235 MOOSTrace("Acceptable Relay range 0-255\n"); 00236 return false; 00237 } 00238 else 00239 { 00240 //we need to make a mask out of what the state of the RelayBoard 00241 //already is so that we do not shut off relays in the process of 00242 //trying to turn only a specific one on 00243 short nState = (short)CheckAllRelayStates(); 00244 MASK = nState | val; 00245 00246 //make note of this value we are writing 00247 sprintf(pChar, "%d\r", MASK); 00248 //The format for setting the relay is MKddd 00249 //where 'ddd' corresponds to the 3 characters in a 0-255 value short 00250 sRelay += pChar; 00251 //write the new command 00252 m_Port.Write((char *)sRelay.c_str(), sRelay.size()); 00253 } 00254 00255 00256 return true; 00257 } 00258 00264 int CRelayBoard::CheckRelayState(short val) 00265 { 00266 string sRelay = "RPK"; 00267 string sReply; 00268 double dfWhen = 0.5; 00269 char pChar[4]; 00270 00271 //should check the range of val 00272 if(val > 7 || val < 0) 00273 { 00274 MOOSTrace("Acceptable Relay range 0-7\n"); 00275 return -1; 00276 } 00277 else 00278 { 00279 //make note of this value we are writing 00280 sprintf(pChar,"%d\r",val); 00281 //The format for setting the relay is MKddd 00282 //where 'ddd' corresponds to the 3 characters in a 0-255 value short 00283 sRelay += pChar; 00284 //write the new command 00285 m_Port.Write((char *)sRelay.c_str(), sRelay.size()); 00286 00287 while(!m_Port.GetTelegram(sReply,dfWhen)) 00288 { 00289 MOOSPause(10); 00290 } 00291 00292 short nRet = (short)atof(sReply.c_str()); 00293 00294 if(m_Port.IsVerbose()) 00295 { 00296 MOOSTrace("checked: %d and found its state to be: %d\n", val, nRet); 00297 } 00298 00299 return nRet; 00300 } 00301 00302 } 00303 00306 int CRelayBoard::CheckInputState(short val) 00307 { 00308 string sRelay = "RPA"; 00309 string sReply; 00310 double dfWhen = 0.5; 00311 char pChar[4]; 00312 00313 //should check the range of val 00314 if(val > 3 || val < 0) 00315 { 00316 MOOSTrace("Acceptable Input range 0-3\n"); 00317 return -1; 00318 } 00319 else 00320 { 00321 //the relay needs 0.5 seconds to make the state change 00322 MOOSPause(5000); 00323 //make note of this value we are writing 00324 sprintf(pChar,"%d\r",val); 00325 sRelay += pChar; 00326 //write the new command 00327 m_Port.Write((char *)sRelay.c_str(), sRelay.size()); 00328 00329 while(!m_Port.GetTelegram(sReply,dfWhen)) 00330 { 00331 MOOSPause(10); 00332 } 00333 00334 short nRet = (short)atof(sReply.c_str()); 00335 00336 if(m_Port.IsVerbose()) 00337 { 00338 MOOSTrace("checked input: %d and found its state to be: %d\n", val, nRet); 00339 } 00340 00341 return nRet; 00342 } 00343 00344 } 00345 00347 bool CRelayBoard::Record() 00348 { 00349 int nInputToMonitor = -1; 00350 00351 INPUT_NAME_2_INT_MAP::iterator p = m_InputNameMap.find(m_sRECORDING); 00352 if(p != m_InputNameMap.end()) 00353 { 00354 nInputToMonitor = p->second; 00355 MOOSTrace("[REC]Looking for %d\n", nInputToMonitor); 00356 } 00357 else 00358 { 00359 MOOSTrace("You have entered an incorrect Input Name[REC]\n"); 00360 return false; 00361 } 00362 00363 //make sure the relay board has power 00364 //and then turn on the VCR and CAMERA 00365 ToggleRelaySwitch(m_sBOARD_POWER, m_sON); 00366 ToggleRelaySwitch(m_sVCR_POWER, m_sON); 00367 ToggleRelaySwitch(m_sCAMERA_POWER, m_sON); 00368 ToggleRelaySwitch(m_sRECORD, m_sON); 00369 00370 if(CheckInputState(nInputToMonitor) == LO) 00371 { 00372 SetMOOSVar("VIDEO_STATUS", m_sRECORDING,MOOSTime()); 00373 return true; 00374 } 00375 else 00376 { 00377 string sProblem = m_sRECORDING + ": FAILED"; 00378 SetMOOSVar("VIDEO_STATUS", sProblem,MOOSTime()); 00379 return false; 00380 } 00381 } 00382 00383 bool CRelayBoard::Stop() 00384 { 00385 int nInputToMonitor = -1; 00386 00387 INPUT_NAME_2_INT_MAP::iterator p = m_InputNameMap.find(m_sRECORDING); 00388 if(p != m_InputNameMap.end()) 00389 { 00390 nInputToMonitor = p->second; 00391 MOOSTrace("[STOP]Looking for %d\n", nInputToMonitor); 00392 } 00393 else 00394 { 00395 MOOSTrace("You have entered an incorrect Input Name[STOP]\n"); 00396 return false; 00397 } 00398 00399 ToggleRelaySwitch(m_sRECORD, m_sOFF); 00400 ToggleRelaySwitch(m_sCAMERA_POWER, m_sOFF); 00401 ToggleRelaySwitch(m_sVCR_POWER, m_sOFF); 00402 00403 if(CheckInputState(nInputToMonitor) == HI) 00404 { 00405 SetMOOSVar("VIDEO_STATUS", m_sSTOPPED, MOOSTime()); 00406 return true; 00407 } 00408 else 00409 { 00410 string sProblem = m_sSTOPPED + ": FAILED"; 00411 SetMOOSVar("VIDEO_STATUS", sProblem,MOOSTime()); 00412 return false; 00413 } 00414 00415 } 00416 00417 00418 bool CRelayBoard::UpdateRelay(CMOOSMsg &Msg) 00419 { 00420 string sNewRelayStates = Msg.m_sVal; 00421 string sMOOSChompResult = MOOSChomp(sNewRelayStates, ","); 00422 string sStatus; 00423 00424 while(!sMOOSChompResult.empty()) 00425 { 00426 string sRelay = MOOSChomp(sMOOSChompResult,":"); 00427 string sState = sMOOSChompResult; 00428 if(ToggleRelaySwitch(sRelay,sState)) 00429 { 00430 sStatus += sRelay + ": OK "; 00431 } 00432 else 00433 { 00434 sStatus += sRelay + ": FAIL "; 00435 } 00436 MOOSTrace("sRelay: %s sState: %s",sRelay.c_str(),sState.c_str()); 00437 00438 sMOOSChompResult = MOOSChomp(sNewRelayStates, ","); 00439 } 00440 00441 //SetMOOSVar("RELAY_STATUS", sStatus, MOOSTime()); 00442 MOOSTrace("sStatus: %s ", sStatus.c_str()); 00443 return true; 00444 00445 } 00446 00447 00451 bool CRelayBoard::ToggleRelaySwitch(string sRelay, string sDesiredState) 00452 { 00453 int nRelayToSwitch = -1; 00454 //we know we are talking to the relay board's power switch 00455 RELAY_FUNCTION_2_TOGGLE_MAP::iterator p = m_RelayToggleMap.find(sRelay); 00456 if(p != m_RelayToggleMap.end()) 00457 { 00458 nRelayToSwitch = p->second; 00459 MOOSTrace("[TBP]Toggling %d\n", nRelayToSwitch); 00460 } 00461 else 00462 { 00463 MOOSTrace("You have entered an incorrect Relay Name[TBP]\n"); 00464 return false; 00465 } 00466 00467 if(sDesiredState == m_sON) 00468 { 00469 if(!IsPowered(sRelay)) 00470 { 00471 SetRelayHi(nRelayToSwitch); 00472 } 00473 } 00474 else if(sDesiredState == m_sOFF) 00475 { 00476 if(IsPowered(sRelay)) 00477 { 00478 SetRelayLo(nRelayToSwitch); 00479 } 00480 00481 } 00482 00483 return ShowRelayBoardStatus(); 00484 } 00485 00489 bool CRelayBoard::IsPowered(string sRelay) 00490 { 00491 //figure out what relay we are trying to query 00492 int nRelayToCheck = -1; 00493 RELAY_FUNCTION_2_CHECK_MAP::iterator p = m_RelayCheckMap.find(sRelay); 00494 00495 if(p != m_RelayCheckMap.end()) 00496 { 00497 nRelayToCheck = p->second; 00498 00499 if(m_Port.IsVerbose()) 00500 { 00501 MOOSTrace("[IP]checking relay: %d\n", nRelayToCheck); 00502 } 00503 00504 } 00505 00506 00507 return (CheckRelayState(nRelayToCheck) == HI); 00508 } 00509 00510 bool CRelayBoard::SetRelayLo(short val) 00511 { 00512 string sRelay = "MK"; 00513 short MASK; 00514 char pChar[4]; 00515 00516 //should check the range of val 00517 if(val>255 || val < 0) 00518 { 00519 MOOSTrace("Acceptable Relay range 0-255\n"); 00520 return false; 00521 } 00522 else 00523 { 00524 //we need to make a mask out of what the state of the RelayBoard 00525 //already is so that we do not shut off relays in the process of 00526 //trying to turn only a specific one off 00527 short nState = (short)CheckAllRelayStates(); 00528 MASK = nState & ~val; 00529 00530 //make note of this value we are writing 00531 sprintf(pChar, "%d\r", MASK); 00532 //The format for setting the relay is MKddd 00533 //where 'ddd' corresponds to the 3 characters in a 0-255 value short 00534 sRelay += pChar; 00535 //write the new command 00536 m_Port.Write((char *)sRelay.c_str(), sRelay.size()); 00537 } 00538 00539 00540 return true; 00541 00542 } 00543 00546 int CRelayBoard::CheckAllRelayStates() 00547 { 00548 string sRelay = "PK\r"; 00549 string sReply; 00550 double dfWhen = 1.0; 00551 00552 //write the status command 00553 00554 m_Port.Write((char *)sRelay.c_str(), sRelay.size()); 00555 00556 while(!m_Port.GetTelegram(sReply,dfWhen)) 00557 { 00558 MOOSPause(10); 00559 } 00560 00561 short nRet = (short)atof(sReply.c_str()); 00562 00563 if(m_Port.IsVerbose()) 00564 { 00565 MOOSTrace("status of ALL relays: %d\n", nRet); 00566 } 00567 00568 return nRet; 00569 00570 } 00571 00572 bool CRelayBoard::ShowRelayBoardStatus() 00573 { 00574 00575 string sStatus; 00576 //we will publish the state of the relays 00577 RELAY_FUNCTION_2_CHECK_MAP::iterator p; 00578 for(p = m_RelayCheckMap.begin(); p != m_RelayCheckMap.end(); p++) 00579 { 00580 string sRelay = p->first.c_str(); 00581 sStatus += sRelay + (IsPowered(sRelay) ? ": ON " : ": OFF "); 00582 } 00583 //alert the DB 00584 SetMOOSVar("RELAY_STATUS", sStatus, MOOSTime()); 00585 00586 return true; 00587 }