-
Notifications
You must be signed in to change notification settings - Fork 2
/
Form1.cs
220 lines (184 loc) · 6.33 KB
/
Form1.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*
Particle Filter Demo and Visualization tool
Created while studying the CS373 course at UdaCity (www.udacity.com)
Author: Moustafa Alzantot ([email protected])
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace FastSLAM
{
public partial class Form1 : Form
{
int numParticles = 10000;
double step_size = 0.15;
double step_noise = 0.02;
double theta = 0;
double theta_noise = Math.PI / 2;
private Boolean stop;
private Random rand= new Random();
public Form1()
{
InitializeComponent();
txtNumParticles.Text = numParticles + "" ;
txtStepSize.Text = step_size + "";
txtOrientation.Text = (theta * 180.0 / Math.PI) + "";
txtOrientationNoise.Text = (theta_noise * 180.0 / Math.PI) + "";
txtStepNoise.Text = step_noise + "";
particles_initialize();
}
private void button1_Click(object sender, EventArgs e)
{
particles_initialize();
}
void animate()
{
while (!stop)
{
step_forward();
Thread.Sleep(50);
}
panel1.Invalidate();
}
private void button2_Click(object sender, EventArgs e)
{
stop = false;
new Thread(animate).Start();
}
private void button3_Click(object sender, EventArgs e)
{
stop = true;
}
private void btnStep_Click(object sender, EventArgs e)
{
step_forward();
}
private double get_weight(Particle p)
{
if (rbEqual.Checked)
{
// equal weights for all
return 1.0;
}
if (rbRandom.Checked)
{
return rand.NextDouble();
}
if (rbRight.Checked)
{
return (1.0 / (1.0 - p.X));
}
if (rbTop.Checked)
return (1 / p.Y);
// diagonal
return ( 1.0 / Math.Abs(p.X - p.Y));
}
private void step_forward()
{
ArrayList particles = new ArrayList();
// Move
for (int i = 0; i < numParticles; i++)
{
Particle p = (Particle)panel1.particles[i];
double nr = step_size + gauss(0, step_noise);
double ntheta = theta + gauss(0, theta_noise);
double new_x = p.X + nr * Math.Cos(ntheta);
new_x = new_x > 1.0 ? new_x - 1.0 : new_x;
double new_y = p.Y + nr * Math.Sin(ntheta);
new_y = new_y > 1.0 ? new_y - 1.0 : new_y;
particles.Add(new Particle { X = new_x, Y = new_y });
}
// Assign Weights
double [] weights = new double[numParticles];
for (int i =0; i < numParticles; i++) {
Particle p = (Particle) particles[i];
weights[i] = get_weight(p);
}
double noramlizer = 0.0;
for (int i = 0; i < numParticles; i++)
{
noramlizer += weights[i];
}
for (int i = 0; i < numParticles; i++)
{
weights[i] = weights[i] / noramlizer;
}
// resample
ArrayList p2 = new ArrayList();
double maxw = weights[0];
for (int i = 1; i < numParticles; i++) {
if (weights[i] > maxw)
maxw = weights[i];
}
int index = rand.Next(numParticles);
double betta = 0;
for (int i = 0; i < numParticles; i++)
{
betta += rand.NextDouble() * 2.0 * maxw;
while (betta > weights[index])
{
betta -= weights[index];
index = (index + 1) % numParticles;
}
p2.Add(particles[index]);
}
particles = p2;
panel1.particles = particles;
panel1.Invalidate();
}
private double gauss(double mean, double stdDev)
{
double u1 = rand.NextDouble(); //these are uniform(0,1) random doubles
double u2 = rand.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
double randNormal =
mean + Math.Sqrt(stdDev)* randStdNormal; //random normal(mean,stdDev^2)
return randNormal;
}
private void particles_initialize()
{
ArrayList particles = new ArrayList();
Random rnd = new Random();
for (int i = 0; i < numParticles; i++)
{
double x = 0.5;
double y = 0.5;
particles.Add(new Particle { X = x, Y = y });
}
// MessageBox.Show(particles.Count + " ");
panel1.particles = particles;
panel1.Invalidate();
}
private void re_initialize()
{
try{
int numParticles = Int32.Parse(txtNumParticles.Text);
double stepSize = double.Parse(txtStepSize.Text);
double stepNoise = double.Parse(txtStepNoise.Text);
double theta = double.Parse(txtOrientation.Text) * Math.PI / 180.0;
double theta_noise = double.Parse(txtOrientationNoise.Text) * Math.PI / 180.0;
this.numParticles = numParticles;
this.step_size = stepSize;
this.theta = theta;
this.step_noise = stepNoise;
this.theta_noise = theta_noise;
particles_initialize();
}catch( Exception ex) {
MessageBox.Show("Error in data : " + ex.Message);
}
}
private void text_configuration_updated(object sender, EventArgs e)
{
stop = true;
re_initialize();
}
}
}