]> rtime.felk.cvut.cz Git - eurobot/public.git/commitdiff
MCL: Modularized and added Marek's resampling algoritm
authorMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 29 Apr 2008 09:53:37 +0000 (11:53 +0200)
committerMichal Sojka <sojkam1@fel.cvut.cz>
Tue, 29 Apr 2008 09:53:37 +0000 (11:53 +0200)
src/mcl/Makefile.omk
src/mcl/matlab/mcl_test.mdl
src/mcl/matlab/reg_mcl.mdl
src/mcl/matlab/resample.m [new file with mode: 0644]
src/mcl/matlab/sf_mcl.c
src/mcl/mcl.c
src/mcl/mcl.h
src/mcl/mcl_laser.c [new file with mode: 0644]
src/mcl/mcl_laser.h [new file with mode: 0644]
src/mcl/mcl_laser_pos.c [new file with mode: 0644]
src/mcl/test/testmcl_performance.c

index 605cbb4b17c371abb7228047b8ce926c777f882c..7885fa0b988c308a3e9065f6a3675878c343e08a 100644 (file)
@@ -3,10 +3,10 @@
 SUBDIRS = test
 
 lib_LIBRARIES = mcl
-mcl_SOURCES = mcl.c
+mcl_SOURCES = mcl.c mcl_laser.c
 mcl_LIBS = robomath m 
 
-include_HEADERS = mcl.h
+include_HEADERS = mcl.h mcl_laser.h
 
 # -ffast-math is the most important optimization here
 CFLAGS := $(filter-out -fno-strict-aliasing,$(CFLAGS)) --std=c99 -D_GNU_SOURCE -ffast-math -O3 -funroll-loops -ftree-vectorize
index bed00e793e4db8a7accf5a9176d55acdbfa199e4..d5603c7fd1720f63bb12b4a103c16e932b4b4cfe 100644 (file)
@@ -6,7 +6,7 @@ Model {
     NumRootInports         0
     NumRootOutports        0
     ParameterArgumentNames  ""
-    ComputedModelVersion    "1.103"
+    ComputedModelVersion    "1.105"
     NumModelReferences     0
     NumTestPointedSignals   0
   }
@@ -46,8 +46,8 @@ Model {
   ModifiedByFormat       "%<Auto>"
   LastModifiedBy         "wsh"
   ModifiedDateFormat     "%<Auto>"
-  LastModifiedDate       "Mon Apr 28 16:21:59 2008"
-  ModelVersionFormat     "1.%<AutoIncrement:103>"
+  LastModifiedDate       "Tue Apr 29 11:52:05 2008"
+  ModelVersionFormat     "1.%<AutoIncrement:105>"
   ConfigurationManager   "None"
   SimulationMode         "normal"
   LinearizationMsg       "none"
@@ -749,7 +749,7 @@ Model {
   }
   System {
     Name                   "mcl_test"
-    Location               [1684, 55, 2666, 437]
+    Location               [358, 561, 1340, 943]
     Open                   on
     ModelBrowserVisibility  off
     ModelBrowserWidth      200
@@ -826,7 +826,7 @@ Model {
          Position                [410, 109, 440, 141]
          Floating                off
          Location                [475, 726, 1126, 908]
-         Open                    on
+         Open                    off
          NumInputPorts           "1"
          List {
            ListType                AxesTitles
@@ -926,7 +926,7 @@ Model {
          Position                [370, 49, 400, 81]
          Floating                off
          Location                [469, 497, 1123, 665]
-         Open                    on
+         Open                    off
          NumInputPorts           "1"
          ZoomMode                "xonly"
          List {
@@ -1330,12 +1330,12 @@ Model {
       MaskIconOpaque         on
       MaskIconRotate         "none"
       MaskIconUnits          "normalized"
-      MaskValueString        "1|1|on"
+      MaskValueString        "1|0.01|on"
       MaskTabNameString              ",,"
       System {
        Name                    "Rotating laser"
-       Location                [84, 67, 1108, 652]
-       Open                    off
+       Location                [127, 99, 1151, 684]
+       Open                    on
        ModelBrowserVisibility  off
        ModelBrowserWidth       200
        ScreenColor             "white"
@@ -1752,6 +1752,16 @@ Model {
          Position                [735, 19, 775, 61]
          OutPortSampleTime       "1/rps"
        }
+       Block {
+         BlockType               Selector
+         Name                    "Selector"
+         Ports                   [1, 1]
+         Position                [585, 91, 625, 129]
+         IndexOptions            "Index vector (dialog)"
+         Indices                 "[1]"
+         OutputSizes             "1"
+         InputPortWidth          "3"
+       }
        Block {
          BlockType               Sum
          Name                    "Subtract"
@@ -1998,12 +2008,6 @@ Model {
          DstBlock                "Mux"
          DstPort                 3
        }
-       Line {
-         SrcBlock                "Beacon memory1"
-         SrcPort                 1
-         DstBlock                "Mux"
-         DstPort                 2
-       }
        Line {
          SrcBlock                "Beacon memory"
          SrcPort                 1
@@ -2035,12 +2039,11 @@ Model {
          SrcPort                 1
          Points                  [15, 0]
          Branch {
-           Points                  [400, 0]
-           DstBlock                "Individual output"
-           DstPort                 trigger
+           DstBlock                "Demux"
+           DstPort                 1
          }
          Branch {
-           DstBlock                "Demux"
+           DstBlock                "Selector"
            DstPort                 1
          }
        }
@@ -2108,6 +2111,19 @@ Model {
          DstBlock                "Compare\nTo Constant"
          DstPort                 1
        }
+       Line {
+         SrcBlock                "Beacon memory1"
+         SrcPort                 1
+         DstBlock                "Mux"
+         DstPort                 2
+       }
+       Line {
+         SrcBlock                "Selector"
+         SrcPort                 1
+         Points                  [140, 0]
+         DstBlock                "Individual output"
+         DstPort                 trigger
+       }
       }
     }
     Block {
@@ -2126,7 +2142,7 @@ Model {
       RTWMemSecDataInternal   "Inherit from model"
       RTWMemSecDataParameters "Inherit from model"
       low                    "0"
-      gain                   "0"
+      gain                   "232.844"
       high                   "360"
     }
     Block {
@@ -2145,7 +2161,7 @@ Model {
       RTWMemSecDataInternal   "Inherit from model"
       RTWMemSecDataParameters "Inherit from model"
       low                    "0"
-      gain                   "1.5"
+      gain                   "1.47"
       high                   "3"
     }
     Block {
@@ -2164,7 +2180,7 @@ Model {
       RTWMemSecDataInternal   "Inherit from model"
       RTWMemSecDataParameters "Inherit from model"
       low                    "0"
-      gain                   "1.1367"
+      gain                   "1.5087"
       high                   "2.1"
     }
     Block {
index 13ac0ac9cc0d04be132f0034a017431e69643a0c..ad15db2af99277b9a61d11ae1c6a2b6bcc1b8ed7 100644 (file)
@@ -6,7 +6,7 @@ Model {
     NumRootInports         0
     NumRootOutports        0
     ParameterArgumentNames  ""
-    ComputedModelVersion    "1.323"
+    ComputedModelVersion    "1.326"
     NumModelReferences     0
     NumTestPointedSignals   0
   }
@@ -48,8 +48,8 @@ Model {
   ModifiedByFormat       "%<Auto>"
   LastModifiedBy         "wsh"
   ModifiedDateFormat     "%<Auto>"
-  LastModifiedDate       "Mon Apr 28 17:05:34 2008"
-  ModelVersionFormat     "1.%<AutoIncrement:323>"
+  LastModifiedDate       "Tue Apr 29 11:44:26 2008"
+  ModelVersionFormat     "1.%<AutoIncrement:326>"
   ConfigurationManager   "None"
   SimulationMode         "normal"
   LinearizationMsg       "none"
@@ -791,7 +791,7 @@ Model {
   }
   System {
     Name                   "reg_mcl"
-    Location               [1729, 496, 2584, 973]
+    Location               [391, 580, 1246, 1057]
     Open                   on
     ModelBrowserVisibility  off
     ModelBrowserWidth      200
@@ -1177,7 +1177,7 @@ Model {
       MaskIconOpaque         on
       MaskIconRotate         "none"
       MaskIconUnits          "autoscale"
-      MaskValueString        "3000|0.01|3/180*pi|2/180*pi"
+      MaskValueString        "3000|0.01|5/180*pi|10/180*pi"
       MaskTabNameString              ",,,"
       Port {
        PortNumber              1
@@ -1287,7 +1287,7 @@ Model {
       System {
        Name                    "Robot kinematics"
        Location                [4, 55, 1176, 412]
-       Open                    off
+       Open                    on
        ModelBrowserVisibility  off
        ModelBrowserWidth       200
        ScreenColor             "white"
@@ -2665,8 +2665,8 @@ Model {
        set0ParseKeys           "9"
        set0Sigs                "Switch:o1"
       }
-      Location               [6, 687, 330, 1044]
-      Open                   on
+      Location               [6, 641, 330, 998]
+      Open                   off
       NumInputPorts          "1"
       List {
        ListType                AxesTitles
diff --git a/src/mcl/matlab/resample.m b/src/mcl/matlab/resample.m
new file mode 100644 (file)
index 0000000..3159452
--- /dev/null
@@ -0,0 +1,26 @@
+% Demonstration of resample algorithm
+
+clc
+m=[ 1 1 5 1 1] % sample weights
+N=length(m);
+Q=[cumsum(m)]
+Q = Q./Q(N)
+xQ = 1:N;
+T=cumsum(-log(rand(1, N+1)))
+T = T./T(length(T))
+xT = 0:N-1;
+
+plot(xQ,Q, 'bo-', xT,T(1:N),'ro-');
+grid
+
+output=zeros(size(m));
+i=0;  j=1;
+while i<N,
+    if Q(j)>T(i+1),
+        output(i+1)=j;
+        i=i+1;
+    else
+        j=j+1;
+    end
+end
+output
\ No newline at end of file
index c9b395a5fa694b38f3a865df6531a1c692461339..5d4d42b78903bbf1ddf926df1b3ccfc284faf17e 100644 (file)
@@ -14,7 +14,7 @@ extern "C" { /*use the C fcn-call standard for all functions */
 #include "simstruc.h"
 #include "math.h"
 #include "robomath.h"
-#include "mcl.h"
+#include "mcl_laser.h"
 #include "stdbool.h"
 
 
@@ -68,14 +68,14 @@ static void mdlCheckParameters(SimStruct *S)
 #if defined(MDL_CHECK_PARAMETERS)  && defined(MATLAB_MEX_FILE)
 static void mdlProcessParameters(SimStruct *S)
 {
-       struct mcl_model *mcl = ssGetPWork(S)[0];
+       struct mcl_laser *l = ssGetPWork(S)[0];
        printf("%s\n", __FUNCTION__);
        /* Tunable parameters was changed during simulation */
-       if (mcl) {
+       if (l) {
                printf("changing mcl\n");
-               mcl->mov_dnoise = NOISE_XY(S);
-               mcl->mov_anoise = NOISE_ANGLE(S);
-               mcl->aeval_sigma = AEVAL_SIGMA(S);
+               l->pred_dnoise = NOISE_XY(S);
+               l->pred_anoise = NOISE_ANGLE(S);
+               l->aeval_sigma = AEVAL_SIGMA(S);
        }
 }
 #endif
@@ -287,56 +287,28 @@ static void mdlInitializeSampleTimes(SimStruct *S)
    */
 static void mdlStart(SimStruct *S)
 {
-       struct mcl_model *mcl;
-       struct mcl_angles *angles;
+       struct mcl_laser *l;
+       struct mcl_laser_measurement *last_angles;
        void **pwork = ssGetPWork(S);
 
-       mcl = malloc(sizeof(*mcl));
-       memset(mcl, 0, sizeof(*mcl));
-       pwork[0] = (void*)mcl;
+       l = malloc(sizeof(*l));
+       memset(l, 0, sizeof(*l));
+       pwork[0] = (void*)l;
 
-       angles = malloc(sizeof(*angles));
-       memset(angles, 0, sizeof(*angles));
-       pwork[1] = (void*)angles;
+       last_angles = malloc(sizeof(*last_angles));
+       memset(last_angles, 0, sizeof(*last_angles));
+       pwork[1] = (void*)last_angles;
 
        /* MCL initialization */
-       mcl->beacon_cnt = 3;
-       mcl->width = 3.0;       /* in m */
-       mcl->height = 2.1;      /* in m */
+       l->beacon_cnt = 3;
+       l->width = 3.0; /* in m */
+       l->height = 2.1;        /* in m */
        /* the noises */
-       mcl->mov_dnoise = NOISE_XY(S);
-       mcl->mov_anoise = NOISE_ANGLE(S);
-       mcl->w_min = 0.25;
-       mcl->w_max = 2.0;
-       mcl->eval_sigma = 160;
-       mcl->aeval_sigma = AEVAL_SIGMA(S);
-       mcl->maxavdist = 0.150;
-       /* bad cycles before reseting */
-       mcl->maxnoisecycle = 10;
-
-       /* amount of particles */
-       mcl->count = PART_COUNT(S);
-
-       mcl->parts = (struct mcl_particle *) 
-               malloc(sizeof(struct mcl_particle)*mcl->count);
-
-       /* phases of the MCL */
-       mcl->init = mcl_init;
-       mcl->move = mcl_move;
-       mcl->update = mcl_update2; /* angles evalution oriented update */
-       mcl->normalize = mcl_normalize;
-       mcl->sort = mcl_partsort;
-       mcl->resample = mcl_resample;
-
-       /* cycles of enumeration */
-       mcl->cycle = 0;
-       mcl->noisecycle = 0;
-
-       /* change flag */
-       mcl->flag = MCL_RUN;
-
-       /* generate particles with noises */
-       mcl->init(mcl);
+       l->pred_dnoise = NOISE_XY(S);
+       l->pred_anoise = NOISE_ANGLE(S);
+       l->aeval_sigma = AEVAL_SIGMA(S);
+
+       mcl_laser_init(l, PART_COUNT(S));
 }
 #endif /*  MDL_START */
 
@@ -352,23 +324,6 @@ static void mdlUpdate(SimStruct *S, int_T tid)
         ssPrintf("Update %d %g\n", tid, ssGetT(S));
 }
 
-static do_move(struct mcl_model *mcl, InputRealPtrsType iPtrsMove)
-{
-       double dx, dy, dangle;
-       dx = *iPtrsMove[0];
-       dy = *iPtrsMove[1];
-       dangle = *iPtrsMove[2];
-       mcl->move(mcl, dx, dy, dangle);
-}
-
-static do_measure(struct mcl_model *mcl, struct mcl_angles angles)
-{
-       mcl->update(mcl, &angles);
-       mcl->normalize(mcl);
-       mcl->sort(mcl);
-       mcl->resample(mcl);
-}
-
 
 /* Function: mdlOutputs =======================================================
  * Abstract:
@@ -377,9 +332,10 @@ static do_measure(struct mcl_model *mcl, struct mcl_angles angles)
  */
 static void mdlOutputs(SimStruct *S, int_T tid)
 {
-    struct mcl_model *mcl = ssGetPWork(S)[0];
-    struct mcl_angles *last_angles = ssGetPWork(S)[1];
-    struct mcl_particle *parts = (struct mcl_particle *)mcl->parts;
+    struct mcl_laser *l = ssGetPWork(S)[0];
+    struct mcl_model *mcl = &l->mcl;
+    struct mcl_laser_measurement *last_angles = ssGetPWork(S)[1];
+    struct mcl_laser_state *parts = l->parts;
     
     double *pos = ssGetOutputPortRealSignal(S,OUTPUT_EST_POS);
     double *bitmap = ssGetOutputPortRealSignal(S,OUTPUT_BITMAP);
@@ -396,11 +352,15 @@ static void mdlOutputs(SimStruct *S, int_T tid)
 /*     ssPrintf("=============================================\n"); */
     if (ssIsSampleHit(S, moveTid, tid)) {
 /*         ssPrintf("move \n"); */
-           do_move(mcl, iPtrsMove);
-        }
+           struct mcl_laser_state d;
+           d.x = *iPtrsMove[0];
+           d.y = *iPtrsMove[1];
+           d.angle = *iPtrsMove[2];
+           mcl->predict(mcl, &d);
+    }
     
     if (ssIsSampleHit(S, measureTid, tid)) {
-           struct mcl_angles angles;
+           struct mcl_laser_measurement angles;
            int i;
            bool nonzero = false;
            bool changed = false;
@@ -423,7 +383,8 @@ static void mdlOutputs(SimStruct *S, int_T tid)
 /*                 for (i=0; i<angles.count; i++) printf(" a=%5.0f deg", angles.val[i]/M_PI*180); */
 /*                 printf("\n"); */
 
-                   do_measure(mcl, angles);
+                   mcl->update(mcl, &angles);
+                   mcl->resample(mcl);
            }
            *last_angles = angles;
     }
@@ -431,14 +392,17 @@ static void mdlOutputs(SimStruct *S, int_T tid)
     /* Update probability bitmap */
     for (i=0; i<BITMAP_WIDTH*BITMAP_HEIGHT; i++)
            bitmap[i] = 0;
+    double max = 0;
+    for (i=0; i<mcl->count; i++)
+           max = fmax(max, mcl->weight[i]);
     for (i=0; i<mcl->count; i++) {
            int x, y;
            double color;
-           x = parts[i].x / mcl->width * BITMAP_WIDTH;
-           y = parts[i].y / mcl->height * BITMAP_HEIGHT;
+           x = parts[i].x / l->width * BITMAP_WIDTH;
+           y = parts[i].y / l->height * BITMAP_HEIGHT;
            y = BITMAP_HEIGHT - 1 - y;
            if (x>=0 && x<BITMAP_WIDTH && y>=0 && y<BITMAP_HEIGHT) {
-                   color = 64.0*parts[i].weight;
+                   color = 64.0*log(1+mcl->weight[i])/log(1+max);
                    color = fmax(color, 16);
                    bitmap[x*BITMAP_HEIGHT+y] = color;
            }
@@ -446,9 +410,10 @@ static void mdlOutputs(SimStruct *S, int_T tid)
 
     /* get the estimated position */
 /*     ssPrintf("pos: %g %g %g", mcl->est_pos.x, mcl->est_pos.y, mcl->est_pos.angle); */
-    pos[0] = mcl->est_pos.x;
-    pos[1] = mcl->est_pos.y;
-    pos[2] = mcl->est_pos.angle;
+    struct mcl_laser_state *est = mcl->estimated;
+    pos[0] = est->x;
+    pos[1] = est->y;
+    pos[2] = est->angle;
 }                                                
 
 /* Function: mdlTerminate =====================================================
index 41cca5be6f9d957050c3f9a6af6317e581574bcc..2bd5fba09863dd0092219a74e20cf7881e5611e7 100644 (file)
 #endif
 
 /**
- * IMPLEMENTATION OF THE MONTE CARLO ALGORITHM.
+ * IMPLEMENTATION OF THE GENERIC PART OF MONTE CARLO ALGORITHM.
  */
 
-/**
- * The prediction phase:
- * Move particles and add some noise to simulate the real movement.
- *
- * @param  dx          movement in axis X
- * @param  dy          movement in axis Y
- * @param  dangle      turning
- */
-void mcl_move(struct mcl_model *mcl, double dx, double dy, double dangle)
-{
-       struct mcl_particle *parts = (struct mcl_particle *)mcl->parts;
-       /*struct mcl_particle robot = *(struct mcl_particle *)mcl->system;*/
-       int i=0;
-       double xdiff, ydiff, a;
-
-       /* move the particles with noises */
-       for (i=0; i<mcl->count; i++) {
-               double a = parts[i].angle;
-               xdiff = dx*cos(a) - dy*sin(a);
-               ydiff = dy*cos(a) + dx*sin(a);
-
-               parts[i].x += xdiff + mcl->mov_dnoise*gaussian_random();
-               parts[i].y += ydiff + mcl->mov_dnoise*gaussian_random();
-               parts[i].angle += dangle + mcl->mov_anoise*gaussian_random();
-
-               /*printf("x=%f y=%f w=%f r.x=%f r.y=%f\n", 
-                       parts[i].x, parts[i].y, parts[i].weight,
-                       robot.x, robot.y);*/
-       }
-
-       /* Update the last estimated position without noise */
-       a = mcl->est_pos.angle;
-       mcl->est_pos.x += dx*cos(a) - dy*sin(a);
-       mcl->est_pos.y += dx*sin(a) + dy*cos(a);
-       mcl->est_pos.angle += dangle;
-}
-
-/**
- * First method:
- * Evaluation of the position.
- * The update phase:
- * check the distance of predicted and measured states and evaluate
- * particle`s weight.
- *
- * @param  mcl         the MCL model
- * @param  data                measured data (x, y, turning)
+/** 
+ * Initializes ::mcl_model and allocates neccessary memory. Should be
+ * called from implementation init function.
+ * 
+ * @param mcl MCL model structure
+ * @param part_size Size of one particle
+ * @param count The number of particles
  */
-void mcl_update(struct mcl_model *mcl, void *data)
+void mcl_init(struct mcl_model *mcl, unsigned count, void *estimated)
 {
-       struct mcl_particle *parts = (struct mcl_particle *)mcl->parts;
-       double xdiff, ydiff, dist, avdist=0;
-       int i;
-       double x = ((double *)data)[0];
-       double y = ((double *)data)[1];
-       /*double angle = ((double *)data)[2];*/
-
-       /* evaluate the weights of each particle */
-       for (i=0; i<mcl->count; i++) {
-               xdiff = parts[i].x - x;
-               ydiff = parts[i].y - y;
-               dist = fabs(sqrt(xdiff*xdiff + ydiff*ydiff));
-               avdist += dist;
-
-               /* evaluate weights with gaussian probability density */
-               parts[i].weight *= evaluate_gaussian(dist, mcl->eval_sigma);
-       }
-
-       /* adjust the evaluation values */
-       avdist /= mcl->count;
-       if (avdist > mcl->maxavdist) {
-               if (mcl->noisecycle > mcl->maxnoisecycle) {
-                       mcl->flag = MCL_RESET;
-                       return;
-               } else
-                       mcl->noisecycle++;
-       }
+       mcl->count = count;
+       mcl->weight = malloc(count*sizeof(*mcl->weight));
+       mcl->estimated = estimated;
 }
 
-/**
- * Second method:
- * Evalution of the angles between the robot's head and reflectors.
- * The update phase:
- * Evaluate particle's weight using measured angles.
- *
- * @param  mcl         the MCL model
- * @param  data                measured angles (angles[0] is the angles count)
+/** 
+ * Deallocates memory allocated by mcl_init().
+ * 
+ * @param mcl MCL model structure.
  */
-#ifdef MATLAB_MEX_FILE
-#define S_FUNCTION_LEVEL 2
-#define S_FUNCTION_NAME  sf_mcl
-#include "simstruc.h"
-#endif
-
-static inline double gaussian(double val, double sigma)
+void mcl_done(struct mcl_model *mcl)
 {
-       return exp(-0.5 * (val*val / (sigma*sigma)));
-}
-
-
-void mcl_update2(struct mcl_model *mcl, void *data)
-{
-       struct mcl_particle * restrict parts = (struct mcl_particle *)mcl->parts;
-       const struct mcl_angles *angles = (struct mcl_angles*)data;
-       mcl_thetas theta;
-       double p;
-       double diff;
-       int i, it, im;
-
-       /* evaluate the weights of each particle */
-       for (i=0; i<mcl->count; i++) {
-               mcl_pos2ang(&parts[i], theta, mcl->beacon_cnt, mcl->beacon_color);
-               parts[i].weight = 1; /* It seems resample doesn't set weight to 1 */
-
-               if (parts[i].x < 0 || parts[i].x > mcl->width ||
-                   parts[i].y < 0 || parts[i].y > mcl->height) {
-                       /* We cannot be out of playground */
-                       parts[i].weight = 0;
-                       continue;
-               }
-
-               for (im=0; im<angles->count; im++) {
-                       p=0;
-                       for (it=0; it<mcl->beacon_cnt; it++) {
-                               diff = fabs(theta[it] - angles->val[im]);
-                               if (diff > M_PI) diff = 2*M_PI-diff;
-                               p += evaluate_gaussian(diff, 2*mcl->aeval_sigma);
-                       }
-                       parts[i].weight *= p;
-               }
-       }
-
-       /* adjust the evaluation values */
-#if 0  
-//     avdist /= mcl->count;
-//     if (avdist > mcl->maxavdist) {
-//             if (mcl->noisecycle > mcl->maxnoisecycle) {
-//                     mcl->flag = MCL_RESET;
-//                     return;
-//             } else
-//                     mcl->noisecycle++;
-//     }
-#endif
+       free(mcl->weight);
 }
 
 /**
- * Normalize the particles. 
+ * Normalize the particle weights. 
  *
  * @param  mcl         the MCL model
  */
 void mcl_normalize(struct mcl_model *mcl)
 {
-       struct mcl_particle *parts = (struct mcl_particle *)mcl->parts;
-       double gain=0, w=0;
+       double sum=0;
        int i;
 
        for (i=0; i<mcl->count; i++)
-               w += parts[i].weight;
-       gain = mcl->count / w;
-       
-       if (gain <= 0)
-               return;
+               sum += mcl->weight[i];
 
        for (i=0; i<mcl->count; i++)
-               parts[i].weight *= gain;
+               mcl->weight[i] /= sum;
 }
 
-/* Compare function. Used to compare the weight of particles. Sorting is
- * realised with the qsort() function. */
-int compare(const void *a, const void *b)
+#if 0
+void mcl_resample_old(struct mcl_model *mcl)
 {
-       return ((double)(((struct mcl_particle *)a)->weight) > 
-               (double)(((struct mcl_particle *)b)->weight));
-}
-
-/**
- * Sort the particles by the weight.
- *
- * @param  *data               data to be compared
- */
-void mcl_partsort(struct mcl_model *mcl)
-{
-       struct mcl_particle *parts = (struct mcl_particle *)mcl->parts;
-       qsort(parts, mcl->count, sizeof(struct mcl_particle), compare);
-}
-
-/**
- * Resample the particles and eliminate the samples with too low or too 
- * high weights.
- *
- * @param  mcl         the MCL model
- */
-void mcl_resample(struct mcl_model *mcl)
-{
-       struct mcl_particle *parts = (struct mcl_particle *)mcl->parts;
+       void *parts = (struct mcl_particle *)mcl->parts;
        int i, j;
        int i_max=0, i_min=0;
        size_t num = 0;
@@ -269,121 +121,7 @@ void mcl_resample(struct mcl_model *mcl)
        mcl->est_pos.y = best.y;
        mcl->est_pos.angle = best.angle;
 }
-
-/**
- * Generate particles with noises. Initialization of the MCL.
- *
- * @param  mcl         the MCL model
- */
-void mcl_init (struct mcl_model *mcl)
-{
-       struct mcl_particle *parts = (struct mcl_particle *)mcl->parts;
-       int i;
-       
-       /*int xgridsize, ygridsize;*/
-
-       /*
-       ygridsize = (int)sqrt((double)((double)mcl->count*(double)mcl->height/
-                               (double)mcl->width));
-       xgridsize = (int)((double)mcl->width/(double)mcl->height*ygridsize);
-       printf("xgridsize=%d ygridsize=%d\n", xgridsize, ygridsize);*/
-
-       if (mcl->beacon_cnt > BEACON_CNT)
-               mcl->beacon_cnt = BEACON_CNT;
-
-       /* particles initialization */
-       for (i=0; i<mcl->count; i++) {
-               /*xdiff = 5*cos(parts[i].angle) + 5*sin(parts[i].angle);
-               ydiff = 5*cos(parts[i].angle) + 5*sin(parts[i].angle);
-
-               parts[i].x = mcl->system->x + xdiff + 
-                               POS_STDEV_FRAC*xdiff*gaussian_random();
-               parts[i].y = mcl->system->y + ydiff + 
-                               POS_STDEV_FRAC*ydiff*gaussian_random();
-               parts[i].angle += dangle + POS_STDEV_FRAC*dangle*gaussian_random();
-               */
-
-               /* generate particles with noises. Starting weight is 1, as we 
-                * consider that any of the particles could be the right one.
-                */
-               parts[i].x = mcl->xoff + (rand()&0xffff)/65535.0*mcl->width;
-               parts[i].y = mcl->yoff + (rand()&0xffff)/65535.0*mcl->height;
-               parts[i].angle = (rand() % 360)/360.0*(2.0*M_PI);
-               parts[i].weight = 1;
-
-               /*
-               parts[i].x = (i%xgridsize)*(mcl->width/xgridsize)+xgridsize/2;
-               parts[i].y = (i/xgridsize)*(mcl->height/ygridsize);
-               parts[i].angle = rand() % (int)mcl->gen_anoise;
-               parts[i].weight = 1;*/
-
-               /*printf("x=%f, y=%f, a=%f, w=%f\n", 
-                       parts[i].x, parts[i].y, 
-                       parts[i].angle, parts[i].weight);*/
-       }                                
-}
-
-/**
- * Get position of the particle with highest weight.
- *
- * @param  mcl         the MCL model
- */
-inline struct mcl_particle mcl_get_pos(struct mcl_model *mcl)
-{
-       return (((struct mcl_particle *)mcl->parts)[mcl->count-1]);
-}
-
-
-
-/**
- * Convert the position to angles between robot's head and reflectors 
- * (angles sense is counter-clockwise)
- *
- * @param  part                MCL particle
- * @param  theta       Returned angles to reflectors
- * @param  color       beacon color
- * @param  cnt         beacon count
- */
-void mcl_pos2ang(const struct mcl_particle *part,
-                mcl_thetas theta,
-                unsigned char cnt, unsigned char color)
-{
-       double head;
-       int i;
-
-       if (cnt > BEACON_CNT)
-               cnt = BEACON_CNT;
-
-       if (color == BEACON_RED)
-               head = part->angle + M_PI;
-       else
-               head = part->angle;
-
-       head = (head < 0) ? 2*M_PI + head : head;
-
-       /* angles between 0 and reflectors (with center at robot position) */
-       if (color == BEACON_RED) {
-               theta[0] = atan2(BEACON_RED1_Y-part->y, BEACON_RED1_X-part->x);
-               theta[1] = atan2(BEACON_RED2_Y-part->y, BEACON_RED2_X-part->x);
-               theta[2] = atan2(BEACON_RED3_Y-part->y, BEACON_RED3_X-part->x);
-               theta[3] = atan2(BEACON_RED4_Y-part->y, BEACON_RED4_X-part->x);
-       } else {
-               theta[0] = atan2(BEACON_BLUE1_Y-part->y, BEACON_BLUE1_X-part->x);
-               theta[1] = atan2(BEACON_BLUE2_Y-part->y, BEACON_BLUE2_X-part->x);
-               theta[2] = atan2(BEACON_BLUE3_Y-part->y, BEACON_BLUE3_X-part->x);
-               theta[3] = atan2(BEACON_BLUE4_Y-part->y, BEACON_BLUE4_X-part->x);
-       }
-
-       for (i=0; i<cnt; i++) {
-               /* normalize angles */
-               if (theta[i] < 0) theta[i] = 2*M_PI + theta[i];
-               theta[i] = (theta[i]-head < 0) ? 
-                       2*M_PI+theta[i]-head : theta[i]-head;
-       }
-
-       /* sort and store results */
-       qsort(theta, cnt, sizeof(double), cmpd);
-}
+#endif
 
 /**
  * End of the MCL stuffs.
index b8fab2b8c8b0e16f7729c26c896d33a7b7246c3e..90cdc9255d9f680d4b8ad5db66ec3a0990539ae7 100644 (file)
 #ifndef __mcl__
 #define __mcl__
 
-#define POS_STDEV_FRAC         2
-
-#include <robodim_eb2008.h>
-
-/* MCL sample */
-struct mcl_particle {
-       double x;
-       double y;
-       double angle;
-       double weight; 
-};
-
-/* Estimated position */
-struct mcl_position {
-       double x;
-       double y;
-       double angle;
-};
-
-typedef double mcl_thetas[BEACON_CNT];
-
-/* Measured angles */
-struct mcl_angles {
-       int count;
-       double val[10];
-};
+typedef float mcl_weight_t;
 
 struct mcl_model {
        /* operations with particles */
-       void (*init) (struct mcl_model *mcl);
-       void (*move) (struct mcl_model *mcl, double dx, double dy, double dangle);
-       void (*update) (struct mcl_model *mcl, void *data);
-       void (*normalize) (struct mcl_model *mcl);
-       void (*sort) (struct mcl_model *mcl);
+
+       /** Resets particles to the initial (random) state */
+       void (*reset) (struct mcl_model *mcl);
+       /** Prediction step of MCL. Moves particles by delta +
+        * noise. Also updates the estimated field by delta (without
+        * noise). */
+       void (*predict) (struct mcl_model *mcl, void *delta);
+       /** Update step. Sets particle weights acording to the
+        * measurement. Updates estimated field to match the particle
+        * with the highest weight. */
+       void (*update) (struct mcl_model *mcl, void *measurement);
+       /** Normalization and resampling. */
        void (*resample) (struct mcl_model *mcl);
-       struct mcl_position est_pos;
+       /** Deallocates all memory etc. */
+       void (*done) (struct mcl_model *mcl);
+
+       void *estimated; /* current best estimation of state */
+
        /* particles */
-       void *parts;            /* pointer to particles */
        int count;              /* number of particles */
-       /* the system (robot, ...) */
-       void *system;           /* system model */
-       /* noises: movement noise,  */
-       double gen_dnoise;      /* dispersion of distance noise to generate */
-       double gen_anoise;      /* dispersion of angles noise to generate */
-       double mov_dnoise;      /* movement distance noises */
-       double mov_anoise;      /* movement angle noises */
-       /* used to evaluate the particles */
-       double w_min;           /* minimal probability used for resampling */
-       double w_max;           /* maximum probability used for resampling */
-       double eval_sigma;      /* sigma used for evaluating */
-       double aeval_sigma;     /* sigma used for angles evaluating */
-       /* size of the playground (in meters) */
-       double width;
-       double height;
-       double xoff;            /* X offset */
-       double yoff;            /* Y offset */
-       /* counters stuff */
-       int cycle;              /* counter of updated cycles */
-       int noisecycle;         /* counter of noise cycles */
-       /* used to reinitialisation after too many bad measures */
-       int maxnoisecycle;      /* max. number of noise cycles before reinit. */
-       double maxavdist;       /* distance to be considered as noise */
-       unsigned char flag;     /* program flag, see below */
-       /* measured data */
-       void *data;
-       unsigned char beacon_cnt;       /* number of beacons */
-       unsigned char beacon_color;     /* red/blue beacons */
-};
-
-enum {
-       MCL_STOP = 0,
-       MCL_RUN = 1,
-       MCL_RESET = 255
+       mcl_weight_t *weight;   /* pointer to particle weights */
+       void *priv;             /* private data for implementation */
 };
 
 /**
@@ -96,18 +49,10 @@ enum {
  */
 #ifdef __cplusplus
 extern "C" {
-#endif 
-void mcl_move(struct mcl_model *mcl, double dx, double dy, double dangle);
-void mcl_update(struct mcl_model *mcl, void *data);
-void mcl_update2(struct mcl_model *mcl, void *data);
+#endif
+void mcl_init(struct mcl_model *mcl, unsigned count, void *estimated);
+void mcl_done(struct mcl_model *mcl);
 void mcl_normalize(struct mcl_model *mcl);
-void mcl_partsort(struct mcl_model *mcl);
-void mcl_resample(struct mcl_model *mcl);
-void mcl_init (struct mcl_model *mcl);
-inline struct mcl_particle mcl_get_pos(struct mcl_model *mcl);
-void mcl_pos2ang(const struct mcl_particle *part,
-                mcl_thetas theta,
-                unsigned char cnt, unsigned char color);
 #ifdef __cplusplus
 }
 #endif 
diff --git a/src/mcl/mcl_laser.c b/src/mcl/mcl_laser.c
new file mode 100644 (file)
index 0000000..8eadcce
--- /dev/null
@@ -0,0 +1,262 @@
+#include "mcl_laser.h"
+#include <stdlib.h>
+#include <math.h>
+#include <robomath.h>
+
+#define mcl_to_laser(mcl) (struct mcl_laser*)((mcl)->priv)
+
+#ifdef MATLAB_MEX_FILE
+#define S_FUNCTION_LEVEL 2
+#define S_FUNCTION_NAME  sf_mcl
+#include "simstruc.h"
+#endif
+
+
+static void mcl_laser_reset(struct mcl_model *mcl)
+{
+       struct mcl_laser *l = mcl_to_laser(mcl);
+       struct mcl_laser_state *parts = l->parts;
+       int i;
+       
+       if (l->beacon_cnt > BEACON_CNT)
+               l->beacon_cnt = BEACON_CNT;
+
+       /* particles initialization */
+       for (i=0; i<mcl->count; i++) {
+               /* generate particles with noises. Starting weight is 1, as we 
+                * consider that any of the particles could be the right one.
+                */
+               parts[i].x = (rand()&0xffff)/65535.0*l->width;
+               parts[i].y = (rand()&0xffff)/65535.0*l->height;
+               parts[i].angle = (rand() % 360)/360.0*(2.0*M_PI);
+       }                                
+
+}
+
+static void mcl_laser_predict(struct mcl_model *mcl, void *delta)
+{
+       struct mcl_laser *l = mcl_to_laser(mcl);
+       struct mcl_laser_state *parts = l->parts;
+       struct mcl_laser_state *d = delta;
+       struct mcl_laser_state *estimated = mcl->estimated;
+       
+       int i=0;
+       double xdiff, ydiff, a;
+
+       /* move the particles with noises */
+       for (i=0; i<mcl->count; i++) {
+               double a = parts[i].angle;
+               xdiff = d->x*cos(a) - d->y*sin(a);
+               ydiff = d->y*cos(a) + d->x*sin(a);
+
+               parts[i].x += xdiff + l->pred_dnoise*gaussian_random();
+               parts[i].y += ydiff + l->pred_dnoise*gaussian_random();
+               parts[i].angle += d->angle + l->pred_anoise*gaussian_random();
+
+               /*printf("x=%f y=%f w=%f r.x=%f r.y=%f\n", 
+                       parts[i].x, parts[i].y, parts[i].weight,
+                       robot.x, robot.y);*/
+       }
+
+       /* Update the last estimated position without noise */
+       a = estimated->angle;
+       estimated->x += d->x*cos(a) - d->y*sin(a);
+       estimated->y += d->x*sin(a) + d->y*cos(a);
+       estimated->angle += d->angle;
+}
+
+static inline double gaussian(double val, double sigma)
+{
+       return exp(-0.5 * (val*val / (sigma*sigma)));
+}
+
+
+static void mcl_laser_update(struct mcl_model *mcl, void *measurement)
+{
+       struct mcl_laser *l = mcl_to_laser(mcl);
+       const struct mcl_laser_state * restrict parts = l->parts;
+       const struct mcl_laser_state * restrict best = &parts[0];
+       const struct mcl_laser_measurement *angles = measurement;
+       mcl_thetas theta;
+       double p;
+       double diff;
+       int i, it, im;
+       mcl_weight_t wmax = 0;
+
+       /* evaluate the weights of each particle */
+       for (i=0; i<mcl->count; i++) {
+               mcl_pos2ang(&parts[i], theta, l->beacon_cnt, l->beacon_color);
+               if (parts[i].x < 0 || parts[i].x > l->width ||
+                   parts[i].y < 0 || parts[i].y > l->height) {
+                       /* We cannot be out of playground */
+                       mcl->weight[i] = 0;
+                       continue;
+               }
+
+               mcl->weight[i] = 1;
+               for (im=0; im<angles->count; im++) {
+                       p=0;
+                       for (it=0; it<l->beacon_cnt; it++) {
+                               diff = fabs(theta[it] - angles->val[im]);
+                               if (diff > M_PI) diff = 2*M_PI-diff;
+                               p += gaussian(diff, 2*l->aeval_sigma);
+                       }
+                       mcl->weight[i] *= p;
+               }
+               if (mcl->weight[i] > wmax) {
+                       wmax = mcl->weight[i];
+                       best = &parts[i];
+               }
+       }
+       *(struct mcl_laser_state*)mcl->estimated = *best;
+}
+
+
+static inline double rnd()
+{
+       return 1 - drand48();   /* exclude zero */
+}
+
+/**
+ * Resample the particles. Mystic alg. 1 from "Improved particle
+ * filter for nonlinear problems".
+ *
+ * @note It already contains normalization so it is not neccessary to
+ * call mcl_normalize().
+ *
+ * @param  mcl         the MCL model
+ */
+static void mcl_laser_resample(struct mcl_model *mcl)
+{
+       struct mcl_laser *l = mcl_to_laser(mcl);
+       struct mcl_laser_state *parts = l->parts;
+       struct mcl_laser_state *resampled = l->resampled;
+       mcl_weight_t *Q = l->Q, *T=l->T, *weight = mcl->weight;
+
+       float sum;
+       int i, j;
+
+       /* Q is shifted one element to the left sice the initial zero
+        * is never accessed. */
+       Q[0] = weight[0];
+       for (i = 1; i <= mcl->count; i++)
+               Q[i] = Q[i-1] + weight[i];
+       
+       /* We normalize here since Q should be now in cache and we
+        * also save one pass as compared to standalone
+        * mcl_normalize(). */
+       sum = Q[mcl->count];
+       for (i = 1; i <= mcl->count; i++)
+               Q[i] /= sum;
+
+       /* We do not store the last element of T since it is always
+        * one and during resample loop this element is never
+        * reached. */
+       T[0] = -log(rnd());
+       for (i = 1; i < mcl->count; i++)
+               T[i] = T[i-1] - log(rnd());
+       sum = T[mcl->count-1] - log(rnd());
+       for (i = 0; i < mcl->count; i++)
+               T[i] /= sum;
+
+       for (i = 0, j = 0; i < mcl->count; ) {
+               if (Q[j] > T[i]) {
+                       resampled[i] = parts[j];
+                       ++i;
+               }
+               else
+                       ++j;
+       }
+
+       /* Swap resampled and non-resampled particles */
+       l->parts = resampled;
+       l->resampled = parts;
+}
+
+void mcl_laser_done(struct mcl_model *mcl)
+{
+       struct mcl_laser *l = mcl_to_laser(mcl);
+
+       mcl_done(mcl);
+       free(l->parts);
+       free(l->resampled);
+       free(l->Q);
+       free(l->T);
+}
+
+
+struct mcl_model *mcl_laser_init(struct mcl_laser *l, unsigned count)
+{
+       struct mcl_model *mcl = &l->mcl;
+
+       mcl_init(mcl, count, &l->estimated);
+       mcl->priv = l;
+
+       l->parts = malloc(count*sizeof(struct mcl_laser_state));
+       l->resampled = malloc(count*sizeof(struct mcl_laser_state));
+       l->Q = malloc(count*sizeof(*l->Q));
+       l->T = malloc(count*sizeof(*l->T));
+
+       if (l->beacon_cnt > BEACON_CNT)
+               l->beacon_cnt = BEACON_CNT;
+
+       /* Initialize method pointers */
+       mcl->reset = mcl_laser_reset;
+       mcl->predict = mcl_laser_predict;
+       mcl->update = mcl_laser_update;
+       mcl->resample = mcl_laser_resample;
+       mcl->done = mcl_laser_done;
+
+       mcl_laser_reset(mcl);
+       return mcl;
+}
+
+/**
+ * Convert the position to angles between robot's head and reflectors 
+ * (angles sense is counter-clockwise)
+ *
+ * @param  part                MCL particle
+ * @param  theta       Returned angles to reflectors
+ * @param  color       beacon color
+ * @param  cnt         beacon count
+ */
+void mcl_pos2ang(const struct mcl_laser_state *part,
+                mcl_thetas theta,
+                unsigned char cnt, unsigned char color)
+{
+       double head;
+       int i;
+
+       if (cnt > BEACON_CNT)
+               cnt = BEACON_CNT;
+
+       if (color == BEACON_RED)
+               head = part->angle + M_PI;
+       else
+               head = part->angle;
+
+       head = (head < 0) ? 2*M_PI + head : head;
+
+       /* angles between 0 and reflectors (with center at robot position) */
+       if (color == BEACON_RED) {
+               theta[0] = atan2(BEACON_RED1_Y-part->y, BEACON_RED1_X-part->x);
+               theta[1] = atan2(BEACON_RED2_Y-part->y, BEACON_RED2_X-part->x);
+               theta[2] = atan2(BEACON_RED3_Y-part->y, BEACON_RED3_X-part->x);
+               theta[3] = atan2(BEACON_RED4_Y-part->y, BEACON_RED4_X-part->x);
+       } else {
+               theta[0] = atan2(BEACON_BLUE1_Y-part->y, BEACON_BLUE1_X-part->x);
+               theta[1] = atan2(BEACON_BLUE2_Y-part->y, BEACON_BLUE2_X-part->x);
+               theta[2] = atan2(BEACON_BLUE3_Y-part->y, BEACON_BLUE3_X-part->x);
+               theta[3] = atan2(BEACON_BLUE4_Y-part->y, BEACON_BLUE4_X-part->x);
+       }
+
+       for (i=0; i<cnt; i++) {
+               /* normalize angles */
+               if (theta[i] < 0) theta[i] = 2*M_PI + theta[i];
+               theta[i] = (theta[i]-head < 0) ? 
+                       2*M_PI+theta[i]-head : theta[i]-head;
+       }
+
+       /* sort and store results */
+       qsort(theta, cnt, sizeof(double), cmpd);
+}
diff --git a/src/mcl/mcl_laser.h b/src/mcl/mcl_laser.h
new file mode 100644 (file)
index 0000000..4ab0772
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef MCL_LASER_H
+#define MCL_LASER_H
+
+#include <mcl.h>
+#include <robodim_eb2008.h>
+
+#define MCL_LASER_MAX_MEASURE 10
+
+struct mcl_laser_state {
+       double x;
+       double y;
+       double angle;
+};
+
+struct mcl_laser_measurement {
+       int count;
+       double val[MCL_LASER_MAX_MEASURE];
+};
+
+typedef double mcl_thetas[BEACON_CNT];
+
+struct mcl_laser {
+       struct mcl_model mcl;
+       struct mcl_laser_state *parts;          /* pointer to particles */
+       struct mcl_laser_state estimated;       /* current best estimated position */
+       /* the system (robot, ...) */
+       void *system;           /* system model */
+       /* noises: movement noise,  */
+       double pred_dnoise;     /* prediction distance noises */
+       double pred_anoise;     /* prediction angle noises */
+       /* used to evaluate the particles */
+       double aeval_sigma;     /* sigma used for angles evaluating */
+       /* size of the playground (in meters) */
+       double width;
+       double height;
+#if 0
+       /* counters stuff */
+       int cycle;              /* counter of updated cycles */
+       int noisecycle;         /* counter of noise cycles */
+       /* used to reinitialisation after too many bad measures */
+       int maxnoisecycle;      /* max. number of noise cycles before reinit. */
+       double maxavdist;       /* distance to be considered as noise */
+       unsigned char flag;     /* program flag, see below */
+       /* measured data */
+       void *data;
+#endif 
+       unsigned char beacon_cnt;       /* number of beacons */
+       unsigned char beacon_color;     /* red/blue beacons */
+
+       /* Temporary arrays for resampling */
+       mcl_weight_t *Q, *T;
+       struct mcl_laser_state *resampled;
+};
+
+
+struct mcl_model *mcl_laser_init(struct mcl_laser *l, unsigned count);
+
+void mcl_pos2ang(const struct mcl_laser_state *part,
+                mcl_thetas theta,
+                unsigned char cnt, unsigned char color);
+
+#endif
diff --git a/src/mcl/mcl_laser_pos.c b/src/mcl/mcl_laser_pos.c
new file mode 100644 (file)
index 0000000..6db47fd
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * First method:
+ * Evaluation of the position.
+ * The update phase:
+ * check the distance of predicted and measured states and evaluate
+ * particle`s weight.
+ *
+ * @param  mcl         the MCL model
+ * @param  data                measured data (x, y, turning)
+ */
+void mcl_laser_pos(struct mcl_model *mcl, void *data)
+{
+       struct mcl_particle *parts = (struct mcl_particle *)mcl->parts;
+       double xdiff, ydiff, dist, avdist=0;
+       int i;
+       double x = ((double *)data)[0];
+       double y = ((double *)data)[1];
+       /*double angle = ((double *)data)[2];*/
+
+       /* evaluate the weights of each particle */
+       for (i=0; i<mcl->count; i++) {
+               xdiff = parts[i].x - x;
+               ydiff = parts[i].y - y;
+               dist = fabs(sqrt(xdiff*xdiff + ydiff*ydiff));
+               avdist += dist;
+
+               /* evaluate weights with gaussian probability density */
+               parts[i].weight *= evaluate_gaussian(dist, mcl->eval_sigma);
+       }
+
+       /* adjust the evaluation values */
+       avdist /= mcl->count;
+       if (avdist > mcl->maxavdist) {
+               if (mcl->noisecycle > mcl->maxnoisecycle) {
+                       mcl->flag = MCL_RESET;
+                       return;
+               } else
+                       mcl->noisecycle++;
+       }
+}
+
index 22118f18cf87ae20a9ffe78d6582891fb2e1807b..908beb6eb25766eaddc19643dac706ea022b83ec 100644 (file)
@@ -13,7 +13,7 @@
 #include <stdlib.h>
 #include <time.h>
 #include <sys/time.h>
-#include <mcl.h>
+#include <mcl_laser.h>
 #include <math.h>
 #include <robomath.h>
 #include <robodim_eb2007.h>
 #define HIST_MIN 0.000001
 #define HIST_MAX 1.0
 
-struct mcl_model mcl;
-struct mcl_angles meas_angles;
-struct mcl_particle act_pos;
-struct mcl_particle est_pos;
-struct mcl_particle meas_pos;
-mcl_thetas theta;
-struct mcl_particle *parts;
+struct mcl_laser l;
+struct mcl_model *mcl;
 
 /**
  * MCL test initialization
@@ -39,48 +34,18 @@ struct mcl_particle *parts;
 void testmcl_init()
 {
        /* MCL initialization */
-       mcl.width = PLAYGROUND_WIDTH_M; /* in meters */
-       mcl.height = PLAYGROUND_HEIGHT_M; /* in meters */
+       l.width = PLAYGROUND_WIDTH_M;   /* in meters */
+       l.height = PLAYGROUND_HEIGHT_M; /* in meters */
        /* the noises */
-       mcl.gen_dnoise = 0.99;
-       mcl.gen_anoise = 360;
-       mcl.mov_dnoise = 0.003;
-       mcl.mov_anoise = 0.03;
-       mcl.w_min = 0.25;
-       mcl.w_max = 2.0;
-       mcl.eval_sigma = 160;
-       mcl.aeval_sigma = 0.90;
-       mcl.maxavdist = 0.150;
-       /* bad cycles before reseting */
-       mcl.maxnoisecycle = 10;
-
-       /* amount of particles */
-       mcl.count = 5000;
-       mcl.parts = (struct mcl_particle *)
-                       malloc(sizeof(struct mcl_particle)*mcl.count);
-
-       /* phases of the MCL */
-       mcl.init = mcl_init;
-       mcl.move = mcl_move;
-       /* style of particles evaluation */
-       mcl.update = mcl_update2;
-       mcl.data = &meas_angles;
-       mcl.beacon_cnt = BEACON_CNT;
-       mcl.beacon_color = BEACON_BLUE;
-
-       mcl.normalize = mcl_normalize;
-       mcl.sort = mcl_partsort;
-       mcl.resample = mcl_resample;
-
-       /* cycles of enumeration */
-       mcl.cycle = 0;
-       mcl.noisecycle = 0;
-
-       /* change flag */
-       mcl.flag = MCL_RUN;
-
-       /* generate particles with noises */
-       mcl.init(&mcl);
+       l.pred_dnoise = 0.003;
+       l.pred_anoise = 0.03;
+       l.aeval_sigma = 0.90;
+
+       l.beacon_cnt = BEACON_CNT;
+       l.beacon_color = BEACON_BLUE;
+
+       /* Initialize with 5000 particles */
+       mcl = mcl_laser_init(&l, 5000);
 }
 
 int main(int argc, char *argv[])
@@ -90,7 +55,11 @@ int main(int argc, char *argv[])
        struct timespec ts_start;       
        struct timespec ts_middle;
        double t;
-       double dx, dy, da;
+       struct mcl_laser_measurement meas_angles;
+       struct mcl_laser_state delta = {.x=0.001, .y=0.001, .angle=0};
+       struct mcl_laser_state *est_pos;
+       struct mcl_laser_state meas_pos;
+       mcl_thetas theta;
        int i;
 
        /* histogram parameters */
@@ -109,50 +78,27 @@ int main(int argc, char *argv[])
 
        /* mcl init */
        testmcl_init();
-       parts = (struct mcl_particle *)mcl.parts;
-
-       /* starting position */
-       act_pos.x = 1.000;      /* in meters */
-       act_pos.y = 1.000;      /* in meters */
-
-       /* movement */
-       dx = 0.001;
-       dy = 0.001;
-       da = 0.0;
 
        meas_pos.x = 1.0;
        meas_pos.y = 1.0;
        meas_pos.angle = DEG2RAD(180);
-       mcl_pos2ang(&meas_pos, theta, mcl.beacon_cnt, mcl.beacon_cnt);
-       meas_angles.count = mcl.beacon_cnt;
-       for(i=0; i<mcl.beacon_cnt; i++)
+       mcl_pos2ang(&meas_pos, theta, l.beacon_cnt, l.beacon_cnt);
+       meas_angles.count = l.beacon_cnt;
+       for(i=0; i<l.beacon_cnt; i++)
                meas_angles.val[i] = theta[i];
 
-/*     printf("meas: x=%g y=%g angle=%g w=%g th1=%g th2=%g th3=%g\n",
-               meas_pos.x, meas_pos.y, meas_pos.angle,
-               meas_pos.weight, 
-               meas_pos.theta[0], meas_pos.theta[1], meas_pos.theta[2]);*/
-/*     for (i=0; i<mcl.count; i++) {
-               printf("%d x=%g y=%g angle=%g w=%g th1=%g th2=%g th3=%g\n",
-                       i, 
-                       parts[i].x, parts[i].y, parts[i].angle,
-                       parts[i].weight, 
-                       parts[i].theta[0], parts[i].theta[1], parts[i].theta[2]);
-       }*/
 
        /* Main boucle */
        for(i=1; i<TEST_COUNT; i++) {
                /* time measurement */
                clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts_start);
-               mcl.move(&mcl, dx, dy, da);
+               mcl->predict(mcl, &delta);
                clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts_middle);
-               mcl.update(&mcl, mcl.data);
-               mcl.normalize(&mcl);
-               mcl.sort(&mcl);
-               mcl.resample(&mcl);
+               mcl->update(mcl, &meas_angles);
+               mcl->resample(mcl);
                clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts_finish);
                /* time measurement */
-               est_pos = mcl_get_pos(&mcl);
+               est_pos = mcl->estimated;
 
                t = (double)(ts_finish.tv_nsec - ts_start.tv_nsec) / 1000000000.0;
                t += (ts_finish.tv_sec - ts_start.tv_sec);