Weather casting with Machine Learning (SVM and SRNN).

Dependencies:   EthernetInterface GraphicHandler NTPClient SRNN SVM SensorModule mbed-rtos mbed

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);
+
 }