add more statistics

This commit is contained in:
Edward Emelianov 2025-05-14 09:04:11 +03:00
parent fd2508c667
commit 3f7b5081ea
10 changed files with 168 additions and 81 deletions

View File

@ -21,6 +21,7 @@
#include <pthread.h> #include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "cameracapture.h" #include "cameracapture.h"
#include "cmdlnopts.h" #include "cmdlnopts.h"
@ -42,6 +43,15 @@ static frameformat curformat;
static frameformat maxformat; static frameformat maxformat;
static frameformat stepformat; static frameformat stepformat;
// statistics of last image
typedef struct{
Imtype minval, maxval, bkg;
float avg, xc, yc;
ptstat_t stat;
} imdata_t;
static imdata_t lastimdata = {0};
static void changeformat(){ static void changeformat(){
if(!theCam) return; if(!theCam) return;
if(maxformat.h < 1 || maxformat.w < 1){ if(maxformat.h < 1 || maxformat.w < 1){
@ -190,7 +200,7 @@ static int needs_exposure_adjustment(const Image *I, float curr_x, float curr_y)
float avg = I->avg_intensity; float avg = I->avg_intensity;
float dx = fabsf(curr_x - last_centroid_x); float dx = fabsf(curr_x - last_centroid_x);
float dy = fabsf(curr_y - last_centroid_y); float dy = fabsf(curr_y - last_centroid_y);
LOGDBG("avg: %g, curr_x: %g, curr_y: %g", avg, curr_x, curr_y); //LOGDBG("avg: %g, curr_x: %g, curr_y: %g", avg, curr_x, curr_y);
// don't change brightness if average value in 5..50 // don't change brightness if average value in 5..50
if(avg > 5.f && avg < 50.f){ if(avg > 5.f && avg < 50.f){
last_avg_intensity = avg; last_avg_intensity = avg;
@ -231,25 +241,13 @@ static void *procthread(void* v){
double t0 = sl_dtime(); double t0 = sl_dtime();
#endif #endif
while(!stopwork){ while(!stopwork){
while(iCaptured < 0) usleep(1000); DBG("===== iCaptured=%d", iCaptured);
pthread_mutex_lock(&capt_mutex); pthread_mutex_lock(&capt_mutex);
if(Icap[iCaptured]){ if(Icap[iCaptured]){
DBG("---- got image #%d @ %g", iCaptured, sl_dtime() - t0); DBG("===== got image #%d @ %g", iCaptured, sl_dtime() - t0);
Image *oIma = Icap[iCaptured]; // take image here and free buffer Image *oIma = Icap[iCaptured]; // take image here and free buffer
Icap[iCaptured] = NULL; Icap[iCaptured] = NULL;
pthread_mutex_unlock(&capt_mutex); pthread_mutex_unlock(&capt_mutex);
if(theconf.expmethod == EXPAUTO){
float xc, yc;
getcenter(&xc, &yc);
if(needs_exposure_adjustment(oIma, xc, yc)) recalcexp(oIma);
}else{
if(fabs(theconf.fixedexp - exptime) > FLT_EPSILON)
exptime = theconf.fixedexp;
if(fabs(theconf.gain - gain) > FLT_EPSILON)
gain = theconf.gain;
if(fabs(theconf.brightness - brightness) > FLT_EPSILON)
brightness = theconf.brightness;
}
if(process){ if(process){
if(theconf.medfilt){ if(theconf.medfilt){
Image *X = get_median(oIma, theconf.medseed); Image *X = get_median(oIma, theconf.medseed);
@ -259,12 +257,38 @@ static void *procthread(void* v){
oIma = X; oIma = X;
} }
} }
DBG("===== process");
process(oIma); process(oIma);
DBG("===== done");
lastimdata.avg = oIma->avg_intensity;
lastimdata.bkg = oIma->background;
lastimdata.minval = oIma->minval;
lastimdata.maxval = oIma->maxval;
lastimdata.stat = oIma->stat;
getcenter(&lastimdata.xc, &lastimdata.yc);
} }
if(theconf.expmethod == EXPAUTO){
DBG("test");
if(needs_exposure_adjustment(oIma, lastimdata.xc, lastimdata.yc)) recalcexp(oIma);
DBG("done");
}else{
if(fabs(theconf.fixedexp - exptime) > FLT_EPSILON)
exptime = theconf.fixedexp;
if(fabs(theconf.gain - gain) > FLT_EPSILON)
gain = theconf.gain;
if(fabs(theconf.brightness - brightness) > FLT_EPSILON)
brightness = theconf.brightness;
}
//Icap[iCaptured] = NULL;
//pthread_mutex_unlock(&capt_mutex);
FREE(oIma->data); FREE(oIma->data);
FREE(oIma); FREE(oIma);
DBG("---- cleared image data @ %g", sl_dtime() - t0); DBG("---- cleared image data @ %g", sl_dtime() - t0);
}else pthread_mutex_unlock(&capt_mutex); }else{
DBG("NO image data");
pthread_mutex_unlock(&capt_mutex);
}
DBG("NEXT!");
usleep(1000); usleep(1000);
} }
return NULL; return NULL;
@ -274,7 +298,7 @@ int camcapture(void (*process)(Image*)){
FNAME(); FNAME();
static float oldexptime = 0.; static float oldexptime = 0.;
static float oldgain = -1.; static float oldgain = -1.;
static float oldbrightness = -1.; static float oldbrightness = 0.;
Image *oIma = NULL; Image *oIma = NULL;
pthread_t proc_thread; pthread_t proc_thread;
if(pthread_create(&proc_thread, NULL, procthread, (void*)process)){ if(pthread_create(&proc_thread, NULL, procthread, (void*)process)){
@ -282,6 +306,7 @@ int camcapture(void (*process)(Image*)){
ERR("pthread_create()"); ERR("pthread_create()");
} }
while(1){ while(1){
double t0 = sl_dtime();
if(stopwork){ if(stopwork){
DBG("STOP"); DBG("STOP");
break; break;
@ -290,13 +315,15 @@ int camcapture(void (*process)(Image*)){
LOGERR("camcapture(): camera not initialized"); LOGERR("camcapture(): camera not initialized");
ERRX("Not initialized"); ERRX("Not initialized");
} }
DBG("T=%g", sl_dtime() - t0);
if(!connected){ if(!connected){
DBG("Disconnected"); DBG("Disconnected, try to connect");
connected = theCam->connect(); connected = theCam->connect();
sleep(1); sleep(1);
changeformat(); changeformat();
continue; continue;
} }
DBG("T=%g", sl_dtime() - t0);
if(fabsf(oldbrightness - brightness) > FLT_EPSILON){ // new brightness if(fabsf(oldbrightness - brightness) > FLT_EPSILON){ // new brightness
DBG("Change brightness to %g", brightness); DBG("Change brightness to %g", brightness);
if(theCam->setbrightness(brightness)){ if(theCam->setbrightness(brightness)){
@ -305,6 +332,7 @@ int camcapture(void (*process)(Image*)){
WARNX("Can't change brightness to %g", brightness); WARNX("Can't change brightness to %g", brightness);
} }
} }
DBG("T=%g", sl_dtime() - t0);
if(exptime > theconf.maxexp) exptime = theconf.maxexp; if(exptime > theconf.maxexp) exptime = theconf.maxexp;
else if(exptime < theconf.minexp) exptime = theconf.minexp; else if(exptime < theconf.minexp) exptime = theconf.minexp;
if(fabsf(oldexptime - exptime) > FLT_EPSILON){ // new exsposition value if(fabsf(oldexptime - exptime) > FLT_EPSILON){ // new exsposition value
@ -315,28 +343,41 @@ int camcapture(void (*process)(Image*)){
WARNX("Can't change exposition time to %gms", exptime); WARNX("Can't change exposition time to %gms", exptime);
} }
} }
DBG("T=%g", sl_dtime() - t0);
if(gain > gainmax) gain = gainmax; if(gain > gainmax) gain = gainmax;
if(fabsf(oldgain - gain) > FLT_EPSILON){ // change gain if(fabsf(oldgain - gain) > FLT_EPSILON){ // change gain
DBG("Change gain to %g\n", gain); DBG("Change gain to %g\n", gain);
LOGDBG("Change gain to %g", gain);
if(theCam->setgain(gain)){ if(theCam->setgain(gain)){
oldgain = gain; oldgain = gain;
}else{ }else{
WARNX("Can't change gain to %g", gain); WARNX("Can't change gain to %g", gain);
LOGWARN("Can't change gain to %g", gain);
gain = oldgain;
} }
} }
DBG("T=%g", sl_dtime() - t0);
// change format // change format
if(abs(curformat.h - theconf.height) || abs(curformat.w - theconf.width) || abs(curformat.xoff - theconf.xoff) || abs(curformat.yoff - theconf.yoff)){ if(abs(curformat.h - theconf.height) || abs(curformat.w - theconf.width) || abs(curformat.xoff - theconf.xoff) || abs(curformat.yoff - theconf.yoff)){
changeformat(); changeformat();
} }
DBG("Try to grab (T=%g)", sl_dtime() - t0);
static int errctr = 0;
if(!(oIma = theCam->capture())){ if(!(oIma = theCam->capture())){
WARNX("Can't grab image"); WARNX("Can't grab image");
if(++errctr > MAX_CAPT_ERRORS){
LOGERR("camcapture(): too much capture errors; reconnect camera");
camdisconnect(); camdisconnect();
continue; errctr = 0;
} }
continue;
}else errctr = 0;
DBG("Grabbed @ %g", sl_dtime() - t0);
pthread_mutex_lock(&capt_mutex); pthread_mutex_lock(&capt_mutex);
if(iCaptured < 0) iCaptured = 0; if(iCaptured < 0) iCaptured = 0;
else iCaptured = !iCaptured; else iCaptured = !iCaptured;
if(Icap[iCaptured]){ // try current value if previous is still busy if(Icap[iCaptured]){ // try current value if previous is still busy
DBG("iCap=%d busy!", iCaptured);
iCaptured = !iCaptured; iCaptured = !iCaptured;
} }
if(!Icap[iCaptured]){ // previous buffer is free if(!Icap[iCaptured]){ // previous buffer is free
@ -344,11 +385,12 @@ int camcapture(void (*process)(Image*)){
Icap[iCaptured] = oIma; Icap[iCaptured] = oIma;
oIma = NULL; oIma = NULL;
}else{ // clear our image - there's no empty buffers }else{ // clear our image - there's no empty buffers
DBG("---- no free buffers"); DBG("---- no free buffers for iCap=%d", iCaptured);
FREE(oIma->data); FREE(oIma->data);
FREE(oIma); FREE(oIma);
} }
pthread_mutex_unlock(&capt_mutex); pthread_mutex_unlock(&capt_mutex);
DBG("unlocked, T=%g", sl_dtime() - t0);
} }
pthread_cancel(proc_thread); pthread_cancel(proc_thread);
if(oIma){ if(oIma){
@ -388,10 +430,13 @@ char *camstatus(const char *messageid, char *buf, int buflen){
float xc, yc; float xc, yc;
getcenter(&xc, &yc); getcenter(&xc, &yc);
snprintf(buf, buflen, "{ \"%s\": \"%s\", \"camstatus\": \"%sconnected\", \"impath\": \"%s\", \"imctr\": %llu, " snprintf(buf, buflen, "{ \"%s\": \"%s\", \"camstatus\": \"%sconnected\", \"impath\": \"%s\", \"imctr\": %llu, "
"\"fps\": %.3f, \"expmethod\": \"%s\", \"exposition\": %g, \"gain\": %g, \"brightness\": %g, " "\"fps\": %.3f, \"expmethod\": \"%s\", \"exposition\": %g, \"gain\": %g, \"maxgain\": %g, \"brightness\": %g, "
"\"xcenter\": %.1f, \"ycenter\": %.1f }\n", "\"xcenter\": %.1f, \"ycenter\": %.1f , \"minval\": %d, \"maxval\": %d, \"background\": %d, "
"\"average\": %.1f, \"xc\": %.1f, \"yc\": %.1f, \"xsigma\": %.1f, \"ysigma\": %.1f, \"area\": %d }\n",
MESSAGEID, messageid, connected ? "" : "dis", impath, ImNumber, getFramesPerS(), MESSAGEID, messageid, connected ? "" : "dis", impath, ImNumber, getFramesPerS(),
(theconf.expmethod == EXPAUTO) ? "auto" : "manual", exptime, gain, brightness, (theconf.expmethod == EXPAUTO) ? "auto" : "manual", exptime, gain, gainmax, brightness,
xc, yc); xc, yc, lastimdata.minval, lastimdata.maxval, lastimdata.bkg, lastimdata.avg,
lastimdata.stat.xc, lastimdata.stat.yc, lastimdata.stat.xsigma, lastimdata.stat.ysigma,
lastimdata.stat.area);
return buf; return buf;
} }

View File

@ -21,6 +21,8 @@
#include "imagefile.h" // Image #include "imagefile.h" // Image
// max capture errors contract to make reconnection
#define MAX_CAPT_ERRORS (10)
// format of single frame // format of single frame
typedef struct{ typedef struct{

View File

@ -34,12 +34,12 @@
#define MAX_THROWPART (0.9) #define MAX_THROWPART (0.9)
#define MAX_OFFSET (10000) #define MAX_OFFSET (10000)
// min/max exposition in ms // min/max exposition in ms
#define EXPOS_MIN (0.1) #define EXPOS_MIN (0.01)
#define EXPOS_MAX (4001.) #define EXPOS_MAX (4001.)
#define GAIN_MIN (0.) #define GAIN_MIN (0.)
#define GAIN_MAX (100.) #define GAIN_MAX (256.)
#define BRIGHT_MIN (0.) #define BRIGHT_MIN (0.)
#define BRIGHT_MAX (10.) #define BRIGHT_MAX (100.)
// max average images counter // max average images counter
#define NAVER_MAX (25) #define NAVER_MAX (25)
// coefficients to convert dx,dy to du,dv // coefficients to convert dx,dy to du,dv
@ -52,15 +52,15 @@
#define MAX_MEDIAN_SEED (7) #define MAX_MEDIAN_SEED (7)
// fixed background // fixed background
#define FIXED_BK_MIN (0) #define FIXED_BK_MIN (0)
#define FIXED_BK_MAX (250) #define FIXED_BK_MAX (255)
// exposition methods: 0 - auto, 1 - fixed // exposition methods: 0 - auto, 1 - fixed
#define EXPAUTO (0) #define EXPAUTO (0)
#define EXPMANUAL (1) #define EXPMANUAL (1)
// roundness parameter // roundness parameter
#define MINWH (0.3) #define MINWH (0.01)
#define MAXWH (3.) #define MAXWH (100.)
// PID limits // PID limits
#define PID_P_MIN (0.1) #define PID_P_MIN (0.1)

View File

@ -372,7 +372,7 @@ static int setexp(float e){
static int cam_startexp(){ static int cam_startexp(){
if(!handle || !pdata) return FALSE; if(!handle || !pdata) return FALSE;
DBG("Start exposition"); DBG("Start exposition for %gs", exptime);
MV_CC_StopGrabbing(handle); MV_CC_StopGrabbing(handle);
TRY(StartGrabbing); TRY(StartGrabbing);
ONERR() return FALSE; ONERR() return FALSE;
@ -380,22 +380,26 @@ static int cam_startexp(){
} }
static Image* capture(){ static Image* capture(){
double starttime = sl_dtime();
if(!cam_startexp()) return NULL; if(!cam_startexp()) return NULL;
MV_FRAME_OUT_INFO_EX stImageInfo = {0}; // last image info MV_FRAME_OUT_INFO_EX stImageInfo = {0}; // last image info
double starttime = sl_dtime(); DBG("Started capt @ %g", sl_dtime() - starttime);
do{ do{
usleep(100); usleep(100);
double diff = exptime - (sl_dtime() - starttime); double diff = exptime - (sl_dtime() - starttime);
if(diff > 0.) continue; // wait until exposure ends if(diff > 0.) continue; // wait until exposure ends
DBG("diff = %g", diff); DBG("diff = %g", diff);
if(diff < -5.0){ // wait much longer than exp lasts if(diff < -MAX_READOUT_TM){ // wait much longer than exp lasts
DBG("OOps, time limit");
MV_CC_StopGrabbing(handle); MV_CC_StopGrabbing(handle);
return NULL; return NULL;
} }
TRY(GetOneFrameTimeout, pdata, pdatasz, &stImageInfo, 10); TRY(GetOneFrameTimeout, pdata, pdatasz, &stImageInfo, 10);
ONOK() break; ONOK() break;
}while(1); }while(1);
DBG("Tcapt=%g, exptime=%g", sl_dtime() - starttime, exptime);
Image *captIma = u8toImage(pdata, stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nWidth); Image *captIma = u8toImage(pdata, stImageInfo.nWidth, stImageInfo.nHeight, stImageInfo.nWidth);
DBG("return @ %g", sl_dtime() - starttime);
return captIma; return captIma;
} }

View File

@ -23,6 +23,9 @@
#define HIKROBOT_CAPT_NAME "hikrobot" #define HIKROBOT_CAPT_NAME "hikrobot"
// maximal readout time, seconds
#define MAX_READOUT_TM (6.)
// tolerance of float values // tolerance of float values
#define HR_FLOAT_TOLERANCE (0.005) #define HR_FLOAT_TOLERANCE (0.005)

View File

@ -257,6 +257,7 @@ int get_histogram(const Image *I, size_t histo[HISTOSZ]){
*/ */
int calc_background(Image *img){ int calc_background(Image *img){
if(!img || !img->data) return FALSE; if(!img || !img->data) return FALSE;
DBG("image min/max=%d/%d", img->minval, img->maxval);
if(img->maxval == img->minval){ if(img->maxval == img->minval){
WARNX("Zero or overilluminated image!"); WARNX("Zero or overilluminated image!");
return FALSE; return FALSE;
@ -266,7 +267,7 @@ int calc_background(Image *img){
WARNX("Image values too small"); WARNX("Image values too small");
return FALSE; return FALSE;
} }
img->background = theconf.fixedbkg; img->background = theconf.fixedbkgval;
return TRUE; return TRUE;
} }
size_t histogram[HISTOSZ]; size_t histogram[HISTOSZ];

View File

@ -32,6 +32,11 @@ typedef uint8_t Imtype;
// WARNING! Check code if you change Imtype: e.g. recalcexp() and other // WARNING! Check code if you change Imtype: e.g. recalcexp() and other
#define HISTOSZ (256) #define HISTOSZ (256)
typedef struct{ // statistics: mean, RMS, area
float xc; float yc; float xsigma; float ysigma;
int area;
} ptstat_t;
typedef struct{ typedef struct{
int width; // width int width; // width
int height; // height int height; // height
@ -40,6 +45,7 @@ typedef struct{
Imtype maxval; Imtype maxval;
float avg_intensity; float avg_intensity;
Imtype background; // background value Imtype background; // background value
ptstat_t stat; // image statistics
} Image; } Image;
// input file/directory type // input file/directory type

View File

@ -31,6 +31,7 @@
#include "draw.h" #include "draw.h"
#include "grasshopper.h" #include "grasshopper.h"
#include "hikrobot.h" #include "hikrobot.h"
#include "imagefile.h"
#include "improc.h" #include "improc.h"
#include "inotify.h" #include "inotify.h"
#include "steppers.h" #include "steppers.h"
@ -132,7 +133,7 @@ static void getDeviation(object *curobj){
averflag = 1; averflag = 1;
if(fXYlog) fprintf(fXYlog, "%.1f\t%.1f\t%.1f\t%.1f", xx, yy, Sx, Sy); if(fXYlog) fprintf(fXYlog, "%.1f\t%.1f\t%.1f\t%.1f", xx, yy, Sx, Sy);
process_corrections: process_corrections:
LOGDBG("here"); //LOGDBG("here");
if(theSteppers){ if(theSteppers){
DBG("Process corrections"); DBG("Process corrections");
if(theSteppers->proc_corr && averflag){ if(theSteppers->proc_corr && averflag){
@ -145,14 +146,10 @@ process_corrections:
LOGERR("Lost connection with stepper server"); LOGERR("Lost connection with stepper server");
WARNX("Lost connection with stepper server"); WARNX("Lost connection with stepper server");
} }
LOGDBG("And there"); //LOGDBG("And there");
XYnewline(); XYnewline();
} }
typedef struct{ // statistics: mean and RMS
float xc; float yc; float xsigma; float ysigma;
} ptstat_t;
/** /**
* @brief sumAndStat - calculate statistics in region of interest * @brief sumAndStat - calculate statistics in region of interest
* @param I - image (with background calculated) * @param I - image (with background calculated)
@ -241,6 +238,7 @@ void process_file(Image *I){
DBG("Get sum and stat for simplest centroid"); DBG("Get sum and stat for simplest centroid");
double sum = sumAndStat(I, NULL, 0, &roi, &stat); double sum = sumAndStat(I, NULL, 0, &roi, &stat);
if(sum > 0.){ if(sum > 0.){
I->stat = stat;
if( fabsf(stat.xc - prev_x) > XY_TOLERANCE || if( fabsf(stat.xc - prev_x) > XY_TOLERANCE ||
fabsf(stat.yc - prev_y) > XY_TOLERANCE){ fabsf(stat.yc - prev_y) > XY_TOLERANCE){
DBG("Bad: was x=%d, y=%d; become x=%g, y=%g ==> need fine calculations", prev_x, prev_y, xc, yc); DBG("Bad: was x=%d, y=%d; become x=%g, y=%g ==> need fine calculations", prev_x, prev_y, xc, yc);
@ -248,6 +246,7 @@ void process_file(Image *I){
double WdH = stat.xsigma/stat.ysigma; double WdH = stat.xsigma/stat.ysigma;
// wery approximate area inside sigmax*sigmay // wery approximate area inside sigmax*sigmay
double area = .4 * stat.xsigma * stat.ysigma; double area = .4 * stat.xsigma * stat.ysigma;
I->stat.area = (int)area;
if(!isnan(WdH) && !isinf(WdH) && // if W/H is a number if(!isnan(WdH) && !isinf(WdH) && // if W/H is a number
WdH > theconf.minwh && WdH < theconf.maxwh && // if W/H near circle WdH > theconf.minwh && WdH < theconf.maxwh && // if W/H near circle
area > theconf.minarea && area < theconf.maxarea){ // if star area is in range area > theconf.minarea && area < theconf.maxarea){ // if star area is in range
@ -274,31 +273,38 @@ void process_file(Image *I){
uint8_t *ibin = Im2bin(I, I->background); uint8_t *ibin = Im2bin(I, I->background);
DELTA("Made binary"); DELTA("Made binary");
if(ibin){ if(ibin){
//savebin(ibin, W, H, "binary.fits"); Image *Itmp = bin2Im(ibin, I->width, I->height);
//DELTA("save binary.fits"); Image_write_jpg(Itmp, "binary.jpg", 1);
Image_free(&Itmp);
DELTA("save binary");
uint8_t *er = il_erosionN(ibin, W, H, theconf.Nerosions); uint8_t *er = il_erosionN(ibin, W, H, theconf.Nerosions);
FREE(ibin); FREE(ibin);
DELTA("Erosion"); DELTA("Erosion");
//savebin(er, W, H, "erosion.fits"); Itmp = bin2Im(er, I->width, I->height);
//DELTA("Save erosion"); Image_write_jpg(Itmp, "erosion.jpg", 1);
Image_free(&Itmp);
DELTA("Save erosion");
uint8_t *opn = il_dilationN(er, W, H, theconf.Ndilations); uint8_t *opn = il_dilationN(er, W, H, theconf.Ndilations);
FREE(er); FREE(er);
DELTA("Opening"); DELTA("Opening");
//savebin(opn, W, H, "opening.fits"); Itmp = bin2Im(opn, I->width, I->height);
//DELTA("Save opening"); Image_write_jpg(Itmp, "opening.jpg", 1);
Image_free(&Itmp);
DELTA("Save opening");
S = il_cclabel4(opn, W, H, &cc); S = il_cclabel4(opn, W, H, &cc);
FREE(opn); FREE(opn);
DBG("Nobj=%zd", cc->Nobj-1); if(S && cc) DBG("Nobj=%zd", cc->Nobj-1);
if(S && cc && cc->Nobj > 1){ // Nobj = amount of objects + 1 if(S && cc && cc->Nobj > 1){ // Nobj = amount of objects + 1
DBGLOG("Nobj=%zd", cc->Nobj-1); DBGLOG("Nobj=%zd", cc->Nobj-1);
if(Nallocated < cc->Nobj-1){ if(Nallocated < cc->Nobj-1){
Nallocated = cc->Nobj-1; Nallocated = cc->Nobj-1;
Objects = realloc(Objects, Nallocated*sizeof(object)); Objects = realloc(Objects, Nallocated*sizeof(object));
} }
I->stat.area = cc->boxes[1].area;
for(size_t i = 1; i < cc->Nobj; ++i){ for(size_t i = 1; i < cc->Nobj; ++i){
il_Box *b = &cc->boxes[i]; il_Box *b = &cc->boxes[i];
double wh = ((double)b->xmax - b->xmin)/(b->ymax - b->ymin); double wh = ((double)b->xmax - b->xmin)/(b->ymax - b->ymin);
//DBG("Obj# %zd: wh=%g, area=%d", i, wh, b->area); DBG("Obj# %zd: wh=%g, area=%d", i, wh, b->area);
if(wh < theconf.minwh || wh > theconf.maxwh) continue; if(wh < theconf.minwh || wh > theconf.maxwh) continue;
if((int)b->area < theconf.minarea || (int)b->area > theconf.maxarea) continue; if((int)b->area < theconf.minarea || (int)b->area > theconf.maxarea) continue;
ptstat_t stat; ptstat_t stat;

View File

@ -86,8 +86,8 @@ steppersproc *theSteppers = NULL;
// stepper numbers // stepper numbers
typedef enum{ typedef enum{
Ustepper = 0, Ustepper = 0,
Vstepper = 2, Vstepper = 1,
Fstepper = 1, Fstepper = 2,
} stepperno; } stepperno;
const char *motornames[NMOTORS] = { const char *motornames[NMOTORS] = {
@ -200,6 +200,7 @@ static void stp_disc(){
static void stp_disconnect(){ static void stp_disconnect(){
DBG("Try to disconnect"); DBG("Try to disconnect");
LOGDBG("Try to disconnect");
if(serialsock){ if(serialsock){
DBG("Close socket"); DBG("Close socket");
sl_sock_delete(&serialsock); sl_sock_delete(&serialsock);
@ -292,9 +293,8 @@ static void parse_msg(char *msg){
for(int idx = 0; idx < CMD_AMOUNT; ++idx){ for(int idx = 0; idx < CMD_AMOUNT; ++idx){
// search index in commands // search index in commands
if(0 == strcmp(stp_commands[idx], key)){ // found our if(0 == strcmp(stp_commands[idx], key)){ // found our
free(key);
//LOGDBG("OK, idx=%d, cmd=%s", idx, stp_commands[idx]); //LOGDBG("OK, idx=%d, cmd=%s", idx, stp_commands[idx]);
parser(idx, parno, ival); LastErr = parser(idx, parno, ival);
break; break;
} }
} }
@ -323,14 +323,19 @@ static errcodes send_message(steppercmd idx, char *msg){
if(!msg) msglen = snprintf(buf, 255, "%s\n", stp_commands[idx]); if(!msg) msglen = snprintf(buf, 255, "%s\n", stp_commands[idx]);
else msglen = snprintf(buf, 255, "%s%s\n", stp_commands[idx], msg); else msglen = snprintf(buf, 255, "%s%s\n", stp_commands[idx], msg);
//DBG("Send message '%s', len %zd", buf, msglen); //DBG("Send message '%s', len %zd", buf, msglen);
LastErr = ERR_AMOUNT;
if(sl_sock_sendstrmessage(serialsock, buf) != (ssize_t)msglen){ if(sl_sock_sendstrmessage(serialsock, buf) != (ssize_t)msglen){
WARN("send()"); WARN("send()");
LOGWARN("send_message(): send() failed"); LOGWARN("send_message(): send() failed");
return ERR_WRONGLEN; return ERR_WRONGLEN;
} }
LOGDBG("Message '%s' sent", buf); //LOGDBG("send_message(): message '%s' sent", buf);
;;; // wait for errcode double t0 = sl_dtime();
return ERR_OK; while(sl_dtime() - t0 < STEPPERS_NOANS_TIMEOUT){
if(LastErr != ERR_AMOUNT) return LastErr;
}
LOGWARN("send_message(): got NO answer for %s%s", stp_commands[idx], msg);
return ERR_CANTRUN;
} }
// send command cmd to n'th motor with param p, @return FALSE if failed // send command cmd to n'th motor with param p, @return FALSE if failed
@ -392,20 +397,24 @@ void *clientproc(void _U_ *par){
FNAME(); FNAME();
char rbuf[BUFSIZ]; char rbuf[BUFSIZ];
if(!serialsock) return NULL; if(!serialsock) return NULL;
double t0 = sl_dtime();
do{ do{
ssize_t got = sl_sock_readline(serialsock, rbuf, BUFSIZ); ssize_t got = sl_sock_readline(serialsock, rbuf, BUFSIZ);
//LOGDBG("got=%zd", got); //LOGDBG("got=%zd", got);
if(got < 0){ // disconnected if(got < 0 || sl_dtime() - t0 > STEPPERS_NOANS_TIMEOUT){ // disconnected
WARNX("Serial server disconnected"); WARNX("Serial server disconnected");
LOGERR("Serial server disconnected (timeout reached)");
if(serialsock) sl_sock_delete(&serialsock); if(serialsock) sl_sock_delete(&serialsock);
state = STP_DISCONN;
return NULL; return NULL;
}else if(got == 0){ // nothing to read from serial port }else if(got == 0){ // nothing to read from serial port
usleep(1000); usleep(1000);
continue; continue;
} }
//LOGDBG("clientproc(): got '%s'", rbuf);
// process data // process data
DBG("GOT: %s", rbuf);
parse_msg(rbuf); parse_msg(rbuf);
t0 = sl_dtime();
} while(serialsock && serialsock->connected); } while(serialsock && serialsock->connected);
WARNX("disconnected"); WARNX("disconnected");
if(serialsock) sl_sock_delete(&serialsock); if(serialsock) sl_sock_delete(&serialsock);
@ -458,9 +467,9 @@ static void process_movetomiddle_stage(){
case SETUP_WAITUV0: // wait for all coordinates moving to zero case SETUP_WAITUV0: // wait for all coordinates moving to zero
if(!relaxed(Ustepper) || !relaxed(Vstepper) || !relaxed(Fstepper)) break; // didn't reach yet if(!relaxed(Ustepper) || !relaxed(Vstepper) || !relaxed(Fstepper)) break; // didn't reach yet
// now all motors are stopped -> send positions to zero // now all motors are stopped -> send positions to zero
if( !nth_motor_setter(CMD_ABSPOS, Ustepper, 1) || if( !nth_motor_setter(CMD_ABSPOS, Ustepper, 0) ||
!nth_motor_setter(CMD_ABSPOS, Vstepper, 1) || !nth_motor_setter(CMD_ABSPOS, Vstepper, 0) ||
!nth_motor_setter(CMD_ABSPOS, Fstepper, 1)) break; !nth_motor_setter(CMD_ABSPOS, Fstepper, 0)) break;
DBG("Reached UVF0!"); DBG("Reached UVF0!");
// goto // goto
if(nth_motor_setter(CMD_GOTO, Ustepper, (theconf.maxUpos + theconf.minUpos)/2) && if(nth_motor_setter(CMD_GOTO, Ustepper, (theconf.maxUpos + theconf.minUpos)/2) &&
@ -508,8 +517,8 @@ static void process_setup_stage(){
case SETUP_WAITUV0: // wait for both coordinates moving to zero case SETUP_WAITUV0: // wait for both coordinates moving to zero
if(!relaxed(Ustepper) || !relaxed(Vstepper)) break; if(!relaxed(Ustepper) || !relaxed(Vstepper)) break;
// set current position to 0 // set current position to 0
if( !nth_motor_setter(CMD_ABSPOS, Ustepper, 1) || if( !nth_motor_setter(CMD_ABSPOS, Ustepper, 0) ||
!nth_motor_setter(CMD_ABSPOS, Vstepper, 1)) break; !nth_motor_setter(CMD_ABSPOS, Vstepper, 0)) break;
DBG("ZERO border reached"); DBG("ZERO border reached");
// goto middle // goto middle
if(nth_motor_setter(CMD_GOTO, Ustepper, (theconf.maxUpos+theconf.minUpos)/2) && if(nth_motor_setter(CMD_GOTO, Ustepper, (theconf.maxUpos+theconf.minUpos)/2) &&
@ -901,30 +910,38 @@ static void *stp_process_states(_U_ void *arg){
stp_connect_server(); stp_connect_server();
continue; continue;
} }
// check request to change focus
if(chfocus){
DBG("Try to move F to %d", newfocpos);
if(nth_motor_setter(CMD_GOTO, Fstepper, newfocpos)) chfocus = FALSE;
}
if(dUmove){
DBG("Try to move U by %d", dUmove);
if(nth_motor_setter(CMD_RELPOS, Ustepper, dUmove)) dUmove = 0;
}
if(dVmove){
DBG("Try to move V by %d", dVmove);
if(nth_motor_setter(CMD_RELPOS, Vstepper, dVmove)) dVmove = 0;
}
static double t0 = -1.; static double t0 = -1.;
if(t0 < 0.) t0 = sl_dtime(); if(t0 < 0.) t0 = sl_dtime();
if(state != STP_DISCONN){ if(state != STP_DISCONN){
if(sl_dtime() - t0 >= 0.1){ // each 0.1s check state if steppers aren't disconnected if(sl_dtime() - t0 >= 0.1){ // each 0.1s check state if steppers aren't disconnected
t0 = sl_dtime(); t0 = sl_dtime();
chkall(); chkall();
}
if(!relaxed(Ustepper) && !relaxed(Vstepper)) continue; if(!relaxed(Ustepper) && !relaxed(Vstepper)) continue;
first = TRUE; first = TRUE;
}else continue;
} }
// if we are here, all U/V moving is finished // if we are here, all U/V moving is finished
// check request to change focus
if(chfocus){
DBG("Try to move F to %d", newfocpos);
if(nth_motor_setter(CMD_GOTO, Fstepper, newfocpos)){
chfocus = FALSE;
}
}
if(dUmove){
DBG("Try to move U by %d", dUmove);
if(nth_motor_setter(CMD_RELPOS, Ustepper, dUmove)){
dUmove = 0;
continue;
}
}
if(dVmove){
DBG("Try to move V by %d", dVmove);
if(nth_motor_setter(CMD_RELPOS, Vstepper, dVmove)){
dVmove = 0;
continue;
}
}
switch(state){ // steppers state machine switch(state){ // steppers state machine
case STP_DISCONN: case STP_DISCONN:
if(!stp_connect_server()){ if(!stp_connect_server()){
@ -933,7 +950,7 @@ static void *stp_process_states(_U_ void *arg){
LOGWARN("Can't reconnect"); LOGWARN("Can't reconnect");
first = FALSE; first = FALSE;
} }
sleep(5); sleep(1);
} }
break; break;
case STP_SETUP: // setup axes (before this state set Xtarget/Ytarget in improc.c) case STP_SETUP: // setup axes (before this state set Xtarget/Ytarget in improc.c)

View File

@ -18,6 +18,9 @@
#pragma once #pragma once
// timeout for "no answer from motors", seconds
#define STEPPERS_NOANS_TIMEOUT (5.)
// set state to `disconnect` after this amount of errors in `moving_finished` // set state to `disconnect` after this amount of errors in `moving_finished`
#define MAX_ERR_CTR (15) #define MAX_ERR_CTR (15)