Weather casting with Machine Learning (SVM and SRNN).

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "main.hpp"
00002 
00003 LocalFileSystem *local_fs;  // マウントポイント
00004 
00005 // Pointer to Class instance (global)
00006 SRNN            *srnn;
00007 MCSVM           *mcsvm;
00008 SensorModule    *sensor_module;
00009 GraphicHandler  *graphic_handler;
00010 // ネットワーク関係(global)
00011 EthernetInterface    eth_if;
00012 NTPClient            ntp_client;
00013 
00014 // 系列データ
00015 float* new_seqence_data;        // 現在の(一番新しい)系列データ
00016 float* new_predict_data;        // 現在の予測結果
00017 int*   new_predict_weather;     // 現在の予測天気
00018 float* new_predict_probability; // 現在の予測天気の確率(厳密には,確率ではない...)
00019 float* srnn_sample_queue;   // SRNNのサンプルキュー(サンキューキュー).
00020 
00021 volatile int ml_flag;
00022 time_t now_time;
00023 struct tm* local_time_p;
00024 
00025 // 生存報告LED
00026 DigitalOut live_led(LED1);
00027 
00028 volatile int thread_count = 0;
00029 int num_data_line = 0;
00030 
00031 // 計器タスク
00032 void read_task(void const *arg)
00033 {
00034 
00035     FILE* seqence_data_fp;
00036 
00037     // データ読み出し
00038     sensor_module->read_all_sensor();
00039     new_seqence_data[TEMPERATURE]  = sensor_module->get_temperture();
00040     new_seqence_data[AIR_PRESSURE] = sensor_module->get_pressure();
00041     new_seqence_data[HUMIDITY]     = sensor_module->get_humidity();
00042     printf("T:%f P:%f H:%f \r\n", new_seqence_data[TEMPERATURE], new_seqence_data[AIR_PRESSURE], new_seqence_data[HUMIDITY]);
00043     graphic_handler->set_now_data(new_seqence_data);
00044 
00045     // サンプルのアップデート
00046     update_srnn_sample(srnn_sample_queue, new_seqence_data);
00047 
00048     // ログの追加
00049     seqence_data_fp = fopen( SEQUENCE_DATA_NAME, "a");
00050     check_file_open( seqence_data_fp, SEQUENCE_DATA_NAME);
00051 
00052     // 形式に沿った文字列を書き出す : y/m/d h:m,<temperature>,<air_pressure>,<humidity>
00053     fprintf( seqence_data_fp, "%d/%d/%d %d:%d:%d,%f,%f,%f\n",
00054              (local_time_p->tm_year + 1900), (local_time_p->tm_mon + 1), local_time_p->tm_mday, local_time_p->tm_hour, local_time_p->tm_min, local_time_p->tm_sec,
00055              new_seqence_data[TEMPERATURE], new_seqence_data[AIR_PRESSURE], new_seqence_data[HUMIDITY]);
00056     fclose( seqence_data_fp );
00057 
00058     // ログファイルの切り詰め
00059     num_data_line++;
00060     if ( num_data_line > SUITABLE_LOG_LENGTH ) {
00061         // コメント:この関数はファイルポインタの開け閉めが激しい為, 頻繁に使うと落ちる可能性あり
00062         truncate_data_file(SUITABLE_LOG_LENGTH);
00063     }
00064 
00065 }
00066 
00067 // 機械学習タスク
00068 void ml_task(void const *arg)
00069 {
00070     // キューからサンプルセット
00071     srnn->set_sample(srnn_sample_queue);
00072 
00073     // SRNNの学習/予測結果から, MCSVMで天気識別
00074     // printf("Learning... %02d:%02d \r\n", local_time_p->tm_hour, local_time_p->tm_min);
00075     srnn->learning();
00076     srnn->predict(new_seqence_data);
00077     memcpy(new_predict_data, srnn->predict_signal, sizeof(float) * DIM_SIGNAL * PREDICT_LENGTH);
00078     // MCSVMによる天候識別
00079     for (int i_predict = 0; i_predict < PREDICT_LENGTH; i_predict++) {
00080         new_predict_weather[i_predict]     = mcsvm->predict_label(&(new_predict_data[i_predict * DIM_SIGNAL]));
00081         new_predict_probability[i_predict] = mcsvm->predict_probability(&(new_predict_data[i_predict * DIM_SIGNAL]));
00082     }
00083     // printf("SVM predict finished \r\n");
00084 }
00085 
00086 //  予測結果の書き込み
00087 void write_predict_task(void const* arg)
00088 {
00089 
00090     FILE* predict_data_fp;
00091     char str_buf[BUF_SIZE];
00092     printf("Write out predict... %02d:%02d \r\n", local_time_p->tm_hour, local_time_p->tm_min);
00093     predict_data_fp = fopen( PREDICT_DATA_NAME, "w");
00094     check_file_open( predict_data_fp, PREDICT_DATA_NAME);
00095 
00096     for (int i_predict = 0; i_predict < PREDICT_LENGTH; i_predict++) {
00097         // 予測時刻へ変換
00098         now_time += PREDICT_INTERVAL_TIME;
00099         local_time_p = localtime(&now_time);
00100         // 気象を文字列に変換
00101         switch(new_predict_weather[i_predict]) {
00102             case SHINY:
00103                 strcpy(str_buf, "shiny");
00104                 break;
00105             case CLOUDY:
00106                 strcpy(str_buf, "cloudy");
00107                 break;
00108             case RAINY:
00109                 strcpy(str_buf, "rainy");
00110                 break;
00111             case SNOWY:
00112                 strcpy(str_buf, "snowy");
00113                 break;
00114             default:
00115                 fprintf( stderr, "Error in write predict result (in weather switch). \r\n");
00116                 break;
00117         }
00118         // 書き出しフォーマット : y/m/d h:m,<weather>,<temperature>,<air_pressure>,<humidity>
00119         fprintf( predict_data_fp, "%d/%d/%d %d:%d:%d,%s,%f,%f,%f\n",
00120                  (local_time_p->tm_year + 1900), (local_time_p->tm_mon + 1), local_time_p->tm_mday, local_time_p->tm_hour, local_time_p->tm_min, local_time_p->tm_sec,
00121                  str_buf,
00122                  new_predict_data[i_predict * DIM_SIGNAL + TEMPERATURE],
00123                  new_predict_data[i_predict * DIM_SIGNAL + AIR_PRESSURE],
00124                  new_predict_data[i_predict * DIM_SIGNAL + HUMIDITY]);
00125     }
00126 
00127     fclose( predict_data_fp );
00128 
00129     // GraphicHandlerの現在予測データのセット
00130     graphic_handler->set_predict_data(new_predict_data, new_predict_weather, new_predict_probability);
00131 
00132 }
00133 
00134 // 描画スレッド : 優先度低め
00135 void draw_task(void const *arg)
00136 {
00137     while (true) {
00138 
00139         if (ml_flag) {
00140             Thread::signal_wait(0x2, osWaitForever);
00141         }
00142         //printf("sp : %d, pc : %d \r\n", __current_sp(), __current_pc());
00143 
00144         // printf("draw thread start. \r\n");
00145         if (time(NULL) % 60 == 0) {
00146             // 一分毎に表示時間を更新
00147             graphic_handler->update_time();
00148         }
00149         graphic_handler->update_image();
00150         // 画面更新
00151         graphic_handler->update_draw();
00152         // printf("draw thread finish. \r\n");
00153         Thread::wait(1 * 1000);
00154 
00155     }
00156 }
00157 
00158 
00159 // ネットワークスレッド : リソースの限界. 廃止.
00160 /*
00161 void network_task(void const *arg)
00162 {
00163     while (true) {
00164         while (ml_flag) {
00165             Thread::signal_wait(0x3);
00166         }
00167         // 1. ポート80のListen
00168         http_server->poll();
00169         // for (int dum = 0; dum < 10000; dum++) ;
00170         net_led = !net_led;
00171         // Thread::wait(500);
00172     }
00173 }
00174 */
00175 
00176 // 生存報告LEDチカ
00177 void liveled_task(void const *arg)
00178 {
00179     while (true) {
00180         if (ml_flag) {
00181             Thread::signal_wait(0x1, osWaitForever);
00182         }
00183         // printf("sp : %d, pc : %d \r\n", __current_sp(), __current_pc());
00184 
00185         live_led = !live_led;
00186         Thread::wait(1000);
00187     }
00188 }
00189 
00190 //
00191 int main(void)
00192 {
00193     set_new_handler(no_memory);
00194     local_fs = new LocalFileSystem("local");
00195 
00196     setup();
00197 
00198     // 擬似的なロックをかける(他のスレッドを待ち状態に)
00199     ml_flag = 1;
00200 
00201     Thread draw_thread(draw_task, NULL, osPriorityNormal, 800);
00202     Thread liveled_thread(liveled_task, NULL, osPriorityLow, 200);
00203 
00204     osThreadSetPriority(Thread::gettid() ,osPriorityHigh);
00205     while (true) {
00206         ml_flag = 1;
00207         // 現在時刻取得(ロギングに用いる)
00208         now_time = time(NULL);
00209         local_time_p = localtime(&now_time);
00210         // センサ読み込み, 機械学習, 予測データセット
00211         //read_task(NULL);
00212         ml_task(NULL);
00213         write_predict_task(NULL);
00214         ml_flag = 0;
00215         // シグナルにより他スレッドの再開
00216         liveled_thread.signal_set(0x1);
00217         draw_thread.signal_set(0x2);
00218         Thread::wait(PREDICT_INTERVAL_TIME);
00219     }
00220 
00221     error("unreachable here");
00222 
00223 }