PID seems like almost working, but I have a great problem with model!
This commit is contained in:
parent
864e257884
commit
138e4bf84d
@ -54,7 +54,7 @@ void pid_delete(PIDController_t **pid){
|
||||
double pid_calculate(PIDController_t *pid, double error, double dt){
|
||||
// calculate flowing integral
|
||||
double oldi = pid->pidIarray[pid->curIidx], newi = error * dt;
|
||||
DBG("oldi/new: %g, %g", oldi, newi);
|
||||
//DBG("oldi/new: %g, %g", oldi, newi);
|
||||
pid->pidIarray[pid->curIidx++] = newi;
|
||||
if(pid->curIidx >= pid->pidIarrSize) pid->curIidx = 0;
|
||||
pid->integral += newi - oldi;
|
||||
@ -71,68 +71,79 @@ typedef struct{
|
||||
} PIDpair_t;
|
||||
|
||||
typedef struct{
|
||||
axis_status_t *state;
|
||||
axis_status_t state;
|
||||
coordval_t position;
|
||||
coordval_t speed;
|
||||
} axisdata_t;
|
||||
/**
|
||||
* @brief process - Process PID for given axe
|
||||
* @brief process - Process PID for given axis
|
||||
* @param tagpos - given coordinate of target position
|
||||
* @param endpoint - endpoint for this coordinate
|
||||
* @param pid - pid itself
|
||||
* @return calculated new speed or -1 for max speed
|
||||
*/
|
||||
static double getspeed(const coordval_t *tagpos, PIDpair_t *pidpair, axisdata_t *axis){
|
||||
if(tagpos->t < axis->position.t || tagpos->t - axis->position.t > MCC_PID_MAX_DT) return axis->speed.val; // data is too old or wrong
|
||||
if(tagpos->t < axis->position.t || tagpos->t - axis->position.t > MCC_PID_MAX_DT){
|
||||
DBG("target time: %g, axis time: %g - too big! (%g)", tagpos->t, axis->position.t, MCC_PID_MAX_DT);
|
||||
return axis->speed.val; // data is too old or wrong
|
||||
}
|
||||
double error = tagpos->val - axis->position.val, fe = fabs(error);
|
||||
PIDController_t *pid = NULL;
|
||||
switch(*axis->state){
|
||||
switch(axis->state){
|
||||
case AXIS_SLEWING:
|
||||
if(fe < MCC_MAX_POINTING_ERR){
|
||||
*axis->state = AXIS_POINTING;
|
||||
DBG("--> Pointing\n");
|
||||
axis->state = AXIS_POINTING;
|
||||
DBG("--> Pointing");
|
||||
pid = pidpair->PIDC;
|
||||
}else{
|
||||
DBG("Slewing...\n");
|
||||
DBG("Slewing...");
|
||||
return -1.; // max speed for given axis
|
||||
}
|
||||
break;
|
||||
case AXIS_POINTING:
|
||||
if(fe < MCC_MAX_GUIDING_ERR){
|
||||
*axis->state = AXIS_GUIDING;
|
||||
DBG("--> Guiding\n");
|
||||
axis->state = AXIS_GUIDING;
|
||||
DBG("--> Guiding");
|
||||
pid = pidpair->PIDV;
|
||||
}else if(fe > MCC_MAX_POINTING_ERR){
|
||||
DBG("--> Slewing\n");
|
||||
*axis->state = AXIS_SLEWING;
|
||||
DBG("--> Slewing");
|
||||
axis->state = AXIS_SLEWING;
|
||||
return -1.;
|
||||
} else pid = pidpair->PIDC;
|
||||
break;
|
||||
case AXIS_GUIDING:
|
||||
pid = pidpair->PIDV;
|
||||
if(fe > MCC_MAX_GUIDING_ERR){
|
||||
DBG("--> Pointing\n");
|
||||
*axis->state = AXIS_POINTING;
|
||||
DBG("--> Pointing");
|
||||
axis->state = AXIS_POINTING;
|
||||
pid = pidpair->PIDC;
|
||||
}else if(fe < MCC_MAX_ATTARGET_ERR){
|
||||
DBG("At target\n");
|
||||
DBG("At target");
|
||||
// TODO: we can point somehow that we are at target or introduce new axis state
|
||||
}else DBG("Current error: %g\n", fe);
|
||||
}else DBG("Current error: %g", fe);
|
||||
break;
|
||||
case AXIS_STOPPED:
|
||||
case AXIS_STOPPED: // start pointing to target; will change speed next time
|
||||
DBG("AXIS STOPPED!!!!");
|
||||
axis->state = AXIS_SLEWING;
|
||||
return -1.;
|
||||
case AXIS_ERROR:
|
||||
DBG("Can't move from erroneous state");
|
||||
return 0.;
|
||||
}
|
||||
if(!pid){
|
||||
DBG("WTF? Where is a PID?");
|
||||
return axis->speed.val;
|
||||
}
|
||||
if(tagpos->t < pid->prevT || tagpos->t - pid->prevT > MCC_PID_MAX_DT) pid_clear(pid);
|
||||
if(tagpos->t < pid->prevT || tagpos->t - pid->prevT > MCC_PID_MAX_DT){
|
||||
DBG("time diff too big: clear PID");
|
||||
pid_clear(pid);
|
||||
}
|
||||
double dt = tagpos->t - pid->prevT;
|
||||
if(dt > MCC_PID_MAX_DT) dt = MCC_PID_CYCLE_TIME;
|
||||
pid->prevT = tagpos->t;
|
||||
//DBG("CALC PID (er=%g, dt=%g)", error, dt);
|
||||
double tagspeed = pid_calculate(pid, error, dt);
|
||||
if(*axis->state == AXIS_GUIDING) return axis->speed.val + tagspeed; // velocity-based
|
||||
if(axis->state == AXIS_GUIDING) return axis->speed.val + tagspeed; // velocity-based
|
||||
return tagspeed; // coordinate-based
|
||||
}
|
||||
|
||||
@ -159,16 +170,24 @@ mcc_errcodes_t correct2(const coordval_pair_t *target, const coordpair_t *endpoi
|
||||
mountdata_t m;
|
||||
coordpair_t tagspeed;
|
||||
if(MCC_E_OK != Mount.getMountData(&m)) return MCC_E_FAILED;
|
||||
axisdata_t axe;
|
||||
axe.state = &m.Xstate;
|
||||
axe.position = m.encXposition;
|
||||
axe.speed = m.encXspeed;
|
||||
tagspeed.X = getspeed(&target->X, &pidX, &axe);
|
||||
axisdata_t axis;
|
||||
DBG("state: %d/%d", m.Xstate, m.Ystate);
|
||||
axis.state = m.Xstate;
|
||||
axis.position = m.encXposition;
|
||||
axis.speed = m.encXspeed;
|
||||
tagspeed.X = getspeed(&target->X, &pidX, &axis);
|
||||
if(tagspeed.X < 0. || tagspeed.X > MCC_MAX_X_SPEED) tagspeed.X = MCC_MAX_X_SPEED;
|
||||
axe.state = &m.Ystate;
|
||||
axe.position = m.encYposition;
|
||||
axe.speed = m.encYspeed;
|
||||
tagspeed.Y = getspeed(&target->Y, &pidY, &axe);
|
||||
axis_status_t xstate = axis.state;
|
||||
axis.state = m.Ystate;
|
||||
axis.position = m.encYposition;
|
||||
axis.speed = m.encYspeed;
|
||||
tagspeed.Y = getspeed(&target->Y, &pidY, &axis);
|
||||
if(tagspeed.Y < 0. || tagspeed.Y > MCC_MAX_Y_SPEED) tagspeed.Y = MCC_MAX_Y_SPEED;
|
||||
axis_status_t ystate = axis.state;
|
||||
if(m.Xstate != xstate || m.Ystate != ystate){
|
||||
DBG("State changed");
|
||||
setStat(xstate, ystate);
|
||||
}
|
||||
DBG("TAG speeds: %g/%g", tagspeed.X, tagspeed.Y);
|
||||
return Mount.moveWspeed(endpoint, &tagspeed);
|
||||
}
|
||||
|
||||
@ -51,10 +51,10 @@ static sl_option_t confopts[] = {
|
||||
end_option
|
||||
};
|
||||
|
||||
static void dumpaxe(char axe, axe_config_t *c){
|
||||
static void dumpaxis(char axis, axis_config_t *c){
|
||||
#define STRUCTPAR(p) (c)->p
|
||||
#define DUMP(par) do{printf("%c%s=%g\n", axe, #par, STRUCTPAR(par));}while(0)
|
||||
#define DUMPD(par) do{printf("%c%s=%g\n", axe, #par, RAD2DEG(STRUCTPAR(par)));}while(0)
|
||||
#define DUMP(par) do{printf("%c%s=%g\n", axis, #par, STRUCTPAR(par));}while(0)
|
||||
#define DUMPD(par) do{printf("%c%s=%g\n", axis, #par, RAD2DEG(STRUCTPAR(par)));}while(0)
|
||||
DUMPD(accel);
|
||||
DUMPD(backlash);
|
||||
DUMPD(errlimit);
|
||||
@ -99,12 +99,12 @@ static void dumpHWconf(){
|
||||
#define DUMPD(par) do{printf("%s=%g\n", #par, RAD2DEG(STRUCTPAR(par)));}while(0)
|
||||
#define DUMPU8(par) do{printf("%s=%u\n", #par, (uint8_t)STRUCTPAR(par));}while(0)
|
||||
#define DUMPU32(par) do{printf("%s=%u\n", #par, (uint32_t)STRUCTPAR(par));}while(0)
|
||||
green("X axe configuration:\n");
|
||||
dumpaxe('X', &HW.Xconf);
|
||||
green("X axis configuration:\n");
|
||||
dumpaxis('X', &HW.Xconf);
|
||||
green("X bits:\n");
|
||||
dumpxbits(&HW.xbits);
|
||||
green("Y axe configuration:\n");
|
||||
dumpaxe('Y', &HW.Yconf);
|
||||
green("Y axis configuration:\n");
|
||||
dumpaxis('Y', &HW.Yconf);
|
||||
green("Y bits:\n");
|
||||
dumpybits(&HW.ybits);
|
||||
green("Other:\n");
|
||||
@ -143,10 +143,12 @@ int main(int argc, char** argv){
|
||||
}
|
||||
if(MCC_E_OK != Mount.init(sconf)) ERRX("Can't init mount");
|
||||
if(MCC_E_OK != Mount.getHWconfig(&HW)) ERRX("Can't read configuration");
|
||||
/*
|
||||
char *c = sl_print_opts(confopts, TRUE);
|
||||
green("Got configuration:\n");
|
||||
printf("%s\n", c);
|
||||
FREE(c);
|
||||
*/
|
||||
dumpHWconf();
|
||||
/*
|
||||
if(G.hwconffile && G.writeconf){
|
||||
|
||||
@ -31,14 +31,18 @@ static conf_t Config = {
|
||||
.EncoderReqInterval = 0.05,
|
||||
.SepEncoder = 2,
|
||||
.EncoderSpeedInterval = 0.1,
|
||||
.XPIDC.P = 0.5,
|
||||
.XPIDC.D = 0.05,
|
||||
.XPIDV.P = 0.5,
|
||||
.XPIDV.D = 0.05,
|
||||
.YPIDC.P = 0.5,
|
||||
.YPIDC.D = 0.05,
|
||||
.XPIDC.P = 0.8,
|
||||
.XPIDC.I = 0.1,
|
||||
.XPIDC.D = 0.3,
|
||||
.XPIDV.P = 1.,
|
||||
.XPIDV.I = 0.01,
|
||||
.XPIDV.D = 0.2,
|
||||
.YPIDC.P = 0.8,
|
||||
.YPIDC.I = 0.1,
|
||||
.YPIDC.D = 0.3,
|
||||
.YPIDV.P = 0.5,
|
||||
.YPIDV.D = 0.05,
|
||||
.YPIDV.I = 0.2,
|
||||
.YPIDV.D = 0.5,
|
||||
};
|
||||
|
||||
static sl_option_t opts[] = {
|
||||
|
||||
@ -127,7 +127,7 @@ void dumpmoving(FILE *fcoords, double t, int N){
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief waitmoving - wait until moving by both axes stops at least for N cycles
|
||||
* @brief waitmoving - wait until moving by both axiss stops at least for N cycles
|
||||
* @param N - amount of stopped cycles
|
||||
*/
|
||||
void waitmoving(int N){
|
||||
|
||||
@ -38,11 +38,12 @@ typedef struct{
|
||||
double X0; // starting point of traectory (-30..30 degr)
|
||||
double Y0; // -//-
|
||||
char *coordsoutput; // dump file
|
||||
char *errlog; // log with position errors
|
||||
char *tfn; // traectory function name
|
||||
char *conffile;
|
||||
} parameters;
|
||||
|
||||
static FILE *fcoords = NULL;
|
||||
static FILE *fcoords = NULL, *errlog = NULL;
|
||||
static pthread_t dthr;
|
||||
static parameters G = {
|
||||
.Ncycles = 40,
|
||||
@ -61,12 +62,13 @@ static sl_option_t cmdlnopts[] = {
|
||||
{"coordsfile", NEED_ARG, NULL, 'o', arg_string, APTR(&G.coordsoutput),"output file with coordinates log"},
|
||||
{"reqinterval", NEED_ARG, NULL, 'i', arg_double, APTR(&G.reqint), "mount requests interval (default: 0.1 second)"},
|
||||
{"traectory", NEED_ARG, NULL, 't', arg_string, APTR(&G.tfn), "used traectory function (default: sincos)"},
|
||||
{"xmax", NEED_ARG, NULL, 'X', arg_double, APTR(&G.Xmax), "maximal X coordinate for traectory (default: 45 degrees)"},
|
||||
{"ymax", NEED_ARG, NULL, 'Y', arg_double, APTR(&G.Ymax), "maximal X coordinate for traectory (default: 45 degrees)"},
|
||||
{"xmax", NEED_ARG, NULL, 'X', arg_double, APTR(&G.Xmax), "maximal abs X coordinate for traectory (default: 45 degrees)"},
|
||||
{"ymax", NEED_ARG, NULL, 'Y', arg_double, APTR(&G.Ymax), "maximal abs Y coordinate for traectory (default: 45 degrees)"},
|
||||
{"tmax", NEED_ARG, NULL, 'T', arg_double, APTR(&G.tmax), "maximal duration time of emulation (default: 300 seconds)"},
|
||||
{"x0", NEED_ARG, NULL, '0', arg_double, APTR(&G.X0), "starting X-coordinate of traectory (default: 10 degrees)"},
|
||||
{"y0", NEED_ARG, NULL, '1', arg_double, APTR(&G.Y0), "starting Y-coordinate of traectory (default: 10 degrees)"},
|
||||
{"conffile", NEED_ARG, NULL, 'C', arg_string, APTR(&G.conffile), "configuration file name"},
|
||||
{"errlog", NEED_ARG, NULL, 'e', arg_string, APTR(&G.errlog), "file with errors log"},
|
||||
end_option
|
||||
};
|
||||
|
||||
@ -76,6 +78,8 @@ void signals(int sig){
|
||||
signal(sig, SIG_IGN);
|
||||
DBG("Get signal %d, quit.\n", sig);
|
||||
}
|
||||
Mount.stop();
|
||||
sleep(1);
|
||||
Mount.quit();
|
||||
if(fcoords) fclose(fcoords);
|
||||
exit(sig);
|
||||
@ -90,22 +94,39 @@ static void *dumping(void _U_ *u){
|
||||
static void runtraectory(traectory_fn tfn){
|
||||
if(!tfn) return;
|
||||
coordval_pair_t telXY;
|
||||
coordpair_t traectXY;
|
||||
double t0 = Mount.currentT();
|
||||
double tlast = 0.;
|
||||
coordval_pair_t target;
|
||||
coordpair_t traectXY, endpoint;
|
||||
endpoint.X = G.Xmax, endpoint.Y = G.Ymax;
|
||||
double t0 = Mount.currentT(), tlast = 0.;
|
||||
double tlastX = 0., tlastY = 0.;
|
||||
while(1){
|
||||
if(!telpos(&telXY)){
|
||||
WARNX("No next telescope position");
|
||||
return;
|
||||
}
|
||||
if(telXY.X.t == tlast && telXY.Y.t == tlast) continue; // last measure - don't mind
|
||||
tlast = (telXY.X.t + telXY.Y.t) / 2.;
|
||||
if(telXY.X.t == tlastX && telXY.Y.t == tlastY) continue; // last measure - don't mind
|
||||
DBG("\n\nTELPOS: %g'/%g' measured @ %g/%g", RAD2AMIN(telXY.X.val), RAD2AMIN(telXY.Y.val), telXY.X.t, telXY.Y.t);
|
||||
tlastX = telXY.X.t; tlastY = telXY.Y.t;
|
||||
double t = Mount.currentT();
|
||||
if(telXY.X.val > G.Xmax || telXY.Y.val > G.Ymax || t - t0 > G.tmax) break;
|
||||
if(fabs(telXY.X.val) > G.Xmax || fabs(telXY.Y.val) > G.Ymax || t - t0 > G.tmax) break;
|
||||
if(!traectory_point(&traectXY, t)) break;
|
||||
DBG("%g: dX=%.1f'', dY=%.1f''", t-t0, RAD2ASEC(traectXY.X-telXY.X.val), RAD2ASEC(traectXY.Y-telXY.Y.val));
|
||||
target.X.val = traectXY.X; target.Y.val = traectXY.Y;
|
||||
target.X.t = target.Y.t = t;
|
||||
// check whether we should change direction
|
||||
if(telXY.X.val > traectXY.X) endpoint.X = -G.Xmax;
|
||||
else if(telXY.X.val < traectXY.X) endpoint.X = G.Xmax;
|
||||
if(telXY.Y.val > traectXY.Y) endpoint.Y = -G.Ymax;
|
||||
else if(telXY.Y.val < traectXY.Y) endpoint.Y = G.Ymax;
|
||||
DBG("target: %g'/%g'", RAD2AMIN(traectXY.X), RAD2AMIN(traectXY.Y));
|
||||
DBG("%g: dX=%.4f'', dY=%.4f''", t-t0, RAD2ASEC(traectXY.X-telXY.X.val), RAD2ASEC(traectXY.Y-telXY.Y.val));
|
||||
DBG("Correct to: %g/%g with EP %g/%g", RAD2DEG(target.X.val), RAD2DEG(target.Y.val), RAD2DEG(endpoint.X), RAD2DEG(endpoint.Y));
|
||||
if(errlog)
|
||||
fprintf(errlog, "%10.4g %10.4g %10.4g\n", t, RAD2ASEC(traectXY.X-telXY.X.val), RAD2ASEC(traectXY.Y-telXY.Y.val));
|
||||
if(MCC_E_OK != Mount.correctTo(&target, &endpoint)) WARNX("Error of correction!");
|
||||
while((t = Mount.currentT()) - tlast < MCC_PID_REFRESH_DT) usleep(50);
|
||||
tlast = t;
|
||||
}
|
||||
WARNX("No next traectory point");
|
||||
WARNX("No next traectory point or emulation ends");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv){
|
||||
@ -118,6 +139,12 @@ int main(int argc, char **argv){
|
||||
G.Xmax = DEG2RAD(G.Xmax); G.Ymax = DEG2RAD(G.Ymax);
|
||||
if(G.X0 < -30. || G.X0 > 30. || G.Y0 < -30. || G.Y0 > 30.)
|
||||
ERRX("X0 and Y0 should be -30..30 degrees");
|
||||
if(G.errlog){
|
||||
if(!(errlog = fopen(G.errlog, "w")))
|
||||
ERRX("Can't open error log %s", G.errlog);
|
||||
else
|
||||
fprintf(errlog, "# time Xerr'' Yerr'' // target - real\n");
|
||||
}
|
||||
if(G.coordsoutput){
|
||||
if(!(fcoords = fopen(G.coordsoutput, "w")))
|
||||
ERRX("Can't open %s", G.coordsoutput);
|
||||
|
||||
@ -20,10 +20,10 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define DEG2RAD(d) (d/180.*M_PI)
|
||||
#define ASEC2RAD(d) (d/180.*M_PI/3600.)
|
||||
#define AMIN2RAD(d) (d/180.*M_PI/60.)
|
||||
#define RAD2DEG(r) (r/M_PI*180.)
|
||||
#define RAD2ASEC(r) (r/M_PI*180.*3600.)
|
||||
#define RAD2AMIN(r) (r/M_PI*180.*60.)
|
||||
#define DEG2RAD(d) ((d)/180.*M_PI)
|
||||
#define ASEC2RAD(d) ((d)/180.*M_PI/3600.)
|
||||
#define AMIN2RAD(d) ((d)/180.*M_PI/60.)
|
||||
#define RAD2DEG(r) ((r)/M_PI*180.)
|
||||
#define RAD2ASEC(r) ((r)/M_PI*180.*3600.)
|
||||
#define RAD2AMIN(r) ((r)/M_PI*180.*60.)
|
||||
|
||||
|
||||
@ -30,10 +30,6 @@ static traectory_fn cur_traectory = NULL;
|
||||
// starting point of traectory
|
||||
static coordpair_t XYstart = {0};
|
||||
static double tstart = 0.;
|
||||
// convert Xe/Ye to approximate motor coordinates:
|
||||
// Xnew = Xcor+Xe; Ynew = Ycor+Ye; as Ye goes backwards to Ym, we have
|
||||
// Xcor = Xm0 - Xe0; Ycor = Xm0 + Ye0
|
||||
static coordval_pair_t XYcor = {0};
|
||||
|
||||
/**
|
||||
* @brief init_traectory - init traectory fn, sync starting positions of motor & encoders
|
||||
@ -52,9 +48,6 @@ int init_traectory(traectory_fn f, coordpair_t *XY0){
|
||||
if(MCC_E_OK == Mount.getMountData(&mdata)) break;
|
||||
}
|
||||
if(ntries == 10) return FALSE;
|
||||
XYcor.X.val = mdata.motXposition.val - mdata.encXposition.val;
|
||||
XYcor.Y.val = mdata.motYposition.val - mdata.encYposition.val;
|
||||
DBG("STARTING POINTS: x=%g, y=%g degrees", DEG2RAD(XYcor.X.val), DEG2RAD(XYcor.Y.val));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -83,8 +76,8 @@ int telpos(coordval_pair_t *curpos){
|
||||
}
|
||||
if(ntries == 10) return FALSE;
|
||||
coordval_pair_t pt;
|
||||
pt.X.val = XYcor.X.val + mdata.encXposition.val;
|
||||
pt.Y.val = XYcor.Y.val + mdata.encYposition.val;
|
||||
pt.X.val = mdata.encXposition.val;
|
||||
pt.Y.val = mdata.encYposition.val;
|
||||
pt.X.t = mdata.encXposition.t;
|
||||
pt.Y.t = mdata.encYposition.t;
|
||||
if(curpos) *curpos = pt;
|
||||
@ -94,7 +87,7 @@ int telpos(coordval_pair_t *curpos){
|
||||
// X=X0+1'/s, Y=Y0+15''/s
|
||||
int Linear(coordpair_t *nextpt, double t){
|
||||
coordpair_t pt;
|
||||
pt.X = XYstart.X + ASEC2RAD(1.) * (t - tstart);
|
||||
pt.X = XYstart.X + ASEC2RAD(0.1) * (t - tstart);
|
||||
pt.Y = XYstart.Y + ASEC2RAD(15.)* (t - tstart);
|
||||
if(nextpt) *nextpt = pt;
|
||||
return TRUE;
|
||||
@ -103,7 +96,7 @@ int Linear(coordpair_t *nextpt, double t){
|
||||
// X=X0+5'*sin(t/30*2pi), Y=Y0+10'*cos(t/200*2pi)
|
||||
int SinCos(coordpair_t *nextpt, double t){
|
||||
coordpair_t pt;
|
||||
pt.X = XYstart.X + AMIN2RAD(5.) * sin((t-tstart)/30.*2*M_PI);
|
||||
pt.X = XYstart.X + ASEC2RAD(5.) * sin((t-tstart)/30.*2*M_PI);
|
||||
pt.Y = XYstart.Y + AMIN2RAD(10.)* cos((t-tstart)/200.*2*M_PI);
|
||||
if(nextpt) *nextpt = pt;
|
||||
return TRUE;
|
||||
@ -116,8 +109,8 @@ typedef struct{
|
||||
} tr_names;
|
||||
|
||||
static tr_names names[] = {
|
||||
{Linear, "linear", "X=X0+1'/s, Y=Y0+15''/s"},
|
||||
{SinCos, "sincos", "X=X0+5'*sin(t/30*2pi), Y=Y0+10'*cos(t/200*2pi)"},
|
||||
{Linear, "linear", "X=X0+0.1''/s, Y=Y0+15''/s"},
|
||||
{SinCos, "sincos", "X=X0+5''*sin(t/30*2pi), Y=Y0+10'*cos(t/200*2pi)"},
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@ -86,7 +86,6 @@ void getModData(mountdata_t *mountdata){
|
||||
if(Xst == ST_MOVE) Xst = Xmodel->proc_move(Xmodel, &Xp, tnow);
|
||||
movestate_t Yst = Ymodel->get_state(Ymodel, &Yp);
|
||||
if(Yst == ST_MOVE) Yst = Ymodel->proc_move(Ymodel, &Yp, tnow);
|
||||
bzero(mountdata, sizeof(mountdata_t));
|
||||
mountdata->motXposition.t = mountdata->encXposition.t = mountdata->motYposition.t = mountdata->encYposition.t = tnow;
|
||||
mountdata->motXposition.val = mountdata->encXposition.val = Xp.coord;
|
||||
mountdata->motYposition.val = mountdata->encYposition.val = Yp.coord;
|
||||
@ -210,6 +209,22 @@ static int chkYs(double s){
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// set SLEWING state if axis was stopped later
|
||||
static void setslewingstate(){
|
||||
//FNAME();
|
||||
mountdata_t d;
|
||||
if(MCC_E_OK == getMD(&d)){
|
||||
axis_status_t newx = d.Xstate, newy = d.Ystate;
|
||||
//DBG("old state: %d/%d", d.Xstate, d.Ystate);
|
||||
if(d.Xstate == AXIS_STOPPED) newx = AXIS_SLEWING;
|
||||
if(d.Ystate == AXIS_STOPPED) newy = AXIS_SLEWING;
|
||||
if(newx != d.Xstate || newy != d.Ystate){
|
||||
DBG("Started moving -> slew");
|
||||
setStat(newx, newy);
|
||||
}
|
||||
}else DBG("CAN't GET MOUNT DATA!");
|
||||
}
|
||||
|
||||
/*
|
||||
static mcc_errcodes_t slew2(const coordpair_t *target, slewflags_t flags){
|
||||
(void)target;
|
||||
@ -241,7 +256,7 @@ static mcc_errcodes_t move2(const coordpair_t *target){
|
||||
cmd.Yspeed = MCC_MAX_Y_SPEED;
|
||||
mcc_errcodes_t r = shortcmd(&cmd);
|
||||
if(r != MCC_E_OK) return r;
|
||||
setStat(AXIS_SLEWING, AXIS_SLEWING);
|
||||
setslewingstate();
|
||||
return MCC_E_OK;
|
||||
}
|
||||
|
||||
@ -279,7 +294,7 @@ static mcc_errcodes_t move2s(const coordpair_t *target, const coordpair_t *speed
|
||||
cmd.Yspeed = speed->Y;
|
||||
mcc_errcodes_t r = shortcmd(&cmd);
|
||||
if(r != MCC_E_OK) return r;
|
||||
setStat(AXIS_SLEWING, AXIS_SLEWING);
|
||||
setslewingstate();
|
||||
return MCC_E_OK;
|
||||
}
|
||||
|
||||
@ -288,6 +303,7 @@ static mcc_errcodes_t move2s(const coordpair_t *target, const coordpair_t *speed
|
||||
* @return errcode
|
||||
*/
|
||||
static mcc_errcodes_t emstop(){
|
||||
FNAME();
|
||||
if(Conf.RunModel){
|
||||
double curt = nanotime();
|
||||
Xmodel->emergency_stop(Xmodel, curt);
|
||||
@ -299,6 +315,7 @@ static mcc_errcodes_t emstop(){
|
||||
}
|
||||
// normal stop
|
||||
static mcc_errcodes_t stop(){
|
||||
FNAME();
|
||||
if(Conf.RunModel){
|
||||
double curt = nanotime();
|
||||
Xmodel->stop(Xmodel, curt);
|
||||
@ -323,6 +340,7 @@ static mcc_errcodes_t shortcmd(short_command_t *cmd){
|
||||
if(!model_move2(Xmodel, ¶m, curt)) return MCC_E_FAILED;
|
||||
param.coord = cmd->Ymot; param.speed = cmd->Yspeed;
|
||||
if(!model_move2(Ymodel, ¶m, curt)) return MCC_E_FAILED;
|
||||
setslewingstate();
|
||||
return MCC_E_OK;
|
||||
}
|
||||
SSscmd s = {0};
|
||||
@ -336,6 +354,7 @@ static mcc_errcodes_t shortcmd(short_command_t *cmd){
|
||||
s.YBits = cmd->YBits;
|
||||
DBG("X->%d, Y->%d, Xs->%d, Ys->%d", s.Xmot, s.Ymot, s.Xspeed, s.Yspeed);
|
||||
if(!cmdS(&s)) return MCC_E_FAILED;
|
||||
setslewingstate();
|
||||
return MCC_E_OK;
|
||||
}
|
||||
|
||||
@ -353,6 +372,7 @@ static mcc_errcodes_t longcmd(long_command_t *cmd){
|
||||
if(!model_move2(Xmodel, ¶m, curt)) return MCC_E_FAILED;
|
||||
param.coord = cmd->Ymot; param.speed = cmd->Yspeed;
|
||||
if(!model_move2(Ymodel, ¶m, curt)) return MCC_E_FAILED;
|
||||
setslewingstate();
|
||||
return MCC_E_OK;
|
||||
}
|
||||
SSlcmd l = {0};
|
||||
@ -365,6 +385,7 @@ static mcc_errcodes_t longcmd(long_command_t *cmd){
|
||||
l.Xatime = S2ADDER(cmd->Xatime);
|
||||
l.Yatime = S2ADDER(cmd->Yatime);
|
||||
if(!cmdL(&l)) return MCC_E_FAILED;
|
||||
setslewingstate();
|
||||
return MCC_E_OK;
|
||||
}
|
||||
|
||||
|
||||
@ -69,7 +69,7 @@ double LS_calc_slope(less_square_t *l, double x, double t);
|
||||
#define COLOR_OLD "\033[0;0;0m"
|
||||
#define FNAME() do{ fprintf(stderr, COLOR_GREEN "\n%s " COLOR_OLD, __func__); \
|
||||
fprintf(stderr, "(%s, line %d)\n", __FILE__, __LINE__);} while(0)
|
||||
#define DBG(...) do{ fprintf(stderr, COLOR_RED "\n%s " COLOR_OLD, __func__); \
|
||||
#define DBG(...) do{ fprintf(stderr, COLOR_RED "%s " COLOR_OLD, __func__); \
|
||||
fprintf(stderr, "(%s, line %d): ", __FILE__, __LINE__); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, "\n");} while(0)
|
||||
|
||||
@ -37,7 +37,10 @@ static void chkminmax(double *min, double *max){
|
||||
movemodel_t *model_init(limits_t *l){
|
||||
if(!l) return FALSE;
|
||||
movemodel_t *m = calloc(1, sizeof(movemodel_t));
|
||||
// we can't use memcpy or assign as Times/Params would be common for all
|
||||
*m = trapez;
|
||||
m->Times = calloc(STAGE_AMOUNT, sizeof(double));
|
||||
m->Params = calloc(STAGE_AMOUNT, sizeof(moveparam_t));
|
||||
moveparam_t *max = &l->max, *min = &l->min;
|
||||
if(min->speed < 0.) min->speed = -min->speed;
|
||||
if(max->speed < 0.) max->speed = -max->speed;
|
||||
|
||||
@ -60,8 +60,8 @@ typedef struct movemodel{
|
||||
moveparam_t Max;
|
||||
movingstage_t movingstage;
|
||||
movestate_t state;
|
||||
double Times[STAGE_AMOUNT];
|
||||
moveparam_t Params[STAGE_AMOUNT];
|
||||
double *Times;
|
||||
moveparam_t *Params;
|
||||
moveparam_t curparams; // init values of limits, jerk
|
||||
int (*calculate)(struct movemodel *m, moveparam_t *target, double t); // calculate stages of traectory beginning from t
|
||||
movestate_t (*proc_move)(struct movemodel *m, moveparam_t *next, double t); // calculate next model point for time t
|
||||
|
||||
@ -23,7 +23,12 @@
|
||||
|
||||
#include "main.h"
|
||||
#include "ramp.h"
|
||||
|
||||
/*
|
||||
#ifdef EBUG
|
||||
#undef DBG
|
||||
#define DBG(...)
|
||||
#endif
|
||||
*/
|
||||
static double coord_tolerance = COORD_TOLERANCE_DEFAULT;
|
||||
|
||||
static void emstop(movemodel_t *m, double _U_ t){
|
||||
@ -66,9 +71,9 @@ ret:
|
||||
* @return FALSE if can't move with given parameters
|
||||
*/
|
||||
static int calc(movemodel_t *m, moveparam_t *x, double t){
|
||||
DBG("coord/speed: %g/%g", x->coord, x->speed);
|
||||
if(!x) return FALSE;
|
||||
pthread_mutex_lock(&m->mutex);
|
||||
DBG("target coord/speed: %g/%g; current coord: %g", x->coord, x->speed, m->curparams.coord);
|
||||
int ret = FALSE;
|
||||
if(x->coord < m->Min.coord || x->coord > m->Max.coord){
|
||||
DBG("Wrong coordinage [%g, %g]", m->Min.coord, m->Max.coord);
|
||||
@ -101,6 +106,33 @@ static int calc(movemodel_t *m, moveparam_t *x, double t){
|
||||
ret = TRUE;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
model_move2 (/home/eddy/C-files/LibSidServo/movingmodel.c, line 63): MOVE to -0.785398 at speed 0.00408621
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 76): target coord/speed: -0.785398/0.00408621; current coord: 0.181616
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 91): Dx=0.967014, sign=-1, dt23=0.0185812, dx23=3.79634e-05
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 101): dt0s=0.0377057, dx0s=0.000156326, curspeed=0.0082919
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 110): SIGN of speed should be changed!
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 215): 0: t=3.9028, coord=0.181616, speed=0.0082919, accel=-0.219911
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 215): 1: t=3.9405, coord=0.181772, speed=0, accel=-0.219911
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 215): 2: t=3.95908, coord=0.181734, speed=-0.00408621, accel=0.219911
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 215): 3: t=3.97766, coord=-0.785398, speed=0, accel=0
|
||||
model_move2 (/home/eddy/C-files/LibSidServo/movingmodel.c, line 63): MOVE to -0.785398 at speed 0.0361538
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 76): target coord/speed: -0.785398/0.0361538; current coord: 0.177343
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 91): Dx=0.962741, sign=-1, dt23=0.218049, dx23=0.00394164
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 101): dt0s=0.185651, dx0s=0.00285737, curspeed=0.0307821
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 110): SIGN of speed should be changed!
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 215): 0: t=3.9028, coord=0.177343, speed=0.0307821, accel=-0.165806
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 215): 1: t=4.08845, coord=0.1802, speed=0, accel=-0.165806
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 215): 2: t=4.3065, coord=0.176259, speed=-0.0361538, accel=0.165806
|
||||
calc (/home/eddy/C-files/LibSidServo/ramp.c, line 215): 3: t=4.52455, coord=-0.785398, speed=0, accel=0
|
||||
proc (/home/eddy/C-files/LibSidServo/ramp.c, line 233): REACHED STOPping stage @ t=3.97837
|
||||
proc (/home/eddy/C-files/LibSidServo/ramp.c, line 235): T[3]=3.97766,
|
||||
proc (/home/eddy/C-files/LibSidServo/ramp.c, line 235): T[2]=3.95908,
|
||||
proc (/home/eddy/C-files/LibSidServo/ramp.c, line 235): T[1]=3.9405,
|
||||
proc (/home/eddy/C-files/LibSidServo/ramp.c, line 235): T[0]=3.9028,
|
||||
|
||||
#endif
|
||||
if(m->curparams.speed * sign < 0. || m->state == ST_STOP || (dx0s > Dx + coord_tolerance)){ // we should change speed sign
|
||||
DBG("SIGN of speed should be changed!");
|
||||
double sign_current = (m->curparams.speed >= 0.) ? 1. : -1.;
|
||||
@ -225,6 +257,11 @@ static movestate_t proc(movemodel_t *m, moveparam_t *next, double t){
|
||||
if(m->movingstage == STAGE_STOPPED){
|
||||
m->curparams.coord = m->Params[STAGE_STOPPED].coord;
|
||||
pthread_mutex_unlock(&m->mutex);
|
||||
DBG("REACHED STOPping stage @ t=%g", t);
|
||||
for(int s = STAGE_STOPPED; s >= 0; --s){
|
||||
DBG("T[%d]=%g, ", s, m->Times[s]);
|
||||
}
|
||||
fflush(stdout);
|
||||
emstop(m, t);
|
||||
goto ret;
|
||||
}
|
||||
|
||||
@ -243,7 +243,10 @@ static int getmntbyte(){
|
||||
if(FD_ISSET(mntfd, &rfds)){
|
||||
ssize_t l = read(mntfd, &byte, 1);
|
||||
//DBG("MNT read=%zd byte=0x%X", l, byte);
|
||||
if(l != 1) return -2; // disconnected ??
|
||||
if(l != 1){
|
||||
DBG("Mount disconnected?");
|
||||
return -2; // disconnected ??
|
||||
}
|
||||
break;
|
||||
} else return -1;
|
||||
}while(1);
|
||||
@ -586,6 +589,7 @@ mcc_errcodes_t getMD(mountdata_t *d){
|
||||
}
|
||||
|
||||
void setStat(axis_status_t Xstate, axis_status_t Ystate){
|
||||
DBG("set x/y state to %d/%d", Xstate, Ystate);
|
||||
pthread_mutex_lock(&datamutex);
|
||||
mountdata.Xstate = Xstate;
|
||||
mountdata.Ystate = Ystate;
|
||||
@ -594,7 +598,10 @@ void setStat(axis_status_t Xstate, axis_status_t Ystate){
|
||||
|
||||
// write-read without locking mutex (to be used inside other functions)
|
||||
static int wr(const data_t *out, data_t *in, int needeol){
|
||||
if((!out && !in) || mntfd < 0) return FALSE;
|
||||
if((!out && !in) || mntfd < 0){
|
||||
DBG("Wrong arguments or no mount fd");
|
||||
return FALSE;
|
||||
}
|
||||
clrmntbuf();
|
||||
//double t0 = nanotime();
|
||||
if(out){
|
||||
|
||||
@ -34,7 +34,7 @@ extern "C"
|
||||
|
||||
// acceptable position error - 0.1''
|
||||
#define MCC_POSITION_ERROR (5e-7)
|
||||
// acceptable disagreement between motor and axe encoders - 2''
|
||||
// acceptable disagreement between motor and axis encoders - 2''
|
||||
#define MCC_ENCODERS_ERROR (1e-7)
|
||||
|
||||
// max speeds (rad/s): xs=10 deg/s, ys=8 deg/s
|
||||
@ -56,10 +56,11 @@ extern "C"
|
||||
// normal PID refresh interval
|
||||
#define MCC_PID_REFRESH_DT (0.1)
|
||||
// boundary conditions for axis state: "slewing/pointing/guiding"
|
||||
// if angle < MCC_MAX_POINTING_ERR, change state from "slewing" to "pointing": 12 degrees
|
||||
#define MCC_MAX_POINTING_ERR (0.20943951)
|
||||
// if angle < MCC_MAX_GUIDING_ERR, chane state from "pointing" to "slewing": 15''
|
||||
#define MCC_MAX_GUIDING_ERR (7.272205e-5)
|
||||
// if angle < MCC_MAX_POINTING_ERR, change state from "slewing" to "pointing": 5 degrees
|
||||
//#define MCC_MAX_POINTING_ERR (0.20943951)
|
||||
#define MCC_MAX_POINTING_ERR (0.08726646)
|
||||
// if angle < MCC_MAX_GUIDING_ERR, chane state from "pointing" to "guiding": 1.5 deg
|
||||
#define MCC_MAX_GUIDING_ERR (0.026179939)
|
||||
// if error less than this value we suppose that target is captured and guiding is good: 0.1''
|
||||
#define MCC_MAX_ATTARGET_ERR (4.8481368e-7)
|
||||
|
||||
@ -89,7 +90,7 @@ typedef struct{
|
||||
double EncoderReqInterval; // interval between subsequent encoder requests (seconds)
|
||||
double EncoderSpeedInterval; // interval between speed calculations
|
||||
int RunModel; // == 1 if you want to use model instead of real mount
|
||||
PIDpar_t XPIDC; // gain parameters of PID for both axes (C - coordinate driven, V - velocity driven)
|
||||
PIDpar_t XPIDC; // gain parameters of PID for both axiss (C - coordinate driven, V - velocity driven)
|
||||
PIDpar_t XPIDV;
|
||||
PIDpar_t YPIDC;
|
||||
PIDpar_t YPIDV;
|
||||
@ -193,7 +194,7 @@ typedef struct{
|
||||
double Yatime; // 28
|
||||
} long_command_t; // long command
|
||||
|
||||
// hardware axe configuration
|
||||
// hardware axis configuration
|
||||
typedef struct{
|
||||
double accel; // Default Acceleration, rad/s^2
|
||||
double backlash; // Backlash (???)
|
||||
@ -204,13 +205,13 @@ typedef struct{
|
||||
double outplimit; // Output Limit, percent (0..100)
|
||||
double currlimit; // Current Limit (A)
|
||||
double intlimit; // Integral Limit (???)
|
||||
} __attribute__((packed)) axe_config_t;
|
||||
} __attribute__((packed)) axis_config_t;
|
||||
|
||||
// hardware configuration
|
||||
typedef struct{
|
||||
axe_config_t Xconf;
|
||||
axis_config_t Xconf;
|
||||
xbits_t xbits;
|
||||
axe_config_t Yconf;
|
||||
axis_config_t Yconf;
|
||||
ybits_t ybits;
|
||||
uint8_t address;
|
||||
double eqrate; // Equatorial Rate (???)
|
||||
|
||||
@ -36,19 +36,18 @@ uint16_t SScalcChecksum(uint8_t *buf, int len){
|
||||
return checksum;
|
||||
}
|
||||
|
||||
|
||||
static void axestat(int32_t *prev, int32_t cur, int *nstopped, axis_status_t *stat){
|
||||
// Next three functions runs under locked mountdata_t mutex and shouldn't call locked it again!!
|
||||
static void chkstopstat(int32_t *prev, int32_t cur, int *nstopped, axis_status_t *stat){
|
||||
if(*prev == INT32_MAX){
|
||||
*stat = AXIS_STOPPED;
|
||||
DBG("START");
|
||||
}else if(*stat != AXIS_STOPPED){
|
||||
if(*prev == cur && ++(*nstopped) > MOTOR_STOPPED_CNT){
|
||||
if(*prev == cur && ++(*nstopped) > MOTOR_STOPPED_CNT){
|
||||
*stat = AXIS_STOPPED;
|
||||
DBG("AXE stopped");
|
||||
DBG("AXIS stopped");
|
||||
}
|
||||
}else if(*prev != cur){
|
||||
DBG("AXE moving");
|
||||
//*stat = AXIS_SLEWING;
|
||||
DBG("AXIS moving");
|
||||
*nstopped = 0;
|
||||
}
|
||||
*prev = cur;
|
||||
@ -57,8 +56,8 @@ static void axestat(int32_t *prev, int32_t cur, int *nstopped, axis_status_t *st
|
||||
static void ChkStopped(const SSstat *s, mountdata_t *m){
|
||||
static int32_t Xmot_prev = INT32_MAX, Ymot_prev = INT32_MAX; // previous coordinates
|
||||
static int Xnstopped = 0, Ynstopped = 0; // counters to get STOPPED state
|
||||
axestat(&Xmot_prev, s->Xmot, &Xnstopped, &m->Xstate);
|
||||
axestat(&Ymot_prev, s->Ymot, &Ynstopped, &m->Ystate);
|
||||
chkstopstat(&Xmot_prev, s->Xmot, &Xnstopped, &m->Xstate);
|
||||
chkstopstat(&Ymot_prev, s->Ymot, &Ynstopped, &m->Ystate);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -191,14 +190,14 @@ mcc_errcodes_t updateMotorPos(){
|
||||
DBG("got; t pos x/y: %g/%g; tnow: %g", md.encXposition.t, md.encYposition.t, t);
|
||||
mcc_errcodes_t OK = MCC_E_OK;
|
||||
if(fabs(md.motXposition.val - md.encXposition.val) > MCC_ENCODERS_ERROR && md.Xstate == AXIS_STOPPED){
|
||||
DBG("NEED to sync X: motors=%g, axes=%g", md.motXposition.val, md.encXposition.val);
|
||||
DBG("NEED to sync X: motors=%g, axiss=%g", md.motXposition.val, md.encXposition.val);
|
||||
if(!SSsetterI(CMD_MOTXSET, X_RAD2MOT(md.encXposition.val))){
|
||||
DBG("Xpos sync failed!");
|
||||
OK = MCC_E_FAILED;
|
||||
}else DBG("Xpos sync OK, Dt=%g", nanotime() - t0);
|
||||
}
|
||||
if(fabs(md.motYposition.val - md.encYposition.val) > MCC_ENCODERS_ERROR && md.Xstate == AXIS_STOPPED){
|
||||
DBG("NEED to sync Y: motors=%g, axes=%g", md.motYposition.val, md.encYposition.val);
|
||||
DBG("NEED to sync Y: motors=%g, axiss=%g", md.motYposition.val, md.encYposition.val);
|
||||
if(!SSsetterI(CMD_MOTYSET, Y_RAD2MOT(md.encYposition.val))){
|
||||
DBG("Ypos sync failed!");
|
||||
OK = MCC_E_FAILED;
|
||||
|
||||
@ -194,8 +194,8 @@
|
||||
#define X_ENC_SIGN (-1.)
|
||||
#define Y_ENC_SIGN (-1.)
|
||||
// encoder position to radians and back
|
||||
#define X_ENC2RAD(n) ang2half(X_ENC_SIGN * 2.*M_PI * ((double)(n-X_ENC_ZERO)) / X_ENC_STEPSPERREV)
|
||||
#define Y_ENC2RAD(n) ang2half(Y_ENC_SIGN * 2.*M_PI * ((double)(n-Y_ENC_ZERO)) / Y_ENC_STEPSPERREV)
|
||||
#define X_ENC2RAD(n) ang2half(X_ENC_SIGN * 2.*M_PI * ((double)((n)-X_ENC_ZERO)) / X_ENC_STEPSPERREV)
|
||||
#define Y_ENC2RAD(n) ang2half(Y_ENC_SIGN * 2.*M_PI * ((double)((n)-Y_ENC_ZERO)) / Y_ENC_STEPSPERREV)
|
||||
#define X_RAD2ENC(r) ((uint32_t)((r) / 2./M_PI * X_ENC_STEPSPERREV))
|
||||
#define Y_RAD2ENC(r) ((uint32_t)((r) / 2./M_PI * Y_ENC_STEPSPERREV))
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user