Weather casting with Machine Learning (SVM and SRNN).
Dependencies: EthernetInterface GraphicHandler NTPClient SRNN SVM SensorModule mbed-rtos mbed
Diff: main.cpp
- Revision:
- 2:20ecfe6edd71
- Parent:
- 1:8538381cae81
- Child:
- 3:5add3759e08a
--- a/main.cpp Mon Feb 16 07:53:45 2015 +0000 +++ b/main.cpp Wed Feb 18 15:02:16 2015 +0000 @@ -2,9 +2,6 @@ LocalFileSystem *local_fs; // マウントポイントを定義(ディレクトリパスになる) -// 時間(global) -time_t global_time; // 現在時刻 -Mutex time_mutex; // 時間のMutex // Pointer to Class instance (global) SRNN *srnn; MCSVM *mcsvm; @@ -12,7 +9,7 @@ GraphicHandler *graphic_handler; // ネットワーク関係(global) EthernetInterface eth_if; -TCPSocketServer http_server; +HTTPServer *http_server; NTPClient ntp_client; // 系列データ @@ -22,32 +19,171 @@ float* new_predict_probability; // 現在の予測天気の確率(厳密には,確率ではない...) FILE* seqence_data_fp; // 系列データのファイルポインタ(SRNNと計器の記録に使う) FILE* predict_data_fp; // 予測データ -Mutex seqence_data_mutex; // 系列データのMutex -Mutex predict_data_mutex; // 予測データのMutex + +// 生存報告LED +DigitalOut live_led(LED1); -// 計器/機械学習スレッド -void read_and_predict_thread(void const *arg) +int thread_count = 0; + +// 計器/機械学習タスク +void read_and_predict_task(void const *arg) { - // 1. 定期的(周期はmainが指定)にセンサーから読み出す + // ローカル変数 + int line = 0, ret; + time_t tmp_sec = get_JST(); + struct tm *tmp_tm = localtime(&tmp_sec); + float* srnn_sample = new float[LEN_DATA_SEQUENCE * DIM_SIGNAL]; // SRNNのサンプル + // 読み込みバッファ + float buf_data[DIM_SIGNAL]; + char str_buf[BUF_SIZE]; + + // while (true) { + // 時刻の取得 + // tmp_sec = get_JST(); + // tmp_tm = localtime(&tmp_sec); + + // 1. センサーから読み出す + printf("[%d] S.T.A.R.T \r\n", thread_count++); + + // printf("[%d] Reading from sensors... %02d:%02d:%02d \r\n", thread_count++, tmp_tm->tm_hour, tmp_tm->tm_min, tmp_tm->tm_sec); + sensor_module->read_all_sensor(); + + // データ更新 + __disable_irq(); // 割り込み禁止 + new_seqence_data[TEMPERATURE] = sensor_module->get_temperture(); + new_seqence_data[AIR_PRESSURE] = sensor_module->get_pressure(); + new_seqence_data[HUMIDITY] = sensor_module->get_humidity(); + __enable_irq(); // 割り込み許可 + + printf("T:%f P:%f H:%f \r\n", new_seqence_data[TEMPERATURE], new_seqence_data[AIR_PRESSURE], new_seqence_data[HUMIDITY]); + // 2. 記録(記録ファイルが長くなっていたら, 削る) - // 3. SRNNに学習データを読み込ませる.(Mutexを使う) + printf("Write to File... %02d:%02d \r\n", tmp_tm->tm_hour, tmp_tm->tm_min); + // 追加書き込み + seqence_data_fp = fopen( SEQUENCE_DATA_NAME, "a"); + check_file_open( seqence_data_fp, SEQUENCE_DATA_NAME); + // 形式に沿った文字列を書き出す : y/m/d h:m,<temperature>,<air_pressure>,<humidity> + fprintf( seqence_data_fp, "%d/%d/%d %d:%d:%d,%f,%f,%f\n", + (tmp_tm->tm_year + 1900), (tmp_tm->tm_mon + 1), tmp_tm->tm_mday, tmp_tm->tm_hour, tmp_tm->tm_min, tmp_tm->tm_sec, + new_seqence_data[TEMPERATURE], new_seqence_data[AIR_PRESSURE], new_seqence_data[HUMIDITY]); + fclose( seqence_data_fp ); + // 古いデータの削除 + truncate_data_file(); + + // 3. SRNNに学習データを読み込ませる. + printf("Set SRNN sample... %02d:%02d \r\n", tmp_tm->tm_hour, tmp_tm->tm_min); + seqence_data_fp = fopen( SEQUENCE_DATA_NAME, "r"); + check_file_open( seqence_data_fp, SEQUENCE_DATA_NAME); + line = 0; + while( ( ret = fscanf( seqence_data_fp, " %[^\n,],%f,%f,%f", str_buf, &(buf_data[0]), &(buf_data[1]), &(buf_data[2])) ) != EOF ) { + memcpy(&(srnn_sample[line * DIM_SIGNAL]), buf_data, sizeof(float) * DIM_SIGNAL); + // printf("sample %d : %s %f %f %f \r\n", line, str_buf, MATRIX_AT(srnn_sample,DIM_SIGNAL,line,0), MATRIX_AT(srnn_sample,DIM_SIGNAL,line,1), MATRIX_AT(srnn_sample,DIM_SIGNAL,line,2)); + line++; + } + fclose( seqence_data_fp ); + srnn->set_sample(srnn_sample); + // 4. SRNNの学習/予測結果から, MCSVMで天気識別 - // 5. 予測結果のセット, 書き込み + printf("Learning... %02d:%02d \r\n", tmp_tm->tm_hour, tmp_tm->tm_min); + srnn->learning(); + srnn->predict(new_seqence_data); + + memcpy(new_predict_data, srnn->predict_signal, sizeof(float) * DIM_SIGNAL * PREDICT_LENGTH); + // MCSVMによる天候識別 + for (int i_predict = 0; i_predict < PREDICT_LENGTH; i_predict++) { + // printf("predict_data[%d] : %f %f %f \r\n", i_predict, new_predict_data[i_predict * DIM_SIGNAL], new_predict_data[i_predict * DIM_SIGNAL + 1], new_predict_data[i_predict * DIM_SIGNAL + 2]); + new_predict_weather[i_predict] = mcsvm->predict_label(&(new_predict_data[i_predict * DIM_SIGNAL])); + new_predict_probability[i_predict] = mcsvm->predict_probability(&(new_predict_data[i_predict * DIM_SIGNAL])); + // printf("P_W : %d P_P : %f \r\n", new_predict_weather[i_predict], new_predict_probability[i_predict]); + } + // printf("SVM predict finished \r\n"); + + + // 5. 予測結果の書き込み + printf("Write out predict... %02d:%02d \r\n", tmp_tm->tm_hour, tmp_tm->tm_min); + predict_data_fp = fopen( PREDICT_DATA_NAME, "w"); + check_file_open( predict_data_fp, PREDICT_DATA_NAME); + for (int i_predict = 0; i_predict < PREDICT_LENGTH; i_predict++) { + // 予測時刻へ変換 + tmp_sec += PREDICT_INTERVAL_TIME; + tmp_tm = localtime(&tmp_sec); + // 気象を文字列に変換 + switch(new_predict_weather[i_predict]) { + case SHINY: + strcpy(str_buf, "shiny"); + break; + case CLOUDY: + strcpy(str_buf, "cloudy"); + break; + case RAINY: + strcpy(str_buf, "rainy"); + break; + case SNOWY: + strcpy(str_buf, "snowy"); + break; + default: + fprintf( stderr, "Error in write predict result (in weather switch). \r\n"); + break; + } + // 書き出しフォーマット : y/m/d h:m,<weather>,<temperature>,<air_pressure>,<humidity> + fprintf( predict_data_fp, "%d/%d/%d %d:%d:%d,%s,%f,%f,%f\n", + (tmp_tm->tm_year + 1900), (tmp_tm->tm_mon + 1), tmp_tm->tm_mday, tmp_tm->tm_hour, tmp_tm->tm_min, tmp_tm->tm_sec, + str_buf, + new_predict_data[i_predict * DIM_SIGNAL + TEMPERATURE], + new_predict_data[i_predict * DIM_SIGNAL + AIR_PRESSURE], + new_predict_data[i_predict * DIM_SIGNAL + HUMIDITY]); + } + fclose( predict_data_fp ); + + // GraphicHandlerの現在の観測/予測データのセット + graphic_handler->set_now_data(new_seqence_data); + graphic_handler->set_predict_data(new_predict_data, new_predict_weather, new_predict_probability); + + // printf("Finishing task... %02d:%02d:%02d \r\n", tmp_tm->tm_hour, tmp_tm->tm_min, tmp_tm->tm_sec); + // Thread::wait(4 * 1000); + // } + + delete [] srnn_sample; + // delete tmp_tm; <- してはいけない(戒め) + } // 描画スレッド : 優先度低め -void draw_thread(void const *arg) +void draw_task(void const *arg) { - // 1. 1分に一回, 時間を取りにいく - // 2. 描画更新 <- 学習中は止めたい... + while (true) { + // 1. 描画更新 <- 学習中は止めたい... + //printf("draw thread start. \r\n"); + if (time(NULL) % 60 == 0) { + // 一分毎に表示時間を更新 + graphic_handler->update_time(); + } + graphic_handler->update_image(); + graphic_handler->update_draw(); + //printf("draw thread finish. \r\n"); + + Thread::wait(2 * 1000); + } } // ネットワークスレッド -void network_thread(void const *arg) +void network_task(void const *arg) { - // 1. たまに時間を更新 - // 2. ポート80のListen <- 学習中は止めたい... + while (true) { + // 1. ポート80のListen <- 学習中は止めたい... + //http_server->poll(); + Thread::wait(0.5 * 1000); + } +} + +// 生存報告LEDチカ +void liveled_task(void const *arg) +{ + while (true) { + live_led = !live_led; + Thread::wait(1 * 1000); + } } // エントリ. スレッドの生成, そして待つ @@ -56,6 +192,14 @@ set_new_handler(no_memory); local_fs = new LocalFileSystem("local"); setup(); - printf("EXIT SUCESS!! \r\n"); - return 0; + + RtosTimer ml_timer(read_and_predict_task, osTimerPeriodic, NULL); + Thread draw_thread(draw_task, NULL, osPriorityBelowNormal); + Thread network_thread(network_task, NULL, osPriorityLow); + Thread liveled_thread(liveled_task, NULL); + + ml_timer.start(5 * 1000); + + Thread::wait(osWaitForever); + }