INCLUDES += -I /usr/local/include
LDFLAGS += -L /usr/local/lib
-bin_PROGRAMS = rozkuk camgrab #v4l-info
+bin_PROGRAMS = rozkuk #v4l-info
#v4l-info_SOURCES = v4l-info.c struct-dump.c struct-v4l.c struct-v4l2.c
-rozkuk_SOURCES = rozkuk.cxx clr2float.cxx
+rozkuk_SOURCES = rozkuk.cxx clr2float.cxx t_decision_box.cxx
rozkuk_LIBS = robodim pthread roboorte robottype orte cv highgui cxcore rt z jpeg
ifeq ($(CROSS_COMPILE),)
maskgen_LIBS = cv highgui
endif
-camgrab_SOURCES = camgrab.c camera.c
-camgrab_LIBS = v4lconvert
-
ifneq ($(wildcard $(OUTPUT_DIR)/_compiled/bin/maskgen),)
binary-pass_HOOKS = masks.stamp
#include "clr2float.h"
#include "masks_globals.h"
+#include "t_decision_box.h"
extern "C" {
#include <roboorte_robottype.h>
#define MASK_CENTER_SHIFT 4
#define MASK_CENTER (0x03 << 4)
+//number of results to select the most probable 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
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.on) {
+ while(ORTE_CAMERA_CONTROL) {
#ifdef ROZKUK_DEBUG /************ DEBUG SESSION ONLY ************/
/* keyboard events handeling */
// convert to float
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 layouts
+ //recognize side and center configurations
sideConfig = recognize(floatMat, sideMasks, SIDEMASKSCNT, &sideDist);
centerConfig = recognize(floatMat, centerMasks, CENTERMASKSCNT, ¢erDist);
+ fprintf(stderr, "SINGLE: thr: %3d, side: %d (%f), center: %d (%f)\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(¢erConfig, ¢erDist);
//publish results
- fprintf(stderr, "thr: %d, side: %d (%f), center: %d (%f)\n", threshold, sideConfig, sideDist, centerConfig, centerDist);
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 (%f), center: %d (%f)\n", sideConfig, sideDist, centerConfig, centerDist);
#ifdef ROZKUK_DEBUG /************ DEBUG SESSION ONLY ************/
displayProduct(floatMat, sideConfig, centerConfig);
* @param capture Pointer to a camera capture.
* @return Code of mode to switch to. */
int modeWait(CvCapture *capture) {
- while(!orte.camera_control.on) {
+ while(!ORTE_CAMERA_CONTROL) {
#ifdef ROZKUK_DEBUG /************ DEBUG SESSION ONLY ************/
//process keyboard events
switch(cvWaitKey(10) & 0xFF) { // wait 10ms for an event
--- /dev/null
+#include <cstddef>
+#include <cstdio>
+#include "t_decision_box.h"
+using namespace std;
+
+/******************************************************************************/
+
+void TDecisionBox::countDistances(void) {
+ for(int i=0; i<=maxVal; i++) optionsWeights[i] = 0;
+
+ Configuration *token = head;
+ while(token) {
+ optionsWeights[token->number] += token->distance;
+ token = token->next;
+ }
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+TDecisionBox::TDecisionBox(int size, int maxVal) {
+ this->size = (size<1 ? 1 : size);
+ this->count = 0;
+ this->maxVal = (maxVal<1 ? 0 : maxVal);
+ this->optionsWeights = new double [this->maxVal+1];
+ this->head = this->tail = NULL;
+}
+
+/******************************************************************************/
+
+TDecisionBox::~TDecisionBox(void) {
+ delete [] optionsWeights;
+ while(head) {
+ Configuration *item = head;
+ head = head->next;
+ delete item;
+ }
+}
+
+/******************************************************************************/
+
+bool TDecisionBox::insertItem(int number, double distance) {
+ if((number<0)||(number>maxVal)) return false;
+
+ Configuration *conf = new Configuration;
+ conf->number = number;
+ conf->distance = distance;
+ conf->next = head;
+ conf->prev = NULL;
+
+ if(head) head->prev = conf;
+ head = conf;
+ if(!tail) tail = conf;
+
+ // delete the last item
+ if(count>=size) {
+ Configuration *last = tail;
+ if(tail) {
+ tail = tail->prev;
+ tail->next = NULL;
+ }
+ delete last;
+ } else ++count;
+
+ return true;
+}
+
+/******************************************************************************/
+
+void TDecisionBox::decide(int *configuration, double *distance) {
+ double maxValue;
+ int maxIndex=0;
+
+ //refresh table of distances
+ countDistances();
+
+ // find highest distance
+ maxValue=optionsWeights[0];
+ for(int i=1; i<=maxVal; i++) {
+ if(optionsWeights[i] > maxValue) {
+ maxValue = optionsWeights[i];
+ maxIndex = i;
+ }
+ }
+
+ if(configuration) *configuration = maxIndex;
+ if(distance) *distance = maxValue / count; //average distance
+}
+
+/******************************************************************************/
+
--- /dev/null
+/*******************************************************************************
+ *
+ * TDecisionBox - Class implementing box selecting most probable solution,
+ * i.e. performs weighted selection on input objects.
+ *
+ * Created for Eurobot 2010 competition.
+ *
+ * Petr Kubizňák (kubiznak.petr@gmail.com), 2010
+ *
+ ******************************************************************************/
+
+#ifndef __T_DECISION_BOX_H__
+#define __T_DECISION_BOX_H__
+
+/******************************************************************************/
+
+struct Configuration {
+ int number;
+ double distance;
+ Configuration *next;
+ Configuration *prev;
+};
+
+/******************************************************************************/
+
+class TDecisionBox {
+protected:
+ /** Capacity of the box. */
+ int size;
+ /** Actual number of items in the box. */
+ int count;
+ /** Maximal value of result. */
+ int maxVal;
+ /** Table of weights of each option. */
+ double *optionsWeights;
+ /** First and last item in the box. */
+ Configuration *head, *tail;
+
+ /** Refreshes the optionsWeights table. */
+ void countDistances(void);
+
+public:
+ TDecisionBox(int size, int maxVal);
+ ~TDecisionBox(void);
+
+ /** Inserts solution properties as one item in the box.
+ * @return False if (number) is invalid value, else true. */
+ bool insertItem(int number, double distance);
+ /** Finds the most supported solution and sets it to (configuration),
+ distance is stored to (distance). */
+ void decide(int *configuration, double *distance);
+};
+
+/******************************************************************************/
+
+#endif /* T_DECISION_BOX */
+