Weather casting with Machine Learning (SVM and SRNN).
Dependencies: EthernetInterface GraphicHandler NTPClient SRNN SVM SensorModule mbed-rtos mbed
main.cpp@2:20ecfe6edd71, 2015-02-18 (annotated)
- Committer:
- yukari_hinata
- Date:
- Wed Feb 18 15:02:16 2015 +0000
- Revision:
- 2:20ecfe6edd71
- Parent:
- 1:8538381cae81
- Child:
- 3:5add3759e08a
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
yukari_hinata | 0:f6cdb984f638 | 1 | #include "main.hpp" |
yukari_hinata | 0:f6cdb984f638 | 2 | |
yukari_hinata | 1:8538381cae81 | 3 | LocalFileSystem *local_fs; // マウントポイントを定義(ディレクトリパスになる) |
yukari_hinata | 0:f6cdb984f638 | 4 | |
yukari_hinata | 0:f6cdb984f638 | 5 | // Pointer to Class instance (global) |
yukari_hinata | 0:f6cdb984f638 | 6 | SRNN *srnn; |
yukari_hinata | 0:f6cdb984f638 | 7 | MCSVM *mcsvm; |
yukari_hinata | 1:8538381cae81 | 8 | SensorModule *sensor_module; |
yukari_hinata | 1:8538381cae81 | 9 | GraphicHandler *graphic_handler; |
yukari_hinata | 1:8538381cae81 | 10 | // ネットワーク関係(global) |
yukari_hinata | 1:8538381cae81 | 11 | EthernetInterface eth_if; |
yukari_hinata | 2:20ecfe6edd71 | 12 | HTTPServer *http_server; |
yukari_hinata | 1:8538381cae81 | 13 | NTPClient ntp_client; |
yukari_hinata | 0:f6cdb984f638 | 14 | |
yukari_hinata | 0:f6cdb984f638 | 15 | // 系列データ |
yukari_hinata | 0:f6cdb984f638 | 16 | float* new_seqence_data; // 現在の(一番新しい)系列データ |
yukari_hinata | 0:f6cdb984f638 | 17 | float* new_predict_data; // 現在の予測結果 |
yukari_hinata | 0:f6cdb984f638 | 18 | int* new_predict_weather; // 現在の予測天気 |
yukari_hinata | 0:f6cdb984f638 | 19 | float* new_predict_probability; // 現在の予測天気の確率(厳密には,確率ではない...) |
yukari_hinata | 0:f6cdb984f638 | 20 | FILE* seqence_data_fp; // 系列データのファイルポインタ(SRNNと計器の記録に使う) |
yukari_hinata | 0:f6cdb984f638 | 21 | FILE* predict_data_fp; // 予測データ |
yukari_hinata | 2:20ecfe6edd71 | 22 | |
yukari_hinata | 2:20ecfe6edd71 | 23 | // 生存報告LED |
yukari_hinata | 2:20ecfe6edd71 | 24 | DigitalOut live_led(LED1); |
yukari_hinata | 0:f6cdb984f638 | 25 | |
yukari_hinata | 2:20ecfe6edd71 | 26 | int thread_count = 0; |
yukari_hinata | 2:20ecfe6edd71 | 27 | |
yukari_hinata | 2:20ecfe6edd71 | 28 | // 計器/機械学習タスク |
yukari_hinata | 2:20ecfe6edd71 | 29 | void read_and_predict_task(void const *arg) |
yukari_hinata | 0:f6cdb984f638 | 30 | { |
yukari_hinata | 2:20ecfe6edd71 | 31 | // ローカル変数 |
yukari_hinata | 2:20ecfe6edd71 | 32 | int line = 0, ret; |
yukari_hinata | 2:20ecfe6edd71 | 33 | time_t tmp_sec = get_JST(); |
yukari_hinata | 2:20ecfe6edd71 | 34 | struct tm *tmp_tm = localtime(&tmp_sec); |
yukari_hinata | 2:20ecfe6edd71 | 35 | float* srnn_sample = new float[LEN_DATA_SEQUENCE * DIM_SIGNAL]; // SRNNのサンプル |
yukari_hinata | 2:20ecfe6edd71 | 36 | // 読み込みバッファ |
yukari_hinata | 2:20ecfe6edd71 | 37 | float buf_data[DIM_SIGNAL]; |
yukari_hinata | 2:20ecfe6edd71 | 38 | char str_buf[BUF_SIZE]; |
yukari_hinata | 2:20ecfe6edd71 | 39 | |
yukari_hinata | 2:20ecfe6edd71 | 40 | // while (true) { |
yukari_hinata | 2:20ecfe6edd71 | 41 | // 時刻の取得 |
yukari_hinata | 2:20ecfe6edd71 | 42 | // tmp_sec = get_JST(); |
yukari_hinata | 2:20ecfe6edd71 | 43 | // tmp_tm = localtime(&tmp_sec); |
yukari_hinata | 2:20ecfe6edd71 | 44 | |
yukari_hinata | 2:20ecfe6edd71 | 45 | // 1. センサーから読み出す |
yukari_hinata | 2:20ecfe6edd71 | 46 | printf("[%d] S.T.A.R.T \r\n", thread_count++); |
yukari_hinata | 2:20ecfe6edd71 | 47 | |
yukari_hinata | 2:20ecfe6edd71 | 48 | // printf("[%d] Reading from sensors... %02d:%02d:%02d \r\n", thread_count++, tmp_tm->tm_hour, tmp_tm->tm_min, tmp_tm->tm_sec); |
yukari_hinata | 2:20ecfe6edd71 | 49 | sensor_module->read_all_sensor(); |
yukari_hinata | 2:20ecfe6edd71 | 50 | |
yukari_hinata | 2:20ecfe6edd71 | 51 | // データ更新 |
yukari_hinata | 2:20ecfe6edd71 | 52 | __disable_irq(); // 割り込み禁止 |
yukari_hinata | 2:20ecfe6edd71 | 53 | new_seqence_data[TEMPERATURE] = sensor_module->get_temperture(); |
yukari_hinata | 2:20ecfe6edd71 | 54 | new_seqence_data[AIR_PRESSURE] = sensor_module->get_pressure(); |
yukari_hinata | 2:20ecfe6edd71 | 55 | new_seqence_data[HUMIDITY] = sensor_module->get_humidity(); |
yukari_hinata | 2:20ecfe6edd71 | 56 | __enable_irq(); // 割り込み許可 |
yukari_hinata | 2:20ecfe6edd71 | 57 | |
yukari_hinata | 2:20ecfe6edd71 | 58 | printf("T:%f P:%f H:%f \r\n", new_seqence_data[TEMPERATURE], new_seqence_data[AIR_PRESSURE], new_seqence_data[HUMIDITY]); |
yukari_hinata | 2:20ecfe6edd71 | 59 | |
yukari_hinata | 0:f6cdb984f638 | 60 | // 2. 記録(記録ファイルが長くなっていたら, 削る) |
yukari_hinata | 2:20ecfe6edd71 | 61 | printf("Write to File... %02d:%02d \r\n", tmp_tm->tm_hour, tmp_tm->tm_min); |
yukari_hinata | 2:20ecfe6edd71 | 62 | // 追加書き込み |
yukari_hinata | 2:20ecfe6edd71 | 63 | seqence_data_fp = fopen( SEQUENCE_DATA_NAME, "a"); |
yukari_hinata | 2:20ecfe6edd71 | 64 | check_file_open( seqence_data_fp, SEQUENCE_DATA_NAME); |
yukari_hinata | 2:20ecfe6edd71 | 65 | // 形式に沿った文字列を書き出す : y/m/d h:m,<temperature>,<air_pressure>,<humidity> |
yukari_hinata | 2:20ecfe6edd71 | 66 | fprintf( seqence_data_fp, "%d/%d/%d %d:%d:%d,%f,%f,%f\n", |
yukari_hinata | 2:20ecfe6edd71 | 67 | (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, |
yukari_hinata | 2:20ecfe6edd71 | 68 | new_seqence_data[TEMPERATURE], new_seqence_data[AIR_PRESSURE], new_seqence_data[HUMIDITY]); |
yukari_hinata | 2:20ecfe6edd71 | 69 | fclose( seqence_data_fp ); |
yukari_hinata | 2:20ecfe6edd71 | 70 | // 古いデータの削除 |
yukari_hinata | 2:20ecfe6edd71 | 71 | truncate_data_file(); |
yukari_hinata | 2:20ecfe6edd71 | 72 | |
yukari_hinata | 2:20ecfe6edd71 | 73 | // 3. SRNNに学習データを読み込ませる. |
yukari_hinata | 2:20ecfe6edd71 | 74 | printf("Set SRNN sample... %02d:%02d \r\n", tmp_tm->tm_hour, tmp_tm->tm_min); |
yukari_hinata | 2:20ecfe6edd71 | 75 | seqence_data_fp = fopen( SEQUENCE_DATA_NAME, "r"); |
yukari_hinata | 2:20ecfe6edd71 | 76 | check_file_open( seqence_data_fp, SEQUENCE_DATA_NAME); |
yukari_hinata | 2:20ecfe6edd71 | 77 | line = 0; |
yukari_hinata | 2:20ecfe6edd71 | 78 | while( ( ret = fscanf( seqence_data_fp, " %[^\n,],%f,%f,%f", str_buf, &(buf_data[0]), &(buf_data[1]), &(buf_data[2])) ) != EOF ) { |
yukari_hinata | 2:20ecfe6edd71 | 79 | memcpy(&(srnn_sample[line * DIM_SIGNAL]), buf_data, sizeof(float) * DIM_SIGNAL); |
yukari_hinata | 2:20ecfe6edd71 | 80 | // 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)); |
yukari_hinata | 2:20ecfe6edd71 | 81 | line++; |
yukari_hinata | 2:20ecfe6edd71 | 82 | } |
yukari_hinata | 2:20ecfe6edd71 | 83 | fclose( seqence_data_fp ); |
yukari_hinata | 2:20ecfe6edd71 | 84 | srnn->set_sample(srnn_sample); |
yukari_hinata | 2:20ecfe6edd71 | 85 | |
yukari_hinata | 0:f6cdb984f638 | 86 | // 4. SRNNの学習/予測結果から, MCSVMで天気識別 |
yukari_hinata | 2:20ecfe6edd71 | 87 | printf("Learning... %02d:%02d \r\n", tmp_tm->tm_hour, tmp_tm->tm_min); |
yukari_hinata | 2:20ecfe6edd71 | 88 | srnn->learning(); |
yukari_hinata | 2:20ecfe6edd71 | 89 | srnn->predict(new_seqence_data); |
yukari_hinata | 2:20ecfe6edd71 | 90 | |
yukari_hinata | 2:20ecfe6edd71 | 91 | memcpy(new_predict_data, srnn->predict_signal, sizeof(float) * DIM_SIGNAL * PREDICT_LENGTH); |
yukari_hinata | 2:20ecfe6edd71 | 92 | // MCSVMによる天候識別 |
yukari_hinata | 2:20ecfe6edd71 | 93 | for (int i_predict = 0; i_predict < PREDICT_LENGTH; i_predict++) { |
yukari_hinata | 2:20ecfe6edd71 | 94 | // 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]); |
yukari_hinata | 2:20ecfe6edd71 | 95 | new_predict_weather[i_predict] = mcsvm->predict_label(&(new_predict_data[i_predict * DIM_SIGNAL])); |
yukari_hinata | 2:20ecfe6edd71 | 96 | new_predict_probability[i_predict] = mcsvm->predict_probability(&(new_predict_data[i_predict * DIM_SIGNAL])); |
yukari_hinata | 2:20ecfe6edd71 | 97 | // printf("P_W : %d P_P : %f \r\n", new_predict_weather[i_predict], new_predict_probability[i_predict]); |
yukari_hinata | 2:20ecfe6edd71 | 98 | } |
yukari_hinata | 2:20ecfe6edd71 | 99 | // printf("SVM predict finished \r\n"); |
yukari_hinata | 2:20ecfe6edd71 | 100 | |
yukari_hinata | 2:20ecfe6edd71 | 101 | |
yukari_hinata | 2:20ecfe6edd71 | 102 | // 5. 予測結果の書き込み |
yukari_hinata | 2:20ecfe6edd71 | 103 | printf("Write out predict... %02d:%02d \r\n", tmp_tm->tm_hour, tmp_tm->tm_min); |
yukari_hinata | 2:20ecfe6edd71 | 104 | predict_data_fp = fopen( PREDICT_DATA_NAME, "w"); |
yukari_hinata | 2:20ecfe6edd71 | 105 | check_file_open( predict_data_fp, PREDICT_DATA_NAME); |
yukari_hinata | 2:20ecfe6edd71 | 106 | for (int i_predict = 0; i_predict < PREDICT_LENGTH; i_predict++) { |
yukari_hinata | 2:20ecfe6edd71 | 107 | // 予測時刻へ変換 |
yukari_hinata | 2:20ecfe6edd71 | 108 | tmp_sec += PREDICT_INTERVAL_TIME; |
yukari_hinata | 2:20ecfe6edd71 | 109 | tmp_tm = localtime(&tmp_sec); |
yukari_hinata | 2:20ecfe6edd71 | 110 | // 気象を文字列に変換 |
yukari_hinata | 2:20ecfe6edd71 | 111 | switch(new_predict_weather[i_predict]) { |
yukari_hinata | 2:20ecfe6edd71 | 112 | case SHINY: |
yukari_hinata | 2:20ecfe6edd71 | 113 | strcpy(str_buf, "shiny"); |
yukari_hinata | 2:20ecfe6edd71 | 114 | break; |
yukari_hinata | 2:20ecfe6edd71 | 115 | case CLOUDY: |
yukari_hinata | 2:20ecfe6edd71 | 116 | strcpy(str_buf, "cloudy"); |
yukari_hinata | 2:20ecfe6edd71 | 117 | break; |
yukari_hinata | 2:20ecfe6edd71 | 118 | case RAINY: |
yukari_hinata | 2:20ecfe6edd71 | 119 | strcpy(str_buf, "rainy"); |
yukari_hinata | 2:20ecfe6edd71 | 120 | break; |
yukari_hinata | 2:20ecfe6edd71 | 121 | case SNOWY: |
yukari_hinata | 2:20ecfe6edd71 | 122 | strcpy(str_buf, "snowy"); |
yukari_hinata | 2:20ecfe6edd71 | 123 | break; |
yukari_hinata | 2:20ecfe6edd71 | 124 | default: |
yukari_hinata | 2:20ecfe6edd71 | 125 | fprintf( stderr, "Error in write predict result (in weather switch). \r\n"); |
yukari_hinata | 2:20ecfe6edd71 | 126 | break; |
yukari_hinata | 2:20ecfe6edd71 | 127 | } |
yukari_hinata | 2:20ecfe6edd71 | 128 | // 書き出しフォーマット : y/m/d h:m,<weather>,<temperature>,<air_pressure>,<humidity> |
yukari_hinata | 2:20ecfe6edd71 | 129 | fprintf( predict_data_fp, "%d/%d/%d %d:%d:%d,%s,%f,%f,%f\n", |
yukari_hinata | 2:20ecfe6edd71 | 130 | (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, |
yukari_hinata | 2:20ecfe6edd71 | 131 | str_buf, |
yukari_hinata | 2:20ecfe6edd71 | 132 | new_predict_data[i_predict * DIM_SIGNAL + TEMPERATURE], |
yukari_hinata | 2:20ecfe6edd71 | 133 | new_predict_data[i_predict * DIM_SIGNAL + AIR_PRESSURE], |
yukari_hinata | 2:20ecfe6edd71 | 134 | new_predict_data[i_predict * DIM_SIGNAL + HUMIDITY]); |
yukari_hinata | 2:20ecfe6edd71 | 135 | } |
yukari_hinata | 2:20ecfe6edd71 | 136 | fclose( predict_data_fp ); |
yukari_hinata | 2:20ecfe6edd71 | 137 | |
yukari_hinata | 2:20ecfe6edd71 | 138 | // GraphicHandlerの現在の観測/予測データのセット |
yukari_hinata | 2:20ecfe6edd71 | 139 | graphic_handler->set_now_data(new_seqence_data); |
yukari_hinata | 2:20ecfe6edd71 | 140 | graphic_handler->set_predict_data(new_predict_data, new_predict_weather, new_predict_probability); |
yukari_hinata | 2:20ecfe6edd71 | 141 | |
yukari_hinata | 2:20ecfe6edd71 | 142 | // printf("Finishing task... %02d:%02d:%02d \r\n", tmp_tm->tm_hour, tmp_tm->tm_min, tmp_tm->tm_sec); |
yukari_hinata | 2:20ecfe6edd71 | 143 | // Thread::wait(4 * 1000); |
yukari_hinata | 2:20ecfe6edd71 | 144 | // } |
yukari_hinata | 2:20ecfe6edd71 | 145 | |
yukari_hinata | 2:20ecfe6edd71 | 146 | delete [] srnn_sample; |
yukari_hinata | 2:20ecfe6edd71 | 147 | // delete tmp_tm; <- してはいけない(戒め) |
yukari_hinata | 2:20ecfe6edd71 | 148 | |
yukari_hinata | 0:f6cdb984f638 | 149 | } |
yukari_hinata | 0:f6cdb984f638 | 150 | |
yukari_hinata | 0:f6cdb984f638 | 151 | // 描画スレッド : 優先度低め |
yukari_hinata | 2:20ecfe6edd71 | 152 | void draw_task(void const *arg) |
yukari_hinata | 0:f6cdb984f638 | 153 | { |
yukari_hinata | 2:20ecfe6edd71 | 154 | while (true) { |
yukari_hinata | 2:20ecfe6edd71 | 155 | // 1. 描画更新 <- 学習中は止めたい... |
yukari_hinata | 2:20ecfe6edd71 | 156 | //printf("draw thread start. \r\n"); |
yukari_hinata | 2:20ecfe6edd71 | 157 | if (time(NULL) % 60 == 0) { |
yukari_hinata | 2:20ecfe6edd71 | 158 | // 一分毎に表示時間を更新 |
yukari_hinata | 2:20ecfe6edd71 | 159 | graphic_handler->update_time(); |
yukari_hinata | 2:20ecfe6edd71 | 160 | } |
yukari_hinata | 2:20ecfe6edd71 | 161 | graphic_handler->update_image(); |
yukari_hinata | 2:20ecfe6edd71 | 162 | graphic_handler->update_draw(); |
yukari_hinata | 2:20ecfe6edd71 | 163 | //printf("draw thread finish. \r\n"); |
yukari_hinata | 2:20ecfe6edd71 | 164 | |
yukari_hinata | 2:20ecfe6edd71 | 165 | Thread::wait(2 * 1000); |
yukari_hinata | 2:20ecfe6edd71 | 166 | } |
yukari_hinata | 0:f6cdb984f638 | 167 | } |
yukari_hinata | 0:f6cdb984f638 | 168 | |
yukari_hinata | 0:f6cdb984f638 | 169 | |
yukari_hinata | 0:f6cdb984f638 | 170 | // ネットワークスレッド |
yukari_hinata | 2:20ecfe6edd71 | 171 | void network_task(void const *arg) |
yukari_hinata | 0:f6cdb984f638 | 172 | { |
yukari_hinata | 2:20ecfe6edd71 | 173 | while (true) { |
yukari_hinata | 2:20ecfe6edd71 | 174 | // 1. ポート80のListen <- 学習中は止めたい... |
yukari_hinata | 2:20ecfe6edd71 | 175 | //http_server->poll(); |
yukari_hinata | 2:20ecfe6edd71 | 176 | Thread::wait(0.5 * 1000); |
yukari_hinata | 2:20ecfe6edd71 | 177 | } |
yukari_hinata | 2:20ecfe6edd71 | 178 | } |
yukari_hinata | 2:20ecfe6edd71 | 179 | |
yukari_hinata | 2:20ecfe6edd71 | 180 | // 生存報告LEDチカ |
yukari_hinata | 2:20ecfe6edd71 | 181 | void liveled_task(void const *arg) |
yukari_hinata | 2:20ecfe6edd71 | 182 | { |
yukari_hinata | 2:20ecfe6edd71 | 183 | while (true) { |
yukari_hinata | 2:20ecfe6edd71 | 184 | live_led = !live_led; |
yukari_hinata | 2:20ecfe6edd71 | 185 | Thread::wait(1 * 1000); |
yukari_hinata | 2:20ecfe6edd71 | 186 | } |
yukari_hinata | 0:f6cdb984f638 | 187 | } |
yukari_hinata | 0:f6cdb984f638 | 188 | |
yukari_hinata | 0:f6cdb984f638 | 189 | // エントリ. スレッドの生成, そして待つ |
yukari_hinata | 0:f6cdb984f638 | 190 | int main(void) |
yukari_hinata | 0:f6cdb984f638 | 191 | { |
yukari_hinata | 0:f6cdb984f638 | 192 | set_new_handler(no_memory); |
yukari_hinata | 1:8538381cae81 | 193 | local_fs = new LocalFileSystem("local"); |
yukari_hinata | 0:f6cdb984f638 | 194 | setup(); |
yukari_hinata | 2:20ecfe6edd71 | 195 | |
yukari_hinata | 2:20ecfe6edd71 | 196 | RtosTimer ml_timer(read_and_predict_task, osTimerPeriodic, NULL); |
yukari_hinata | 2:20ecfe6edd71 | 197 | Thread draw_thread(draw_task, NULL, osPriorityBelowNormal); |
yukari_hinata | 2:20ecfe6edd71 | 198 | Thread network_thread(network_task, NULL, osPriorityLow); |
yukari_hinata | 2:20ecfe6edd71 | 199 | Thread liveled_thread(liveled_task, NULL); |
yukari_hinata | 2:20ecfe6edd71 | 200 | |
yukari_hinata | 2:20ecfe6edd71 | 201 | ml_timer.start(5 * 1000); |
yukari_hinata | 2:20ecfe6edd71 | 202 | |
yukari_hinata | 2:20ecfe6edd71 | 203 | Thread::wait(osWaitForever); |
yukari_hinata | 2:20ecfe6edd71 | 204 | |
yukari_hinata | 0:f6cdb984f638 | 205 | } |