00001 // File: HawkFreezer.C 00002 // Author: Josh Villbrandt <josh.villbrandt@usc.edu> 00003 // Date: April 2010 00004 00005 #include "Robots/BeoHawk/computer/HawkFreezer.H" 00006 00007 // ###################################################################### 00008 HawkFreezer::HawkFreezer(std::string myName, int argc, char* argv[]) 00009 : HawkAgent(myName, argc, argv) { 00010 // Help section 00011 helpTitle = "HawkFreezer"; 00012 helpDescription = "Stores ICE messages for future playback. Also plays them back."; 00013 helpOptions.push_back("\t--mode\t\t(record) Should be 'record' or 'playback'."); 00014 helpOptions.push_back("\t--file\t\t(default.freezer) File to read or write from."); 00015 helpOptions.push_back("\t--duration\t(30) Duration to playback or record ICE messages."); 00016 helpOptions.push_back("\t--frequency\t(0) Maximum messages per second to play or record. Set to 0 to ignore this setting."); 00017 00018 // Parameters 00019 duration = loadDoubleParameter("duration", 30); 00020 frequency = loadDoubleParameter("frequency", 0); 00021 std::string modeString = loadStringParameter("mode", "record"); 00022 file = loadStringParameter("file", "default.freezer"); 00023 timer = Timer(1000000); 00024 00025 // Set skip period 00026 if(frequency == 0) period = 0; 00027 else period = 1/frequency; 00028 lastMessageSeconds = timer.getSecs() - period; 00029 00030 // Set state 00031 if(modeString == "record") { 00032 std::cout << "starting to record to " << file << " for " << duration << " seconds" << std::endl; 00033 state = RECORD; 00034 } 00035 else { 00036 std::cout << "set to playback from " << file << std::endl; 00037 state = LOAD_PLAYBACK; 00038 } 00039 } 00040 00041 // ###################################################################### 00042 void HawkFreezer::registerTopics() { 00043 registerPublisher("SensorDataMessage"); 00044 registerSubscription("SensorDataMessage"); 00045 } 00046 00047 // ###################################################################### 00048 bool HawkFreezer::scheduler() { 00049 if(state == RECORD) { 00050 if(timer.getSecs() < duration) { 00051 usleep(1000000); // this does not respect non-integer durations, who cares 00052 std::cout << "captured " << messages.size() << " messages..." << std::endl; 00053 return true; 00054 } 00055 else { 00056 std::cout << "record duration reached, writing to file..." << std::endl; 00057 saveMessages(); 00058 } 00059 } 00060 else if(state == LOAD_PLAYBACK) { 00061 loadMessages(); 00062 return true; 00063 } 00064 else if(state == PLAYBACK) { 00065 if(messages.size() > 0 && timer.getSecs() < duration) { 00066 std::cout << messages.size() << " messages left to play..." << std::endl; 00067 playNextMessages(); 00068 return true; 00069 } 00070 else { 00071 std::cout << "no more messages to play back (or duration elapsed)..." << std::endl; 00072 } 00073 } 00074 00075 stop(); 00076 return false; 00077 } 00078 00079 // ###################################################################### 00080 void HawkFreezer::catchMessage(const HawkMessages::MessagePtr& hawkMessage, const Ice::Current&) { 00081 if(state == RECORD && hawkMessage->ice_isA("::HawkMessages::SensorDataMessage") && timer.getSecs() > (lastMessageSeconds + period)) 00082 { 00083 // Save message to storage queue 00084 Message msg; 00085 msg.sensorData = HawkMessages::SensorDataMessagePtr::dynamicCast(hawkMessage); 00086 msg.timestamp = timer.getSecs(); 00087 messages.push_back(msg); 00088 00089 // Reset 00090 lastMessageSeconds = timer.getSecs(); 00091 } 00092 } 00093 00094 // ###################################################################### 00095 void HawkFreezer::playNextMessages() { 00096 // Play messages 00097 while(messages.size() > 0 && messages.front().timestamp <= timer.getSecs()) { 00098 publish("SensorDataMessage", messages.front().sensorData); 00099 lastMessageSeconds = messages.front().timestamp; 00100 messages.erase(messages.begin()); 00101 } 00102 00103 // Delete future skipped messages 00104 while(messages.size() > 0 && messages.front().timestamp < (lastMessageSeconds+period)) { 00105 messages.erase(messages.begin()); 00106 } 00107 00108 // Sleep until next message 00109 if(messages.size() > 0) 00110 usleep((int)((messages.front().timestamp - timer.getSecs())*1000000)); 00111 } 00112 00113 // ###################################################################### 00114 void HawkFreezer::loadMessages() { 00115 std::ifstream fileStream; 00116 fileStream.open(file.c_str()); 00117 if(fileStream) { 00118 // Load number of messages 00119 int numberOfMessages; 00120 fileStream >> numberOfMessages; 00121 00122 // Load each message 00123 for(int i = 0; i < numberOfMessages; i++) { 00124 Message msg; 00125 00126 // Timestamp 00127 fileStream >> msg.timestamp; 00128 00129 // Attempted move 00130 HawkMessages::Pose attemptedMove; 00131 fileStream >> attemptedMove.x; 00132 fileStream >> attemptedMove.y; 00133 fileStream >> attemptedMove.z; 00134 fileStream >> attemptedMove.theta; 00135 00136 // Scanner data 00137 double angularResolution; 00138 fileStream >> angularResolution; 00139 int scannerDataSize; 00140 fileStream >> scannerDataSize; 00141 HawkMessages::LongSeq scannerData; 00142 long temp; 00143 for(int j = 0; j < scannerDataSize; j++) { 00144 fileStream >> temp; 00145 scannerData.push_back(temp); 00146 } 00147 00148 // Add to message vector 00149 msg.sensorData = new HawkMessages::SensorDataMessage; 00150 msg.sensorData->attemptedMove = attemptedMove; 00151 msg.sensorData->angularResolution = angularResolution; 00152 msg.sensorData->scannerData = scannerData; 00153 messages.push_back(msg); 00154 } 00155 00156 std::cout << "playback file loaded, now starting playback..." << std::endl; 00157 state = PLAYBACK; 00158 } 00159 else { 00160 std::cout << "Error: file could not be opened." << std::endl; 00161 state = INIT_FAIL; 00162 } 00163 fileStream.close(); 00164 } 00165 00166 // ###################################################################### 00167 void HawkFreezer::saveMessages() { 00168 std::ofstream fileStream; 00169 fileStream.open(file.c_str()); 00170 if(fileStream) { 00171 // Write number of messages 00172 fileStream << messages.size() << std::endl; 00173 00174 // Write each message 00175 for(int i = 0; i < (int)messages.size(); i++) { 00176 // Timestamp 00177 fileStream << messages[i].timestamp << std::endl; 00178 00179 // Attempted move 00180 fileStream << messages[i].sensorData->attemptedMove.x << " "; 00181 fileStream << messages[i].sensorData->attemptedMove.y << " "; 00182 fileStream << messages[i].sensorData->attemptedMove.z << " "; 00183 fileStream << messages[i].sensorData->attemptedMove.theta << std::endl; 00184 00185 // Scanner data 00186 fileStream << messages[i].sensorData->angularResolution << " "; 00187 fileStream << messages[i].sensorData->scannerData.size(); 00188 for(int j = 0; j < (int)messages[i].sensorData->scannerData.size(); j++) { 00189 fileStream << " " << messages[i].sensorData->scannerData[j]; 00190 } 00191 fileStream << std::endl; 00192 } 00193 } 00194 else { 00195 std::cout << "Error: file could not be opened. That sucks." << std::endl; 00196 } 00197 fileStream.close(); 00198 } 00199 00200 // ###################################################################### 00201 int main (int argc, char* argv[]) { 00202 std::cout << "HawkFreezer: starting..." << std::endl; 00203 00204 HawkFreezer agent("HawkFreezer", argc, argv); 00205 agent.start(); 00206 00207 std::cout << "HawkFreezer: all done!" << std::endl; 00208 }