Weather casting with Machine Learning (SVM and SRNN).

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

main.cpp

Committer:
yukari_hinata
Date:
2015-02-22
Revision:
6:29d393d430d0
Parent:
5:b61f3f5b0fc8

File content as of revision 6:29d393d430d0:

#include "main.hpp"

LocalFileSystem *local_fs;  // マウントポイント

// Pointer to Class instance (global)
SRNN            *srnn;
MCSVM           *mcsvm;
SensorModule    *sensor_module;
GraphicHandler  *graphic_handler;
// ネットワーク関係(global)
EthernetInterface    eth_if;
NTPClient            ntp_client;

// 系列データ
float* new_seqence_data;        // 現在の(一番新しい)系列データ
float* new_predict_data;        // 現在の予測結果
int*   new_predict_weather;     // 現在の予測天気
float* new_predict_probability; // 現在の予測天気の確率(厳密には,確率ではない...)
float* srnn_sample_queue;   // SRNNのサンプルキュー(サンキューキュー).

volatile int ml_flag;
time_t now_time;
struct tm* local_time_p;

// 生存報告LED
DigitalOut live_led(LED1);

volatile int thread_count = 0;
int num_data_line = 0;

// 計器タスク
void read_task(void const *arg)
{

    FILE* seqence_data_fp;

    // データ読み出し
    sensor_module->read_all_sensor();
    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();
    printf("T:%f P:%f H:%f \r\n", new_seqence_data[TEMPERATURE], new_seqence_data[AIR_PRESSURE], new_seqence_data[HUMIDITY]);
    graphic_handler->set_now_data(new_seqence_data);

    // サンプルのアップデート
    update_srnn_sample(srnn_sample_queue, new_seqence_data);

    // ログの追加
    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",
             (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,
             new_seqence_data[TEMPERATURE], new_seqence_data[AIR_PRESSURE], new_seqence_data[HUMIDITY]);
    fclose( seqence_data_fp );

    // ログファイルの切り詰め
    num_data_line++;
    if ( num_data_line > SUITABLE_LOG_LENGTH ) {
        // コメント:この関数はファイルポインタの開け閉めが激しい為, 頻繁に使うと落ちる可能性あり
        truncate_data_file(SUITABLE_LOG_LENGTH);
    }

}

// 機械学習タスク
void ml_task(void const *arg)
{
    // キューからサンプルセット
    srnn->set_sample(srnn_sample_queue);

    // SRNNの学習/予測結果から, MCSVMで天気識別
    // printf("Learning... %02d:%02d \r\n", local_time_p->tm_hour, local_time_p->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++) {
        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("SVM predict finished \r\n");
}

//  予測結果の書き込み
void write_predict_task(void const* arg)
{

    FILE* predict_data_fp;
    char str_buf[BUF_SIZE];
    printf("Write out predict... %02d:%02d \r\n", local_time_p->tm_hour, local_time_p->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++) {
        // 予測時刻へ変換
        now_time += PREDICT_INTERVAL_TIME;
        local_time_p = localtime(&now_time);
        // 気象を文字列に変換
        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",
                 (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,
                 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_predict_data(new_predict_data, new_predict_weather, new_predict_probability);

}

// 描画スレッド : 優先度低め
void draw_task(void const *arg)
{
    while (true) {

        if (ml_flag) {
            Thread::signal_wait(0x2, osWaitForever);
        }
        //printf("sp : %d, pc : %d \r\n", __current_sp(), __current_pc());

        // 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(1 * 1000);

    }
}


// ネットワークスレッド : リソースの限界. 廃止.
/*
void network_task(void const *arg)
{
    while (true) {
        while (ml_flag) {
            Thread::signal_wait(0x3);
        }
        // 1. ポート80のListen
        http_server->poll();
        // for (int dum = 0; dum < 10000; dum++) ;
        net_led = !net_led;
        // Thread::wait(500);
    }
}
*/

// 生存報告LEDチカ
void liveled_task(void const *arg)
{
    while (true) {
        if (ml_flag) {
            Thread::signal_wait(0x1, osWaitForever);
        }
        // printf("sp : %d, pc : %d \r\n", __current_sp(), __current_pc());

        live_led = !live_led;
        Thread::wait(1000);
    }
}

//
int main(void)
{
    set_new_handler(no_memory);
    local_fs = new LocalFileSystem("local");

    setup();

    // 擬似的なロックをかける(他のスレッドを待ち状態に)
    ml_flag = 1;

    Thread draw_thread(draw_task, NULL, osPriorityNormal, 800);
    Thread liveled_thread(liveled_task, NULL, osPriorityLow, 200);

    osThreadSetPriority(Thread::gettid() ,osPriorityHigh);
    while (true) {
        ml_flag = 1;
        // 現在時刻取得(ロギングに用いる)
        now_time = time(NULL);
        local_time_p = localtime(&now_time);
        // センサ読み込み, 機械学習, 予測データセット
        //read_task(NULL);
        ml_task(NULL);
        write_predict_task(NULL);
        ml_flag = 0;
        // シグナルにより他スレッドの再開
        liveled_thread.signal_set(0x1);
        draw_thread.signal_set(0x2);
        Thread::wait(PREDICT_INTERVAL_TIME);
    }

    error("unreachable here");

}