kalman.cpp

Kalman Filter example in c++ - Gijs Molenaar, 2010-05-03 07:57 pm

Download (3.6 kB)

 
1
//   Tracking of rotating point.
2
//   Rotation speed is constant.
3
//   Both state and measurements vectors are 1D (a point angle),
4
//   Measurement is the real point angle + gaussian noise.
5
//   The real and the estimated points are connected with yellow line segment,
6
//   the real and the measured points are connected with red line segment.
7
//   (if Kalman filter works correctly,
8
//    the yellow segment should be shorter than the red one).
9
//   Pressing any key (except ESC) will reset the tracking with a different speed.
10
//   Pressing ESC will stop the program.
11
12
13
#include "cv.h"
14
#include "highgui.h"
15
16
using namespace cv;
17
18
19
Point calc_point(Mat& img, double angle) {
20
    int x = round(img.cols/2 + img.rows/3*cos(angle));
21
    int y = round(img.cols/2 - img.rows/3*sin(angle));
22
    return Point(x, y);
23
};
24
25
26
void draw_cross(Mat& img, Point center, Scalar color, int d) {
27
    line(img, Point(center.x - d, center.y - d),
28
                 Point(center.x + d, center.y + d), color, 1, CV_AA, 0);
29
    line(img, Point(center.x + d, center.y - d),
30
                 Point(center.x - d, center.y + d), color, 1, CV_AA, 0);
31
};
32
33
34
int main (int argc, char * const argv[]) {
35
    Mat img = Mat(500, 500, CV_8UC3);
36
    KalmanFilter kalman = KalmanFilter(2, 1, 0);
37
    Mat state = Mat(2, 1, CV_32FC1);  // (phi, delta_phi)
38
    Mat process_noise = Mat(2, 1, CV_32FC1);
39
    Mat measurement = Mat(1, 1, CV_32FC1);
40
    Mat measurement_noise = Mat(1, 1, CV_32FC1);
41
42
    measurement.setTo(Scalar(0));
43
    namedWindow("kalman", 1);
44
45
    float m[2][2] = {{1, 1}, {0, 1}};
46
    kalman.transitionMatrix = Mat(2, 2, CV_32FC1, m);
47
48
    setIdentity(kalman.measurementMatrix, Scalar(1));
49
    setIdentity(kalman.processNoiseCov, Scalar(1e-5));
50
    setIdentity(kalman.measurementNoiseCov, Scalar(1e-1));
51
    setIdentity(kalman.errorCovPost, Scalar(1));
52
53
    int code = -1;
54
    
55
    while (true) {
56
        randu(state, Scalar(0), Scalar(0.1));
57
        randu(kalman.statePost, Scalar(0), Scalar(0.1));
58
59
        while (true) {
60
            img.setTo(Scalar(0));
61
62
            float state_angle = state.at<float>(0,0);
63
            Point state_pt = calc_point(img, state_angle);
64
65
            // predict a measurement
66
            Mat prediction = kalman.predict();
67
            float predict_angle = prediction.at<float>(0, 0);
68
            Point predict_pt = calc_point(img, predict_angle);
69
70
            // generate measurement with measurement noise
71
            randn(measurement_noise, Scalar(0), Scalar(sqrt(kalman.measurementNoiseCov.at<float>(0, 0))));
72
            measurement = kalman.measurementMatrix * state + measurement_noise;
73
74
            float measurement_angle = measurement.at<float>(0, 0);
75
            Point measurement_pt = calc_point(img, measurement_angle);
76
77
            // draw stuff
78
            line(img, state_pt, measurement_pt, CV_RGB(255, 0,0), 3,  CV_AA, 0);
79
            line(img, state_pt, predict_pt, CV_RGB(255, 255, 0), 3,  CV_AA, 0);
80
            draw_cross(img, state_pt, CV_RGB(255, 255, 255), 3);
81
            draw_cross(img, measurement_pt, CV_RGB(255, 0,0), 3);
82
            draw_cross(img, predict_pt, CV_RGB(0, 255, 0), 3);
83
84
            // correct kalman internal state with measurement
85
            kalman.correct(measurement);
86
87
            // update state
88
            randn(process_noise, Scalar(0), Scalar(sqrt(kalman.processNoiseCov.at<float>(0, 0))));
89
            state = kalman.transitionMatrix * state + process_noise;
90
91
            imshow("kalman", img);
92
            code = waitKey(100);
93
            if (code > -1)
94
                break;
95
        };
96
97
        if (code == 27 || code == 113 || code == 65617)
98
            break;
99
    };
100
};