]> rtime.felk.cvut.cz Git - eurobot/public.git/blobdiff - src/camera/rozkuk/rozkuk.cxx
If the game_color is changed during recognition, load appropriate masks.
[eurobot/public.git] / src / camera / rozkuk / rozkuk.cxx
index 876b677147087a69aa2c1ee2db7d514fe28c2d3b..cc2d30d1456594293201715b8322c6b9744cf0f7 100644 (file)
@@ -8,7 +8,6 @@
  * 
  ******************************************************************************/
 
-extern "C" {
 #include <inttypes.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -17,132 +16,194 @@ extern "C" {
 #include <getopt.h>
 #include <unistd.h>
 
-#include <orte.h>
-//#include "roboorte.h"
-//#include "rozkorte.h"
-}
-
 #include <opencv/cv.h>
 #include <opencv/highgui.h>
 
 #include "clr2float.h"
+#include "masks_globals.h"
+#include "t_decision_box.h"
 
+extern "C" {
+#include <roboorte_robottype.h>
+#include <robot.h>
+}
 /******************************************************************************/
 
+// uncomment next line to "log" the output frames - save them as pnm to the working directory
+//#define PPC_DEBUG
+
 // modes definitions
-#define MODE_QUIT                                      0x01
-#define MODE_REALTIME                  0x02
-#define MODE_RECOGNIZE         0x04
+#define MODE_QUIT         0x01
+#define MODE_REALTIME     0x02
+#define MODE_RECOGNIZE    0x04
+#define MODE_WAIT         0x08
 
 // mask of all modes / errors
-#define MASK_MODES                             0x07
-#define MASK_ERRORS                            (~MASK_MODES)
+#define MASK_MODES        0x0F
+#define MASK_ERRORS       (~MASK_MODES)
 
 // errors
-#define ERR_MASK_READ_FAILURE  0x08
+#define ERR_MASK_READ_FAILURE 0x10
 
-// default mode in standard session
-#define START_MODE                             MODE_RECOGNIZE
+// default mode in standard session (i.e. on ppc)
+#define START_MODE        MODE_WAIT
 
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
 
-// default mode in debug session
+// default mode in debug session (i.e. on pc)
 #undef START_MODE
-#define START_MODE                             MODE_REALTIME
+#define START_MODE        MODE_REALTIME
 
 // highgui windows names
-#define WINDOW_ORIG                            "ROZKUK original scene"
-#define WINDOW_THRES                   "ROZKUK threshold"
-#define WINDOW_MASK                            "ROZKUK mask"
-#define WINDOW_PROD                            "ROZKUK product"
+#define WINDOW_ORIG       "ROZKUK original scene"
+#define WINDOW_THRES      "ROZKUK threshold"
+#define WINDOW_MASK       "ROZKUK mask"
+#define WINDOW_PROD       "ROZKUK product"
 
 // values of keys
-#define KEY_ESC                                                0x1B
-#define KEY_SPACE                                      0x20
-#define KEY_P                                                  0x50
-#define KEY_R                                                  0x52
-#define KEY_S                                                  0x53
-#define KEY_p                                                  0x70
-#define KEY_r                                                  0x72
-#define KEY_s                                                  0x73
+#define KEY_ESC           0x1B
+#define KEY_SPACE         0x20
+#define KEY_P             0x50
+#define KEY_R             0x52
+#define KEY_S             0x53
+#define KEY_W             0x57
+#define KEY_p             0x70
+#define KEY_r             0x72
+#define KEY_s             0x73
+#define KEY_w             0x77
 
 // number of frames passed in rozkuk mode before refresh
-#define PASS_FRAMES                            0
+#define PASS_FRAMES       0
 
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
 
 //default threshold and saturation
-#define THRESHOLD                                      70
-#define SATURATION                             1.0
+#define THRESHOLD         70
+#define SATURATION        1.0
 
-//number of all masks
-#define MASKSCNT                                       5
 //mask filename pattern
-#define MASKFILENAME                   "../rozkuk_masks/mask%02d.bin"
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
+#define MASKFILENAME      "./mask%02d%c%c.pnm"
+#else                     /******************** PPC *******************/
+#define MASKFILENAME      "./mask%02d%c%c.pnm"
+#endif                    /*------------------------------------------*/
 
 //size of frames from camera
-#define FRAME_WIDTH                            640
-#define FRAME_HEIGHT                   480
-#define FRAME_SIZE                             (FRAME_WIDTH * FRAME_HEIGHT)
+#define FRAME_WIDTH       640
+#define FRAME_HEIGHT      480
+#define FRAME_SIZE        (FRAME_WIDTH * FRAME_HEIGHT)
+
+//both (side and center) subresults will be returned in one int masked binary as 00ccssss
+#define MASK_SIDE         0x0F
+#define MASK_CENTER_SHIFT 4
+#define MASK_CENTER       (0x03 << 4)
+
+//number of results to select the most supported one from
+#define DECISION_BOX_SIZE 5
+
+//camera control system (if true, rozkuk recognizes, else it waits)
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
+#define ORTE_CAMERA_CONTROL 1
+#else                     /******************** PPC *******************/
+#define ORTE_CAMERA_CONTROL orte.camera_control.on
+#endif                    /*------------------------------------------*/
 
 /******************************************************************************/
 
 // function declarations
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
+int saveFrame(const CvArr *img);
 void drawPauseText(IplImage *img);
-int saveFrame(const IplImage *img);
-void displayProduct(const CvMat *floatMat, int recognizedLayout);
+void displayProduct(const CvMat *floatMat, int sideConfig, int centerConfig);
+void displayMasksSum(const CvMat *mat1, const CvMat *mat2, const char *windowName);
 void displayFloatMat(const CvMat *floatMat, const char *windowName);
 int modeRealtime(CvCapture* capture);
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
-int modeRecognize(CvCapture* capture);
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
+int modeRecognize(CvCapture* capture, CORBA_octet currentColor);
+int modeWait(CvCapture *capture);
 int modeManager(int defaultMode);
-int recognize(const CvMat *frame);
+int countThreshold(const IplImage *frame);
+int recognize(const CvMat *frame, CvMat **masks, int masksCnt, double *resDist=NULL);
 int loadMask(const char *filename, CvMat **mask);
-int loadMasks(void);
+int loadMasks(char color);
 void freeMasks(void);
+void rcv_cmr_ctrl_cb(const ORTERecvInfo *info, void *vinstance, void *recvCallBackParam);
 
 /******************************************************************************/
 
 // variable declarations
-CvMat **masks=NULL;                    //float mask matrices
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
-CvFont font;                                           //text font
+struct robottype_orte_data orte;
+int orteError=0;
+CvMat **sideMasks=NULL;     //float mask matrices
+CvMat **centerMasks=NULL;
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
+CvFont font;                //text font
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
 
 /******************************************************************************/
 
-/** Writes text "pause" in the CAMERA window. */
-void drawPauseText(IplImage *img) {
-       cvPutText(img,"pause", cvPoint(300,440), &font, cvScalar(255,255,255));
-       cvShowImage(WINDOW_ORIG, img);
-}
-
-/******************************************************************************/
+#if defined (ROZKUK_DEBUG) || defined (PPC_DEBUG)  /************ BOTH DEBUG SESSIONS ************/
 
 /** Saves current image to a new file in the current directory. */
-int saveFrame(const IplImage *img) {
+int saveFrame(const CvArr *img) {
        struct stat stFileInfo;
-       char filename[30] = "snapshot00.png";
        unsigned int i=0;
+
        //find a non-existent filename
+#if defined (ROZKUK_DEBUG)
+       char filename[30] = "snapshot00.png";
        while(!stat(filename, &stFileInfo)) sprintf(filename, "snapshot%02d.png", ++i);
+#else
+       char filename[30] = "snapshot00.pnm";
+       while(!stat(filename, &stFileInfo)) sprintf(filename, "snapshot%02d.pnm", ++i);
+#endif
+
+       fprintf(stdout, "Saving frame to %s...\n", filename);
        //save image to file
        return cvSaveImage(filename, img);
 }
 
+#endif                    /*----------- BOTH DEBUG SESSIONS -----------*/
+
+/******************************************************************************/
+
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
+
+/** Writes text "pause" in the CAMERA window. */
+void drawPauseText(IplImage *img) {
+       cvPutText(img,"pause", cvPoint(300,440), &font, cvScalar(255,255,255));
+       cvShowImage(WINDOW_ORIG, img);
+}
+
 /******************************************************************************/
 
 /** Displays in separate window the result of multiplying camera frame (in float)
   * and recognized mask.
   * @param floatMat Pointer to the camera frame converted to float matrix.
-  * @param recognizedLayout Index of recognized situation. */
-void displayProduct(const CvMat *floatMat, int recognizedLayout) {
-       CvMat *product = cvCloneMat(floatMat);
+  * @param sideConfig Index of recognized side situation.
+  * @param centerConfig Index of recognized center situation. */
+void displayProduct(const CvMat *floatMat, int sideConfig, int centerConfig) {
+       CvMat *sideProduct = cvCloneMat(floatMat);
+       CvMat *centerProduct = cvCloneMat(floatMat);
+
+       cvMul(floatMat, sideMasks[sideConfig], sideProduct);            //count product of frame and side mask
+       cvMul(floatMat, centerMasks[centerConfig], centerProduct);      //count product of frame and center mask
+       displayMasksSum(sideProduct, centerProduct, WINDOW_PROD);       //display sum
+
+       cvReleaseMat(&sideProduct);
+       cvReleaseMat(&centerProduct);
+}
 
-       cvMul(floatMat, masks[recognizedLayout], product);              // count product
-       displayFloatMat(product, WINDOW_PROD);
+/******************************************************************************/
 
-       cvReleaseMat(&product);
+/** Displays a sum of two matrices in specified window. */
+void displayMasksSum(const CvMat *mat1, const CvMat *mat2, const char *windowName) {
+       CvMat *sum = cvCloneMat(mat1);
+       
+       cvAdd(mat1, mat2, sum);
+       displayFloatMat(sum, windowName);
+       
+       cvReleaseMat(&sum);
 }
 
 /******************************************************************************/
@@ -154,8 +215,8 @@ void displayFloatMat(const CvMat *floatMat, const char *windowName) {
        double min=0.0, max=0.0;
        CvMat *normalized = cvCloneMat(floatMat);
 
-       cvMinMaxLoc(floatMat, &min, &max);                                                                                      // find extremes
-       cvConvertScale(floatMat, normalized, 1/(max-min), -(min/(max-min)));            // normalize
+       cvMinMaxLoc(floatMat, &min, &max);                    // find extremes
+       cvConvertScale(floatMat, normalized, 1/(max-min), -(min/(max-min)));  // normalize
        cvShowImage(windowName, normalized);
 
        cvReleaseMat(&normalized);
@@ -167,127 +228,193 @@ void displayFloatMat(const CvMat *floatMat, const char *windowName) {
  * @param capture Pointer to a camera capture.
  * @return Code of mode to switch to. */
 int modeRealtime(CvCapture* capture) {
-  IplImage* frame = NULL;                                                                                                                              // frame from camera
-  int pause=0;                                                                                                                                                                 // set pause=1 to pause the video
-  
+       IplImage* frame = NULL;                               // frame from camera
+       int pause=0;                                          // set pause=1 to pause the video
+
        while(1) {
                /* keyboard events handeling */
-    switch(cvWaitKey(10) & 0xFF) {                                                                                     // wait 10ms for an event
-    // stop capturing
-    case KEY_ESC:
-       return MODE_QUIT;
-    // switch to recognize mode
-    case KEY_R:
-    case KEY_r:
-       return MODE_RECOGNIZE;
-    // (un)pause
-    case KEY_P:
-    case KEY_p:
-       pause = !pause;
-       drawPauseText(frame);
-       break;
-    // save frame to file
-    case KEY_S:
-    case KEY_s:
-       saveFrame(frame);
-       break;
-    }
-
-    frame = cvQueryFrame(capture);                                                                                     // Get one frame
-    if(!frame) {
-      perror("NULL frame");
-      continue;
-    }
-               
-    if(!pause) cvShowImage(WINDOW_ORIG, frame);                                        // show image (! Do not release the frame !)    
+               switch(cvWaitKey(10) & 0xFF) {                      // wait 10ms for an event
+               // stop capturing
+               case KEY_ESC:
+                       return MODE_QUIT;
+               // switch to recognize mode
+               case KEY_R:
+               case KEY_r:
+                       return MODE_RECOGNIZE;
+               // (un)pause
+               case KEY_P:
+               case KEY_p:
+                       pause = !pause;
+                       drawPauseText(frame);
+                       break;
+               // save frame to file
+               case KEY_S:
+               case KEY_s:
+                       saveFrame(frame);
+                       break;
+               }
+
+               frame = cvQueryFrame(capture);                      // Get one frame
+               if(!frame) {
+                       fprintf(stderr, "NULL frame\n");
+                       continue;
+               }
+
+               if(!pause) cvShowImage(WINDOW_ORIG, frame);         // show image (! Do not release the frame !)
        }
        return MODE_QUIT;
 }
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
 
 /******************************************************************************/
 
 /** Implements the camera recognition of corns.
  * In DEBUG session the results are also displayed on screen.
  * @param capture Pointer to a camera capture.
+ * @param currentColor Number of starting color. If it changes in orte during
+ *   recognition, this mode needs to restart (to load suitable masks).
  * @return Code of mode to switch to. */
-int modeRecognize(CvCapture* capture) {
-       IplImage *frame = NULL;                                                                                                                         // frame from camera
-  IplImage *thresFrame = NULL;                                                                                                 // thresholded frame
-       CvMat *floatMat = NULL;                                                                                                                         // float <-1,1> image of the frame
-  int layout;                                                                                                                                                                          // number of recognized situation
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
-  int framesPassed = PASS_FRAMES;                                                                                              // number of passed frames before refresh
-       int pause=0;                                                                                                                                                                    // set pause=1 to pause processing
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
-       while(1) {
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
+int modeRecognize(CvCapture* capture, CORBA_octet currentColor) {
+       IplImage *frame = NULL;                               // frame from camera
+       IplImage *thresFrame = NULL;                          // thresholded frame
+       CvMat *floatMat = NULL;                               // float <-1,1> image of the frame
+       int sideConfig, centerConfig;                         // indices of recognized configurations
+       double sideDist, centerDist;                          // distances between the best and second best results
+       TDecisionBox sideBox(DECISION_BOX_SIZE, SIDEMASKSCNT);     // side solutions "averaging" decision box
+       TDecisionBox centerBox(DECISION_BOX_SIZE, CENTERMASKSCNT); // center solutions "averaging" decision box
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
+       int framesPassed = PASS_FRAMES;                       // number of passed frames before refresh
+       int pause=0;                                          // set pause=1 to pause processing
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
+       while(ORTE_CAMERA_CONTROL) {
+       
+               //if color changed during recognition, restart the mode to load appropriate masks
+               if(orte.camera_control.game_color != currentColor) return MODE_RECOGNIZE;
+
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
                /* keyboard events handeling */
-    switch(cvWaitKey(10) & 0xFF) {                                                                                     // wait 10ms for an event
-    // stop capturing
-    case KEY_ESC:
-       return MODE_QUIT;
-    // skip the frame
-    case KEY_SPACE:
-       framesPassed = PASS_FRAMES;
-       break;
-    // switch to recognize mode
-    case KEY_R:
-    case KEY_r:
-       return MODE_REALTIME;
-    // (un)pause
-    case KEY_P:
-    case KEY_p:
-       pause = !pause;
-       drawPauseText(frame);
-       break;
-    // save frame to file
-    case KEY_S:
-    case KEY_s:
-       saveFrame(frame);
-       break;
-    }
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
+               switch(cvWaitKey(10) & 0xFF) {                      // wait 10ms for an event
+               // stop capturing
+               case KEY_ESC:
+                       return MODE_QUIT;
+               // skip the frame
+               case KEY_SPACE:
+                       framesPassed = PASS_FRAMES;
+                       break;
+               // switch to recognize mode
+               case KEY_R:
+               case KEY_r:
+                       return MODE_REALTIME;
+               // (un)pause
+               case KEY_P:
+               case KEY_p:
+                       pause = !pause;
+                       drawPauseText(frame);
+                       break;
+               // save frame to file
+               case KEY_S:
+               case KEY_s:
+                       saveFrame(frame);
+                       break;
+               // wait
+               case KEY_W:
+               case KEY_w:
+                       return MODE_WAIT;
+               }
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
 
                // Get one frame
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
                if(pause) cvQueryFrame(capture);
                else
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
                        frame = cvQueryFrame(capture);
-    if(!frame) {
-      perror("NULL frame");
-      continue;
-    }
-    
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
+               if(!frame) {
+                       fprintf(stderr, "NULL frame\n");
+                       // save error code to orte and publish it
+                       orte.camera_result.error |= camera_ERR_NO_FRAME;
+                       ORTEPublicationSend(orte.publication_camera_result);
+                       usleep(100*1000);
+                       continue;
+               } else if(orte.camera_result.error & camera_ERR_NO_FRAME) {
+                       orte.camera_result.error &= ~camera_ERR_NO_FRAME;
+                       ORTEPublicationSend(orte.publication_camera_result);
+               }
+
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
                if(pause) continue;
 
-    // transform colorful image to its float <-1,1> representation
-    cvReleaseImage(&thresFrame);
-       thresFrame = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
+               // transform colorful image to its float <-1,1> representation
+               cvReleaseImage(&thresFrame);
+               thresFrame = cvCreateImage(cvSize(FRAME_WIDTH,FRAME_HEIGHT),IPL_DEPTH_8U,1);
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
                // convert to float
-       clr2float(frame, &floatMat, THRESHOLD, SATURATION, thresFrame); // get float representation (in DEBUG session, thresholded image is stored to thresFrame)
-       layout = recognize(floatMat);
-               printf("varianta: %d\n", layout);
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
-       displayProduct(floatMat, layout);
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
+               int threshold = countThreshold(frame);
+               clr2float(frame, &floatMat, threshold, SATURATION, thresFrame); // get float representation (in DEBUG session, thresholded image is stored to thresFrame)
+               //recognize side and center configurations
+               sideConfig = recognize(floatMat, sideMasks, SIDEMASKSCNT, &sideDist);
+               centerConfig = recognize(floatMat, centerMasks, CENTERMASKSCNT, &centerDist);
+               fprintf(stderr, "SINGLE:   thr: %3d, side: %d (%.2f), center: %d (%.2f)\n", threshold, sideConfig, sideDist, centerConfig, centerDist);
+               //push the results to the decision box and get "averaged" solutions from it
+               sideBox.insertItem(sideConfig, sideDist);
+               centerBox.insertItem(centerConfig, centerDist);
+               sideBox.decide(&sideConfig, &sideDist);
+               centerBox.decide(&centerConfig, &centerDist);
+               //publish results
+               orte.camera_result.side = sideConfig;
+               orte.camera_result.center = centerConfig;
+               orte.camera_result.sideDist = sideDist;
+               orte.camera_result.centerDist = centerDist;
+               ORTEPublicationSend(orte.publication_camera_result);
+               fprintf(stderr, "ORTE:               side: %d (%.2f), center: %d (%.2f)\n", sideConfig, sideDist, centerConfig, centerDist);
+               
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
+               displayProduct(floatMat, sideConfig, centerConfig);
+#elif defined (PPC_DEBUG) ///////////// PPC DEBUG SESSION //////////////
+               saveFrame(frame);
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
                cvReleaseMat(&floatMat);
 
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
                if(framesPassed++ > PASS_FRAMES) {
-           framesPassed=0;
-           cvShowImage(WINDOW_ORIG, frame);                                                                    // show image (! Do not release the frame !)
-       cvShowImage(WINDOW_THRES, thresFrame);
-           displayFloatMat(masks[layout], WINDOW_MASK);                        // display selected mask
-       cvReleaseImage(&thresFrame);
+                       framesPassed=0;
+                       cvShowImage(WINDOW_ORIG, frame);                  // show image (! Do not release the frame !)
+                       cvShowImage(WINDOW_THRES, thresFrame);
+                       displayMasksSum(sideMasks[sideConfig], centerMasks[centerConfig], WINDOW_MASK);  // display selected mask
+                       cvReleaseImage(&thresFrame);
                }
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
 
        }
-       return MODE_QUIT;
+       return MODE_WAIT;
+}
+
+/******************************************************************************/
+
+/** Waits while no action is wanted. To stop waiting set orte.camera_control.on=TRUE
+  * or in DEBUG session press W key.
+  * @param capture Pointer to a camera capture.
+  * @return Code of mode to switch to. */
+int modeWait(CvCapture *capture) {
+       while(!ORTE_CAMERA_CONTROL) {
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
+               //process keyboard events
+               switch(cvWaitKey(10) & 0xFF) {                      // wait 10ms for an event
+               // exit program
+               case KEY_ESC:
+                       return MODE_QUIT;
+
+               // stop waiting
+               case KEY_W:
+               case KEY_w:
+                       return MODE_RECOGNIZE;
+
+               }
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
+               fprintf(stderr, "waiting...\n");
+               sleep(1);
+       }
+       return MODE_RECOGNIZE;
 }
 
 /******************************************************************************/
@@ -296,73 +423,101 @@ int modeRecognize(CvCapture* capture) {
  * @param defaultMode The first mode to run. */
 int modeManager(int defaultMode) {
        int mode=defaultMode;
-  CvCapture* capture;
-  
+       int ret;
+       CvCapture* capture;
+       CORBA_octet color;
+
        // connect to a camera
-  while(!(capture=cvCaptureFromCAM(CV_CAP_ANY))) {
-         perror("NULL capture");
-    usleep(500*1000);
-  }  
-  
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
+       while(!((capture=cvCaptureFromCAM(0)) || (capture=cvCaptureFromCAM(1)))) {
+               fprintf(stderr, "NULL capture (is camera connected?)\n");
+               orte.camera_result.error |= camera_ERR_NO_VIDEO;
+               ORTEPublicationSend(orte.publication_camera_result);
+               usleep(500*1000);
+       }
+       orte.camera_result.error &= ~camera_ERR_NO_VIDEO;
+       ORTEPublicationSend(orte.publication_camera_result);
+       fprintf(stderr, "rozkuk started, camera connected successfully\n");
+
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
        // create gui windows and init font
-  cvNamedWindow(WINDOW_ORIG, CV_WINDOW_AUTOSIZE);                              // real camera video / one frame viewer
-       cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 1.0, 1.0, 0, 1);             //init text font
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
-
-  while(!(mode & MODE_QUIT)) {
-       switch(mode & MASK_MODES) {
-
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
-       case MODE_REALTIME:
-               cvDestroyWindow(WINDOW_THRES);
-               mode = modeRealtime(capture);
-               break;
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
-
-       case MODE_RECOGNIZE:
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
-               cvNamedWindow(WINDOW_THRES, CV_WINDOW_AUTOSIZE);
-               cvMoveWindow(WINDOW_THRES, cvQueryFrame(capture)->width, 0);
-               cvNamedWindow(WINDOW_MASK, CV_WINDOW_AUTOSIZE);
-               cvMoveWindow(WINDOW_MASK, 0, cvQueryFrame(capture)->height+50);
-               cvNamedWindow(WINDOW_PROD, CV_WINDOW_AUTOSIZE);
-               cvMoveWindow(WINDOW_PROD, cvQueryFrame(capture)->width, cvQueryFrame(capture)->height+50);
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
-               mode = modeRecognize(capture);
-               break;
-
-       default:
-               goto end;                       // jump out of the loop
-       }
-  }
+       cvNamedWindow(WINDOW_ORIG, CV_WINDOW_AUTOSIZE);       // real camera video / one frame viewer
+       cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 1.0, 1.0, 0, 1);  //init text font
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
+
+       while(!(mode & MODE_QUIT)) {
+               switch(mode & MASK_MODES) {
+
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
+               case MODE_REALTIME:
+                       cvDestroyWindow(WINDOW_THRES);
+                       mode = modeRealtime(capture);
+                       break;
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
+
+               case MODE_RECOGNIZE:
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
+                       cvNamedWindow(WINDOW_THRES, CV_WINDOW_AUTOSIZE);
+                       cvMoveWindow(WINDOW_THRES, cvQueryFrame(capture)->width, 0);
+                       cvNamedWindow(WINDOW_MASK, CV_WINDOW_AUTOSIZE);
+                       cvMoveWindow(WINDOW_MASK, 0, cvQueryFrame(capture)->height+50);
+                       cvNamedWindow(WINDOW_PROD, CV_WINDOW_AUTOSIZE);
+                       cvMoveWindow(WINDOW_PROD, cvQueryFrame(capture)->width, cvQueryFrame(capture)->height+50);
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
+                       //load masks and run recognition mode, then free masks (they are in memory only while in recognition mode)
+                       color = orte.camera_control.game_color;
+                       if((ret=loadMasks((color==BLUE ? clBLUE : clYELLOW)))) return ret;
+                       mode = modeRecognize(capture, color);
+                       freeMasks();
+                       break;
+
+               case MODE_WAIT:
+                       mode = modeWait(capture);
+                       break;
+
+               default:
+                       goto end;    // jump out of the loop
+               }
+       }
 
 end:
-  cvReleaseCapture(&capture);
-#ifdef ROZKUK_DEBUG                            /************ DEBUG SESSION ONLY ************/
-  cvDestroyWindow(WINDOW_ORIG);
-  cvDestroyWindow(WINDOW_THRES);
-  cvDestroyWindow(WINDOW_MASK);
-  cvDestroyWindow(WINDOW_PROD);
-#endif                                                                         /*----------- DEBUG SESSION ONLY -----------*/
-  return mode & MASK_ERRORS;
+       cvReleaseCapture(&capture);
+#ifdef ROZKUK_DEBUG       /************ DEBUG SESSION ONLY ************/
+       cvDestroyWindow(WINDOW_ORIG);
+       cvDestroyWindow(WINDOW_THRES);
+       cvDestroyWindow(WINDOW_MASK);
+       cvDestroyWindow(WINDOW_PROD);
+#endif                    /*----------- DEBUG SESSION ONLY -----------*/
+       return mode & MASK_ERRORS;
+}
+
+/******************************************************************************/
+
+/** Returns a threshold computed from the frame. */
+int countThreshold(const IplImage *frame) {
+       return cvAvg(frame).val[0];
 }
 
 /******************************************************************************/
 
 /** Returns an ordinary number of recognized layout.
-       * @param frame Float representation of frame. */
-int recognize(const CvMat *frame) {
+  * @param frame Float representation of frame.
+  * @param masks Array of masks to compare with.
+  * @param masksCnt Size of the array.
+  * @param resDist If not NULL, a distance between the best and second best result is stored here.*/
+int recognize(const CvMat *frame, CvMat **masks, int masksCnt, double *resDist) {
        double max = cvDotProduct(frame, masks[0]);
+       double max2 = -(FRAME_SIZE);                          // the least possible value
        int maxInd = 0;
-       for(int i=1; i<MASKSCNT; i++)   {
+       for(int i=1; i<masksCnt; i++) {
                double prod = cvDotProduct(frame, masks[i]);
                if(prod > max) {
+                       max2 = max;
                        max = prod;
                        maxInd = i;
-               }
+               } else if(prod > max2) max2 = prod;
        }
-       return maxInd;
+       if(resDist) *resDist = max-max2;
+       return maxInd;
 }
 
 /******************************************************************************/
@@ -372,21 +527,22 @@ int recognize(const CvMat *frame) {
  * @param mask Address of array, where to alloc memory and store the data.
  * @return Length of read data or zero in case of error. */
 int loadMask(const char *filename, CvMat **mask) {
-       float *data;
        int len;
-       FILE *pFile = fopen(filename, "rb");                                                                    //open binary file for reading
-       if(!pFile) {
-               char msg[200];
-               sprintf(msg, "Mask %s cannot be loaded.", filename);
-               perror(msg);
+       
+       IplImage *img = cvLoadImage(filename, CV_LOAD_IMAGE_GRAYSCALE);
+       if(!img) {
+               fprintf(stderr, "Mask %s cannot be loaded.\n", filename);
+               fprintf(stderr, "Run me from _build/user/camera/rozkuk\n");
                return 0;
        }
        
-       *mask = cvCreateMat(FRAME_HEIGHT, FRAME_WIDTH, CV_32FC1);
-       data = (*mask)->data.fl;
-       len = fread((float *)data, sizeof(float), FRAME_SIZE, pFile);   //read data
-       
-       fclose(pFile);
+       *mask = NULL;
+       if(!(len=clr2float(img, mask, CL_NEUTRAL, 1.0, NULL)))
+               fprintf(stderr, "A problem while converting mask to float occured.\n");
+       else
+               fprintf(stderr, "Mask %s successfully loaded.\n", filename);
+
+       cvReleaseImage(&img);
        return len;
 }
 
@@ -394,12 +550,19 @@ int loadMask(const char *filename, CvMat **mask) {
 
 /** Loads all the float masks from files.
  * @return Zero if ok, else non-zero. */
-int loadMasks(void) {
-       masks = (CvMat **)malloc(MASKSCNT*sizeof(CvMat *));             //alloc memory for array of masks
-       for(int i=0; i<MASKSCNT; i++) {
-               char filename[100];
-               sprintf(filename, MASKFILENAME, i);
-               if(!loadMask(filename, masks+i)) return ERR_MASK_READ_FAILURE;
+int loadMasks(char color) {
+       char filename[100];
+       //alloc memory for arrays of masks
+       sideMasks = (CvMat **)malloc(SIDEMASKSCNT*sizeof(CvMat *));
+       centerMasks = (CvMat **)malloc(CENTERMASKSCNT*sizeof(CvMat *));
+       //load masks
+       for(int i=0; i<SIDEMASKSCNT; i++) {
+               sprintf(filename, MASKFILENAME, i, orSIDE, color);
+               if(!loadMask(filename, sideMasks+i)) return ERR_MASK_READ_FAILURE;
+       }
+       for(int i=0; i<CENTERMASKSCNT; i++) {
+               sprintf(filename, MASKFILENAME, i, orCENTER, color);
+               if(!loadMask(filename, centerMasks+i)) return ERR_MASK_READ_FAILURE;
        }
        return 0;
 }
@@ -408,24 +571,49 @@ int loadMasks(void) {
 
 /** Frees the memory alloced for masks. */
 void freeMasks(void) {
-       for(int i=0; i<MASKSCNT; i++) {
-               cvReleaseMat(masks+i);
+       for(int i=0; i<SIDEMASKSCNT; i++) cvReleaseMat(sideMasks+i);
+       for(int i=0; i<CENTERMASKSCNT; i++) cvReleaseMat(centerMasks+i);
+       free(sideMasks);
+       free(centerMasks);
+}
+
+/******************************************************************************/
+
+/** Orte camera control callback function. */
+void rcv_cmr_ctrl_cb(const ORTERecvInfo *info, void *vinstance, void *recvCallBackParam) {
+#ifdef ORTE_DEBUG
+       struct robottype_orte_data *orte_data = (struct robottype_orte_data *)recvCallBackParam;
+#endif /*----------- ORTE_DEBUG -----------*/
+
+       switch (info->status) {
+               case NEW_DATA:
+                       // nothing to do - changes will be processed in the recognition loop
+#ifdef ORTE_DEBUG
+                       printf("orte: New data: ctrl %d, clr %d\n", orte_data->camera_control.on, orte_data->camera_control.game_color);
+#endif /*----------- ORTE_DEBUG -----------*/
+                       break;
+               case DEADLINE:
+                       printf("ORTE deadline occurred - CMR_CTRL receive\n");
+                       break;
        }
-       free(masks);
 }
 
 /******************************************************************************/
 
 int main(int argc, char *argv[]) {
        int ret;
-/*  while (orte_init()) {
-    perror("orte_init");
-    usleep(500*1000);
-  }
-*/
-       if((ret=loadMasks())) return ret;
-       ret = modeManager(START_MODE);
-       freeMasks();
+
+       ret = robottype_roboorte_init(&orte);
+       if(ret < 0) {
+               fprintf(stderr, "robottype_roboorte_init failed\n");
+               return ret;
+       }
+       robottype_publisher_camera_result_create(&orte, NULL, NULL);
+       robottype_subscriber_camera_control_create(&orte, rcv_cmr_ctrl_cb, &orte);
+       
+       modeManager(START_MODE);
+
+       ret = robottype_roboorte_destroy(&orte);
        return ret;
 }