00001 #include <iostream> 00002 00003 #include "Learn/WiimoteGR/Database.h" 00004 #include "Learn/WiimoteGR/TimeSlot.h" 00005 #include "Learn/WiimoteGR/Quantizer.h" 00006 #include "Learn/WiimoteGR/HMMLib.h" 00007 00008 namespace WiimoteGR{ 00009 00010 /* a trick to ensure Database will be closed and deleted on program termination */ 00011 class DBCloser{ 00012 public: 00013 ~DBCloser(){ 00014 Database::Close(); 00015 } 00016 } DBCloserInstance; 00017 00018 Database* Database::dbInstance = 0; 00019 00020 Database& Database::Open() 00021 { 00022 if(dbInstance == 0){ 00023 dbInstance = new Database; 00024 } 00025 return *dbInstance; 00026 } 00027 00028 void Database::Close() 00029 { 00030 if(dbInstance!=0){ 00031 sqlite3_close(dbInstance->db); 00032 delete dbInstance; 00033 dbInstance = 0; 00034 } 00035 } 00036 00037 /* 00038 main functions 00039 */ 00040 void Database::SaveGesture(const Gesture& gesture) 00041 { 00042 //binding values 00043 rc = sqlite3_bind_text(saveGestureStmt,1, gesture.gestureName.c_str(), gesture.gestureName.size(), SQLITE_TRANSIENT); 00044 if(rc!=SQLITE_OK) std::cout << "Error when binding gestureName in SaveGesture()" << std::endl << sqlite3_errmsg(db) << std::endl; 00045 rc = sqlite3_bind_int(saveGestureStmt,2, gesture.data.size()); 00046 if(rc!=SQLITE_OK) std::cout << "Error when binding data in SaveGesture()" << std::endl << sqlite3_errmsg(db) << std::endl; 00047 rc = sqlite3_bind_blob(saveGestureStmt,3, &(gesture.data[0]), sizeof(Acceleration)*gesture.data.size(), SQLITE_TRANSIENT); 00048 if(rc!=SQLITE_OK) std::cout << "Error when binding data in SaveGesture()" << std::endl << sqlite3_errmsg(db) << std::endl; 00049 00050 //evaluating 00051 rc = sqlite3_step(saveGestureStmt); 00052 if(rc!=SQLITE_DONE) std::cout << "Error when evaluating in SaveGesture()" << std::endl << sqlite3_errmsg(db) << std::endl; 00053 00054 //reset statement for next evaluation 00055 sqlite3_reset(saveGestureStmt); 00056 sqlite3_clear_bindings(saveGestureStmt); 00057 } 00058 00059 void Database::SaveObservationSequence(const TimeSlot& seq) 00060 { 00061 //binding values 00062 rc = sqlite3_bind_text(saveObservationSequenceStmt, 1, seq.gestureName.c_str(), seq.gestureName.size(), SQLITE_TRANSIENT); 00063 if(rc!=SQLITE_OK) std::cout << "Error when binding gestureName in SaveObservationSequence()" << std::endl; 00064 rc = sqlite3_bind_text(saveObservationSequenceStmt, 2, seq.quantizerName.c_str(), seq.quantizerName.size(), SQLITE_TRANSIENT); 00065 if(rc!=SQLITE_OK) std::cout << "Error when binding quantizerName in SaveObservationSequence()" << std::endl; 00066 rc = sqlite3_bind_int(saveObservationSequenceStmt, 3, seq.o.size()); 00067 if(rc!=SQLITE_OK) std::cout << "Error when binding o in SaveObservationSequence()" << std::endl; 00068 rc = sqlite3_bind_blob(saveObservationSequenceStmt, 4, &(seq.o[0]), sizeof(size_t)*seq.o.size(), SQLITE_TRANSIENT); 00069 if(rc!=SQLITE_OK) std::cout << "Error when binding o in SaveObservationSequence()" << std::endl; 00070 00071 //evaluating 00072 rc = sqlite3_step(saveObservationSequenceStmt); 00073 if(rc!=SQLITE_DONE) std::cout << "Error when evaluating in SaveObservationSequence()" << std::endl; 00074 00075 //reset statement for next evaluation 00076 sqlite3_reset(saveObservationSequenceStmt); 00077 sqlite3_clear_bindings(saveObservationSequenceStmt); 00078 } 00079 00080 void Database::SaveHMM(const HMM& hmm) 00081 { 00082 /* testing existence*/ 00083 //binding values 00084 rc = sqlite3_bind_text(isExistHMMStmt, 1, hmm.gestureName.c_str(), hmm.gestureName.size(), SQLITE_TRANSIENT); 00085 if(rc!=SQLITE_OK) std::cout << "Error when binding gestureName in SaveHMM() for test existence" << std::endl; 00086 rc = sqlite3_bind_text(isExistHMMStmt, 2, hmm.quantizerName.c_str(), hmm.quantizerName.size(), SQLITE_TRANSIENT); 00087 if(rc!=SQLITE_OK) std::cout << "Error when binding quantizerName in SaveHMM() for test existence" << std::endl; 00088 rc = sqlite3_bind_text(isExistHMMStmt, 3, hmm.modelStyle.c_str(), hmm.modelStyle.size(), SQLITE_TRANSIENT); 00089 if(rc!=SQLITE_OK) std::cout << "Error when binding modelStyle in SaveHMM() for test existence" << std::endl; 00090 rc = sqlite3_bind_int(isExistHMMStmt, 4, hmm.trained); 00091 if(rc!=SQLITE_OK) std::cout << "Error when binding trained in SaveHMM() for test existence" << std::endl; 00092 00093 sqlite3_stmt* chosenStmt = 0; 00094 00095 //evaluating 00096 rc = sqlite3_step(isExistHMMStmt); 00097 if(rc==SQLITE_DONE){ 00098 //not exist, insert 00099 chosenStmt = insertHMMStmt; 00100 }else if(rc==SQLITE_ROW){ 00101 //exist, update 00102 chosenStmt = updateHMMStmt; 00103 }else{ 00104 std::cout << "Error when evaluating in SaveHMM() for test existence" << std::endl; 00105 } 00106 //reset 00107 sqlite3_reset(isExistHMMStmt); 00108 sqlite3_clear_bindings(isExistHMMStmt); 00109 00110 00111 /* INSERT or UPDATE */ 00112 if(chosenStmt != 0){ 00113 //binding values 00114 rc = sqlite3_bind_text(chosenStmt, 1, hmm.gestureName.c_str(), hmm.gestureName.size(), SQLITE_TRANSIENT); 00115 if(rc!=SQLITE_OK) std::cout << "Error when binding gestureName in SaveHMM()" << std::endl; 00116 rc = sqlite3_bind_text(chosenStmt, 2, hmm.quantizerName.c_str(), hmm.quantizerName.size(), SQLITE_TRANSIENT); 00117 if(rc!=SQLITE_OK) std::cout << "Error when binding quantizerName in SaveHMM()" << std::endl; 00118 rc = sqlite3_bind_text(chosenStmt, 3, hmm.modelStyle.c_str(), hmm.modelStyle.size(), SQLITE_TRANSIENT); 00119 if(rc!=SQLITE_OK) std::cout << "Error when binding modelStyle in SaveHMM()" << std::endl; 00120 rc = sqlite3_bind_int(chosenStmt, 4, hmm.trained); 00121 if(rc!=SQLITE_OK) std::cout << "Error when binding trained in SaveHMM()" << std::endl; 00122 rc = sqlite3_bind_int(chosenStmt, 5, hmm.N); 00123 if(rc!=SQLITE_OK) std::cout << "Error when binding N in SaveHMM()" << std::endl; 00124 rc = sqlite3_bind_int(chosenStmt, 6, hmm.M); 00125 if(rc!=SQLITE_OK) std::cout << "Error when binding M in SaveHMM()" << std::endl; 00126 rc = sqlite3_bind_blob(chosenStmt, 7, &(hmm.pi[0]), sizeof(double)*hmm.pi.size(), SQLITE_TRANSIENT); 00127 if(rc!=SQLITE_OK) std::cout << "Error when binding pi in SaveHMM()" << std::endl; 00128 rc = sqlite3_bind_blob(chosenStmt, 8, &(hmm.A[0]), sizeof(double)*hmm.A.size(), SQLITE_TRANSIENT); 00129 if(rc!=SQLITE_OK) std::cout << "Error when binding A in SaveHMM()" << std::endl; 00130 rc = sqlite3_bind_blob(chosenStmt, 9, &(hmm.B[0]), sizeof(double)*hmm.B.size(), SQLITE_TRANSIENT); 00131 if(rc!=SQLITE_OK) std::cout << "Error when binding B in SaveHMM()" << std::endl; 00132 00133 //evaluating 00134 rc = sqlite3_step(chosenStmt); 00135 if(rc!=SQLITE_DONE) std::cout << "Error when evaluating in SaveHMM()" << std::endl; 00136 00137 //reset statement for next evaluation 00138 sqlite3_reset(chosenStmt); 00139 sqlite3_clear_bindings(chosenStmt); 00140 } 00141 } 00142 00143 void Database::LoadGestures(const char* gestureName, vector<Gesture>& gestureVec) 00144 { 00145 gestureVec.reserve(gestureVecSpace); 00146 //SQL: "SELECT dataLength data FROM GestureTable WHERE gestureName==?1;" 00147 rc = sqlite3_bind_text(loadGesturesStmt, 1, gestureName, -1, SQLITE_TRANSIENT); 00148 if(rc!=SQLITE_OK) std::cout << "Error when binding gestureName in LoadGestures()" << std::endl; 00149 00150 Gesture tempGesture(gestureName); 00151 size_t dataLength; 00152 const Acceleration* dataPtr = 0; 00153 00154 //evaluation 00155 rc = sqlite3_step(loadGesturesStmt); 00156 while(rc==SQLITE_ROW){ 00157 gestureVec.push_back(tempGesture); 00158 dataLength = sqlite3_column_int(loadGesturesStmt, 0); 00159 dataPtr = (const Acceleration*)sqlite3_column_blob(loadGesturesStmt, 1); 00160 gestureVec.back().data.assign(dataPtr,dataPtr+dataLength); 00161 rc = sqlite3_step(loadGesturesStmt); 00162 } 00163 if(rc!=SQLITE_DONE) std::cout << "Error when evaluation in LoadGestures()" << std::endl; 00164 //reset 00165 sqlite3_reset(loadGesturesStmt); 00166 sqlite3_clear_bindings(loadGesturesStmt); 00167 } 00168 00169 void Database::LoadObservationSequences(const char* gestureName, const Quantizer& quantizer, vector<TimeSlot>& seqVec) 00170 { 00171 seqVec.reserve(seqVecSpace); 00172 //SQL: "SELECT oLength o FROM ObservationSequenceTable WHERE gestureName==?1 AND quantizerName==?2;"; 00173 rc = sqlite3_bind_text(loadObservationSequencesStmt, 1, gestureName, -1, SQLITE_TRANSIENT); 00174 if(rc!=SQLITE_OK) std::cout << "Error when binding gestureName in LoadObservationSequences()" << std::endl; 00175 rc = sqlite3_bind_text(loadObservationSequencesStmt, 2, quantizer.name.c_str(), quantizer.name.size(), SQLITE_TRANSIENT); 00176 if(rc!=SQLITE_OK) std::cout << "Error when binding quantizerName in LoadObservationSequences()" << std::endl; 00177 00178 TimeSlot tempSeq(gestureName,quantizer); 00179 size_t oLength; 00180 const size_t* oPtr = 0; 00181 00182 //evaluation 00183 rc = sqlite3_step(loadObservationSequencesStmt); 00184 while(rc==SQLITE_ROW){ 00185 oLength= sqlite3_column_int(loadObservationSequencesStmt, 0); 00186 oPtr = (const size_t*)sqlite3_column_blob(loadObservationSequencesStmt, 1); 00187 seqVec.push_back(tempSeq); 00188 seqVec.back().o.assign(oPtr,oPtr+oLength); 00189 rc = sqlite3_step(loadObservationSequencesStmt); 00190 } 00191 if(rc!=SQLITE_DONE) std::cout << "Error when evaluation in LoadObservationSequences()" << std::endl; 00192 00193 //reset 00194 sqlite3_reset(loadObservationSequencesStmt); 00195 sqlite3_clear_bindings(loadObservationSequencesStmt); 00196 } 00197 00198 void Database::LoadHMM(HMM& hmm) 00199 { 00200 //SQL: "SELECT N M pi A B FROM HMMTable WHERE gestureName==?1 AND quantizerName==?2 AND modelStyle==?3 AND trained==?4;" 00201 rc = sqlite3_bind_text(loadHMMStmt, 1, hmm.gestureName.c_str(), hmm.gestureName.size(), SQLITE_TRANSIENT); 00202 if(rc!=SQLITE_OK) std::cout << "Error when binding gestureName in LoadHMM()" << std::endl; 00203 rc = sqlite3_bind_text(loadHMMStmt, 2, hmm.quantizerName.c_str(), hmm.quantizerName.size(), SQLITE_TRANSIENT); 00204 if(rc!=SQLITE_OK) std::cout << "Error when binding quantizerName in LoadHMM()" << std::endl; 00205 rc = sqlite3_bind_text(loadHMMStmt, 3, hmm.modelStyle.c_str(), hmm.modelStyle.size(), SQLITE_TRANSIENT); 00206 if(rc!=SQLITE_OK) std::cout << "Error when binding modelStyle in LoadHMM()" << std::endl; 00207 rc = sqlite3_bind_int(loadHMMStmt, 4, hmm.trained); 00208 if(rc!=SQLITE_OK) std::cout << "Error when binding trained in LoadHMM()" << std::endl; 00209 00210 //evaluation 00211 rc = sqlite3_step(loadHMMStmt); 00212 if(rc==SQLITE_ROW){ 00213 hmm.N = sqlite3_column_int(loadHMMStmt, 0); 00214 hmm.M = sqlite3_column_int(loadHMMStmt, 1); 00215 const double* piPtr = (const double*)sqlite3_column_blob(loadHMMStmt, 2); 00216 hmm.pi.assign(piPtr,piPtr+hmm.N); 00217 const double* APtr = (const double*)sqlite3_column_blob(loadHMMStmt, 3); 00218 hmm.A.assign(APtr,APtr+hmm.N*hmm.N); 00219 const double* BPtr = (const double*)sqlite3_column_blob(loadHMMStmt, 4); 00220 hmm.B.assign(BPtr,BPtr+hmm.N*hmm.M); 00221 } 00222 rc = sqlite3_step(loadHMMStmt); 00223 if(rc!=SQLITE_DONE) std::cout << "Error when evaluation in LoadHMM()" << std::endl; 00224 00225 //reset 00226 sqlite3_reset(loadHMMStmt); 00227 sqlite3_clear_bindings(loadHMMStmt); 00228 } 00229 00230 void Database::LoadHMMs(const Quantizer& quantizer, const char* modelStyle, bool trained, vector<HMM>& hmmVec) 00231 { 00232 hmmVec.reserve(hmmVecSpace+hmmVec.size()); 00233 //SQL: "SELECT gestureName, N, M, pi, A, B FROM HMMTable WHERE quantizerName==?1 AND modelStyle==?2 AND trained==?3;" 00234 rc = sqlite3_bind_text(loadHMMsStmt, 1, quantizer.name.c_str(), quantizer.name.size(), SQLITE_TRANSIENT); 00235 if(rc!=SQLITE_OK) std::cout << "Error when binding quantizerName in LoadHMMs()" << std::endl; 00236 rc = sqlite3_bind_text(loadHMMsStmt, 2, modelStyle, -1, SQLITE_TRANSIENT); 00237 if(rc!=SQLITE_OK) std::cout << "Error when binding modelStyle in LoadHMMs()" << std::endl; 00238 rc = sqlite3_bind_int(loadHMMsStmt, 3, trained); 00239 if(rc!=SQLITE_OK) std::cout << "Error when binding trained in LoadHMMs()" << std::endl; 00240 00241 HMM tempHMM(quantizer, modelStyle, trained); 00242 00243 //evaluation 00244 rc = sqlite3_step(loadHMMsStmt); 00245 while(rc==SQLITE_ROW){ 00246 hmmVec.push_back(tempHMM); 00247 HMM& curHMM = hmmVec.back(); 00248 curHMM.gestureName = (const char*)sqlite3_column_text(loadHMMsStmt, 0); 00249 curHMM.N = sqlite3_column_int(loadHMMsStmt, 1); 00250 curHMM.M = sqlite3_column_int(loadHMMsStmt, 2); 00251 const double* piPtr = (const double*)sqlite3_column_blob(loadHMMsStmt, 3); 00252 curHMM.pi.assign(piPtr,piPtr+curHMM.N); 00253 const double* APtr = (const double*)sqlite3_column_blob(loadHMMsStmt, 4); 00254 curHMM.A.assign(APtr,APtr+curHMM.N*curHMM.N); 00255 const double* BPtr = (const double*)sqlite3_column_blob(loadHMMsStmt, 5); 00256 curHMM.B.assign(BPtr,BPtr+curHMM.N*curHMM.M); 00257 rc = sqlite3_step(loadHMMsStmt); 00258 } 00259 if(rc!=SQLITE_DONE) std::cout << "Error when evaluation in LoadHMMs()" << std::endl; 00260 //reset 00261 sqlite3_reset(loadHMMsStmt); 00262 sqlite3_clear_bindings(loadHMMsStmt); 00263 } 00264 00265 void Database::DeleteGestures(const char* gestureName){ 00266 string sql = "DELETE FROM GestureTable WHERE gestureName=='" + string(gestureName) + "';"; 00267 char* errMsg = 0; 00268 rc = sqlite3_exec(db,sql.c_str(),0,0,&errMsg); 00269 if(rc!=SQLITE_OK) std::cout << errMsg << endl; 00270 } 00271 void Database::DeleteObservationSequences(const char* gestureName, const Quantizer& quantizer){ 00272 string sql = "DELETE FROM ObservationSequenceTable WHERE gestureName=='" + string(gestureName) 00273 + "' AND quantizerName=='" + quantizer.name + "';"; 00274 char* errMsg = 0; 00275 rc = sqlite3_exec(db,sql.c_str(),0,0,&errMsg); 00276 if(rc!=SQLITE_OK) std::cout << errMsg << endl; 00277 } 00278 00279 Database::Database() 00280 :dbOpened(false),saveGestureStmt(0),saveObservationSequenceStmt(0), 00281 isExistHMMStmt(0),updateHMMStmt(0),insertHMMStmt(0), 00282 loadGesturesStmt(0),loadObservationSequencesStmt(0),loadHMMStmt(0),loadHMMsStmt(0) 00283 { 00284 rc = sqlite3_open("WiimoteGR.db", &db); 00285 if(rc){ 00286 std::cout << "Can't open database: " << sqlite3_errmsg(db) << std::endl; 00287 sqlite3_close(db); 00288 }else{ 00289 dbOpened=true; 00290 rc = sqlite3_exec(db, 00291 "CREATE TABLE IF NOT EXISTS GestureTable( " 00292 " gestureName TEXT NOT NULL, " 00293 " dataLength INTEGER NOT NULL, " 00294 " data BLOB NOT NULL " 00295 "); " 00296 00297 "CREATE TABLE IF NOT EXISTS ObservationSequenceTable( " 00298 " gestureName TEXT NOT NULL, " 00299 " quantizerName TEXT NOT NULL, " 00300 " oLength INTEGER NOT NULL, " 00301 " o BLOB NOT NULL " 00302 "); " 00303 00304 "CREATE TABLE IF NOT EXISTS HMMTable( " 00305 " gestureName TEXT NOT NULL, " 00306 " quantizerName TEXT NOT NULL, " 00307 " modelStyle TEXT NOT NULL, " 00308 " trained INTEGER NOT NULL, " 00309 " N INTEGER NOT NULL, " 00310 " M INTEGER NOT NULL, " 00311 " pi BLOB NOT NULL, " 00312 " A BLOB NOT NULL, " 00313 " B BLOB NOT NULL " 00314 "); ", 00315 0, 0, &zErrMsg); 00316 if(rc!=SQLITE_OK) std::cout << "Error when CREATE TABLEs" << std::endl; 00317 00318 string saveGestureSQL = "INSERT INTO GestureTable VALUES( :gestureName, :dataLength, :data );"; 00319 rc = sqlite3_prepare_v2(db,saveGestureSQL.c_str(),saveGestureSQL.size()+1, &saveGestureStmt, 0); 00320 if(rc!=SQLITE_OK || saveGestureStmt==0) std::cout << "Error when prepare INSERT INTO GestureTable" << std::endl; 00321 00322 string saveObservationSequenceSQL = "INSERT INTO ObservationSequenceTable VALUES( :gestureName, :quantizerName, :oLength, :o );"; 00323 rc = sqlite3_prepare_v2(db,saveObservationSequenceSQL.c_str(),saveObservationSequenceSQL.size()+1, &saveObservationSequenceStmt, 0); 00324 if(rc!=SQLITE_OK || saveObservationSequenceStmt==0) std::cout << "Error when prepare INSERT INTO ObservationSequenceTable" << std::endl; 00325 00326 string isExistHMMSQL = "SELECT ROWID FROM HMMTable WHERE gestureName==?1 AND quantizerName==?2 AND modelStyle==?3 AND trained==?4 LIMIT 1;"; 00327 rc = sqlite3_prepare_v2(db,isExistHMMSQL.c_str(),isExistHMMSQL.size()+1, &isExistHMMStmt, 0); 00328 if(rc!=SQLITE_OK || isExistHMMStmt==0) std::cout << "Error when prepare SELECT * FROM HMMTable for test existence" << std::endl; 00329 00330 string insertHMMSQL = "INSERT INTO HMMTable VALUES( :gestureName, :quantizerName, :modelStyle, :trained, :N, :M, :pi, :A, :B );"; 00331 rc = sqlite3_prepare_v2(db,insertHMMSQL.c_str(),insertHMMSQL.size()+1, &insertHMMStmt, 0); 00332 if(rc!=SQLITE_OK || insertHMMStmt==0) std::cout << "Error when prepare INSERT INTO HMMTable" << std::endl; 00333 00334 string updateHMMSQL = "UPDATE HMMTable SET N=?5, M=?6, pi=?7, A=?8, B=?9 " 00335 "WHERE gestureName==?1 AND quantizerName==?2 AND modelStyle==?3 AND trained==?4;"; 00336 rc = sqlite3_prepare_v2(db,updateHMMSQL.c_str(),updateHMMSQL.size()+1, &updateHMMStmt, 0); 00337 if(rc!=SQLITE_OK || updateHMMStmt==0) std::cout << "Error when prepare UPDATE HMMTable" << std::endl; 00338 00339 string loadGesturesSQL = "SELECT dataLength, data FROM GestureTable WHERE gestureName==?1;"; 00340 rc = sqlite3_prepare_v2(db,loadGesturesSQL.c_str(),loadGesturesSQL.size()+1, &loadGesturesStmt, 0); 00341 if(rc!=SQLITE_OK || loadGesturesStmt==0) std::cout << "Error when prepare loadGesture statement" << std::endl; 00342 00343 string loadObservationSequencesSQL = "SELECT oLength, o FROM ObservationSequenceTable WHERE gestureName==?1 AND quantizerName==?2;"; 00344 rc = sqlite3_prepare_v2(db,loadObservationSequencesSQL.c_str(),loadObservationSequencesSQL.size()+1, &loadObservationSequencesStmt, 0); 00345 if(rc!=SQLITE_OK || loadObservationSequencesStmt==0) std::cout << "Error when prepare loadObservationSequences statement" << std::endl; 00346 00347 string loadHMMSQL = "SELECT N, M, pi, A, B FROM HMMTable WHERE gestureName==?1 AND quantizerName==?2 AND modelStyle==?3 AND trained==?4;"; 00348 rc = sqlite3_prepare_v2(db,loadHMMSQL.c_str(),loadHMMSQL.size()+1, &loadHMMStmt, 0); 00349 if(rc!=SQLITE_OK || loadHMMStmt==0) std::cout << "Error when prepare loadHMM statement" << std::endl; 00350 00351 string loadHMMsSQL = "SELECT gestureName, N, M, pi, A, B FROM HMMTable WHERE quantizerName==?1 AND modelStyle==?2 AND trained==?3;"; 00352 rc = sqlite3_prepare_v2(db,loadHMMsSQL.c_str(),loadHMMsSQL.size()+1, &loadHMMsStmt, 0); 00353 if(rc!=SQLITE_OK || loadHMMsStmt==0) std::cout << "Error when prepare loadHMMs statement" << std::endl; 00354 } 00355 } 00356 00357 Database::~Database() 00358 { 00359 sqlite3_close(db); 00360 } 00361 }