#include #include #include #include #include #include #include "mainform.h" #include "gaitgen.h" /* function prototypes */ void Load(FL_OBJECT *, long); void Save(FL_OBJECT *, long); void Animate(FL_OBJECT *, long); void AngleUpdate(FL_OBJECT *, long); void About(FL_OBJECT *, long); void HideAbout(int, void *); void TimeDelta(FL_OBJECT *, long); void Init(Window); void DrawLinks(void); void ChangeFrame(FL_OBJECT *, long); void UpdateForm(void); short AConvert(LINK, int); /* variables and pointers */ FD_main *mainform; FD_about *aboutform; static GC gcBox; Display *disp; int displayScreen; ViewInfo views; XSegment sideLinks[SIDE_LINKS]; XSegment frontLinks[FRONT_LINKS]; XSegment topLinks[TOP_LINKS]; XArc heads[3]; int angle[NUM_LINKS]; int acc[NUM_ACC]; int time; char buff[100]; const char *load; const char *save; const char *aboutInfo = "\n@c@m@bGait Generator v0.1\n @c@iElliot Nicholls \n @cThe University of Western Australia\n\n @cThis program is used to generate gaits for the\n @cbipedal walking robot. For more information see\n @cthe documentation."; ANGLES *angles; ANGLES *currAngle; int *times; int *currTime; ACCDATA *accData; ACCDATA *currAccData; int numFrames; int offset[9] = {128, 128, 128, 128, 128, 128, 128, 128, 128}; int sFact[9] = {-508, -133, -133, 133, -423, -133, 133, 133, -508}; /* main program: create forms, call initialise variables/pointers and pass control to the event driving libforms (xforms) engine */ void main(int argc, char *argv[]) { disp = fl_initialize(&argc, argv, "Gait Generator", 0, 0); mainform = create_form_main(); aboutform = create_form_about(); fl_show_form(mainform->main,FL_PLACE_MOUSE,FL_FULLBORDER,"Main view"); displayScreen = DefaultScreen(disp); Init(FL_ObjWin(mainform->sideView)); DrawLinks(); fl_do_forms(); } /* init function: initialise variables/pointers, xforms houskeeping */ void Init(Window win) { int i; /* set-up window information */ views.side.x = mainform->sideView->x + 2; views.side.y = mainform->sideView->y + 2; views.side.w = mainform->sideView->w - 4; views.side.h = mainform->sideView->h - 4; views.front.x = mainform->frontView->x + 2; views.front.y = mainform->frontView->y + 2; views.front.w = mainform->frontView->w - 4; views.front.h = mainform->frontView->h - 4; views.top.x = mainform->topView->x + 2; views.top.y = mainform->topView->y + 2; views.top.w = mainform->topView->w - 4; views.top.h = mainform->topView->h - 4; /* create a GC for drawing in the windows */ gcBox = XCreateGC(disp, win, 0, 0); XMapWindow(disp, win); XFlush(disp); /* allocate memory for first frame and set-up frame pointers */ times = (int *)malloc(sizeof(int)); angles = (ANGLES *)malloc(sizeof(ANGLES)); accData = (ACCDATA *)malloc(sizeof(ACCDATA)); fprintf(stderr,"sizeof(ANGLES)=%d\n", sizeof(ANGLES)); fprintf(stderr, "memory alloc: angles=%d, times=%d\n", sizeof(*angles), sizeof(*times)); currAngle = angles; currTime = times; currAccData = accData; numFrames = 1; *currTime = DEFAULT_TIME_DELTA; time = DEFAULT_TIME_DELTA; sprintf(buff, "%d", *currTime); fprintf(stderr, "time=%d\n", *currTime); fl_set_input(mainform->time, buff); fl_set_counter_value(mainform->framePos, 1); /* set-up counter properly (fdesign bug) */ fl_set_counter_step(mainform->framePos, 1, 10); fl_set_counter_return(mainform->framePos, FL_RETURN_CHANGED); fl_set_counter_bounds(mainform->framePos, 1, 2); mainform->NumFrames->label = "1"; fl_redraw_object(mainform->NumFrames); /* set-up slider bounds properly */ fl_set_slider_bounds(mainform->rHipT, (int)((255 - 128)*100/sFact[rHipT]), (int)((0 - 128)*100/sFact[rHipT])); fl_set_slider_bounds(mainform->rHipB, (int)((255 - 128)*100/sFact[rHipB]), (int)((0 - 128)*100/sFact[rHipB])); fl_set_slider_bounds(mainform->rKnee, (int)((255 - 128)*100/sFact[rKnee]), (int)((0 - 128)*100/sFact[rKnee])); fl_set_slider_bounds(mainform->rAnkle, (int)((0 - 128)*100/sFact[rAnkle]), (int)((255 - 128)*100/sFact[rAnkle])); fl_set_slider_bounds(mainform->torso, (int)((255 - 128)*100/sFact[torso]), (int)((0 - 128)*100/sFact[torso])); fl_set_slider_bounds(mainform->lAnkle, (int)((255 - 128)*100/sFact[lAnkle]), (int)((0 - 128)*100/sFact[lAnkle])); fl_set_slider_bounds(mainform->lKnee, (int)((0 - 128)*100/sFact[lKnee]), (int)((255 - 128)*100/sFact[lKnee])); fl_set_slider_bounds(mainform->lHipB, (int)((0 - 128)*100/sFact[lHipB]), (int)((255 - 128)*100/sFact[lHipB])); fl_set_slider_bounds(mainform->lHipT, (int)((255 - 128)*100/sFact[lHipT]), (int)((0 - 128)*100/sFact[lHipT])); /* set-up about box */ fl_add_browser_line(aboutform->AboutText, aboutInfo); } /* calculate and draw the stick figure views */ void DrawLinks(void) { /* clear the windows by redrawing the links in the background colour */ XSetForeground(disp, gcBox, fl_get_pixel(FL_LEFT_BCOL)); /*XFillRectangle(disp, FL_ObjWin(mainform->sideView), gcBox, views.side.x, views.side.y, views.side.w, views.side.h); XFillRectangle(disp, FL_ObjWin(mainform->frontView), gcBox, views.front.x, views.front.y, views.front.w, views.front.h); XFillRectangle(disp, FL_ObjWin(mainform->topView), gcBox, views.top.x, views.top.y, views.top.w, views.top.h);*/ /* draw side links and head*/ XDrawSegments(disp, FL_ObjWin(mainform->sideView), gcBox, sideLinks, 7); XDrawArcs(disp, FL_ObjWin(mainform->sideView), gcBox, heads, 3); /* draw front links */ XDrawSegments(disp, FL_ObjWin(mainform->frontView), gcBox, frontLinks, 8); /* draw top links */ XDrawSegments(disp, FL_ObjWin(mainform->topView), gcBox, topLinks, 4); XSetForeground(disp, gcBox, fl_get_pixel(FL_BLUE)); XFlush(disp); /* set up the side view links */ /* torso link */ sideLinks[storso].x1 = views.side.x + views.side.w / 2; sideLinks[storso].y1 = views.side.y + views.side.h / 2; sideLinks[storso].x2 = sideLinks[storso].x1 + (TORSO_LENGTH*cos(angle[torso]*M_PI/180))*sin(angle[rotSide]*M_PI/180); sideLinks[storso].y2 = sideLinks[storso].y1 - (TORSO_LENGTH*cos(angle[torso]*M_PI/180))*cos(angle[rotSide]*M_PI/180); /* rHipB link */ sideLinks[srHipB].x1 = sideLinks[storso].x1; sideLinks[srHipB].y1 = sideLinks[storso].y1; sideLinks[srHipB].x2 = sideLinks[srHipB].x1 + LEG_LINK_LENGTH*sin((angle[rHipB]-angle[rotSide])*M_PI/180); sideLinks[srHipB].y2 = sideLinks[srHipB].y1 + LEG_LINK_LENGTH*cos((angle[rHipB]-angle[rotSide])*M_PI/180); /* rKnee link */ sideLinks[srKnee].x1 = sideLinks[srHipB].x2; sideLinks[srKnee].y1 = sideLinks[srHipB].y2; sideLinks[srKnee].x2 = sideLinks[srKnee].x1 + LEG_LINK_LENGTH*sin((angle[rHipB]+angle[rKnee]-angle[rotSide])*M_PI/180); sideLinks[srKnee].y2 = sideLinks[srKnee].y1 + LEG_LINK_LENGTH*cos((angle[rHipB]+angle[rKnee]-angle[rotSide])*M_PI/180); /* rAnkle link */ sideLinks[srAnkle].x1 = sideLinks[srKnee].x2; sideLinks[srAnkle].y1 = sideLinks[srKnee].y2; sideLinks[srAnkle].x2 = sideLinks[srAnkle].x1 + FOOT_LENGTH*sin((angle[rHipB]+angle[rKnee]+angle[rAnkle]-angle[rotSide]+90)*M_PI/180); sideLinks[srAnkle].y2 = sideLinks[srAnkle].y1 + FOOT_LENGTH*cos((angle[rHipB]+angle[rKnee]+angle[rAnkle]-angle[rotSide]+90)*M_PI/180); /* lHipB link */ sideLinks[slHipB].x1 = sideLinks[storso].x1; sideLinks[slHipB].y1 = sideLinks[storso].y1; sideLinks[slHipB].x2 = sideLinks[slHipB].x1 + LEG_LINK_LENGTH*sin((angle[lHipB]-angle[rotSide])*M_PI/180); sideLinks[slHipB].y2 = sideLinks[slHipB].y1 + LEG_LINK_LENGTH*cos((angle[lHipB]-angle[rotSide])*M_PI/180); /* lKnee link */ sideLinks[slKnee].x1 = sideLinks[slHipB].x2; sideLinks[slKnee].y1 = sideLinks[slHipB].y2; sideLinks[slKnee].x2 = sideLinks[slKnee].x1 + LEG_LINK_LENGTH*sin((angle[lHipB]+angle[lKnee]-angle[rotSide])*M_PI/180); sideLinks[slKnee].y2 = sideLinks[slKnee].y1 + LEG_LINK_LENGTH*cos((angle[lHipB]+angle[lKnee]-angle[rotSide])*M_PI/180); /* lAnkle link */ sideLinks[slAnkle].x1 = sideLinks[slKnee].x2; sideLinks[slAnkle].y1 = sideLinks[slKnee].y2; sideLinks[slAnkle].x2 = sideLinks[slAnkle].x1 + 10*sin((angle[lHipB]+angle[lKnee]+angle[lAnkle]-angle[rotSide]+90)*M_PI/180); sideLinks[slAnkle].y2 = sideLinks[slAnkle].y1 + 10*cos((angle[lHipB]+angle[lKnee]+angle[lAnkle]-angle[rotSide]+90)*M_PI/180); /* head */ heads[0].x = sideLinks[storso].x1 + ((TORSO_LENGTH+HEAD_RADIUS)*cos(angle[torso]*M_PI/180))*sin(angle[rotSide]*M_PI/180) - HEAD_RADIUS; heads[0].y = sideLinks[storso].y1 - (TORSO_LENGTH+HEAD_RADIUS)*cos(angle[torso]*M_PI/180)*cos(angle[rotSide]*M_PI/180) - HEAD_RADIUS; heads[0].width = HEAD_RADIUS*2; heads[0].height = HEAD_RADIUS*2; heads[0].angle1 = 0; heads[0].angle2 = 360*64; /* set up the front view links */ /* torso link */ frontLinks[ftorso].x1 = views.front.x + views.front.w / 2; frontLinks[ftorso].y1 = views.front.y + views.front.h / 2; frontLinks[ftorso].x2 = frontLinks[ftorso].x1 + TORSO_LENGTH*sin(angle[torso]*M_PI/180); frontLinks[ftorso].y2 = frontLinks[ftorso].y1 - TORSO_LENGTH*cos(angle[torso]*M_PI/180); /* pelvic link */ frontLinks[fPelv].x1 = frontLinks[ftorso].x1 - HIP_WIDTH/2; frontLinks[fPelv].y1 = frontLinks[ftorso].y1; frontLinks[fPelv].x2 = frontLinks[fPelv].x1 + HIP_WIDTH; frontLinks[fPelv].y2 = frontLinks[fPelv].y1; /* rHipB link */ frontLinks[frHipB].x1 = frontLinks[fPelv].x1; frontLinks[frHipB].y1 = frontLinks[fPelv].y1; frontLinks[frHipB].x2 = frontLinks[frHipB].x1; frontLinks[frHipB].y2 = frontLinks[frHipB].y1 + LEG_LINK_LENGTH*cos(angle[rHipB]*M_PI/180); /* rKnee link */ frontLinks[frKnee].x1 = frontLinks[frHipB].x2; frontLinks[frKnee].y1 = frontLinks[frHipB].y2; frontLinks[frKnee].x2 = frontLinks[frKnee].x1; frontLinks[frKnee].y2 = frontLinks[frKnee].y1 + LEG_LINK_LENGTH*cos((angle[rHipB]+angle[rKnee])*M_PI/180); /* rAnkle link */ frontLinks[frAnkle].x1 = frontLinks[frKnee].x2 - FOOT_WIDTH/2; frontLinks[frAnkle].y1 = frontLinks[frKnee].y2; frontLinks[frAnkle].x2 = frontLinks[frAnkle].x1 + FOOT_WIDTH; frontLinks[frAnkle].y2 = frontLinks[frAnkle].y1; /* lHipB link */ frontLinks[flHipB].x1 = frontLinks[fPelv].x2; frontLinks[flHipB].y1 = frontLinks[fPelv].y2; frontLinks[flHipB].x2 = frontLinks[flHipB].x1; frontLinks[flHipB].y2 = frontLinks[flHipB].y1 + LEG_LINK_LENGTH*cos(angle[lHipB]*M_PI/180); /* lKnee link */ frontLinks[flKnee].x1 = frontLinks[flHipB].x2; frontLinks[flKnee].y1 = frontLinks[flHipB].y2; frontLinks[flKnee].x2 = frontLinks[flKnee].x1; frontLinks[flKnee].y2 = frontLinks[flKnee].y1 + LEG_LINK_LENGTH*cos((angle[lHipB]+angle[lKnee])*M_PI/180); /* rAnkle link */ frontLinks[flAnkle].x1 = frontLinks[flKnee].x2 - FOOT_WIDTH/2; frontLinks[flAnkle].y1 = frontLinks[flKnee].y2; frontLinks[flAnkle].x2 = frontLinks[flAnkle].x1 + FOOT_WIDTH; frontLinks[flAnkle].y2 = frontLinks[flAnkle].y1; /* head */ heads[1].x = frontLinks[ftorso].x1 + (TORSO_LENGTH+HEAD_RADIUS)*sin(angle[torso]*M_PI/180) - HEAD_RADIUS; heads[1].y = frontLinks[ftorso].y1 - (TORSO_LENGTH+HEAD_RADIUS)*cos(angle[torso]*M_PI/180) - HEAD_RADIUS; heads[1].width = HEAD_RADIUS*2; heads[1].height = HEAD_RADIUS*2; heads[1].angle1 = 0; heads[1].angle2 = 360*64; /* set-up top view links */ /* head */ heads[2].x = views.top.x + views.top.w/2 - HEAD_RADIUS + (TORSO_LENGTH+HEAD_RADIUS)*sin(angle[torso]*M_PI/180); heads[2].y = views.top.y + views.top.h/2 - HEAD_RADIUS; heads[2].width = HEAD_RADIUS*2; heads[2].height = HEAD_RADIUS*2; heads[2].angle1 = 0; heads[2].angle2 = 360*64; /* rPelv */ topLinks[trPelv].x1 = views.top.x + views.top.w/2; topLinks[trPelv].y1 = views.top.y + views.top.h/2; topLinks[trPelv].x2 = topLinks[trPelv].x1 - HEAD_RADIUS*2; topLinks[trPelv].y2 = topLinks[trPelv].y1; /* rAnkle */ topLinks[trHipT].x1 = topLinks[trPelv].x2; topLinks[trHipT].y1 = topLinks[trPelv].y2; topLinks[trHipT].x2 = topLinks[trHipT].x1 + FOOT_LENGTH*sin(angle[rHipT]*M_PI/180); topLinks[trHipT].y2 = topLinks[trHipT].y1 + FOOT_LENGTH*cos(angle[rHipT]*M_PI/180); /* lPelv */ topLinks[tlPelv].x1 = views.top.x + views.top.w/2; topLinks[tlPelv].y1 = views.top.y + views.top.h/2; topLinks[tlPelv].x2 = topLinks[tlPelv].x1 + HEAD_RADIUS*2; topLinks[tlPelv].y2 = topLinks[tlPelv].y1; /* lAnkle */ topLinks[tlHipT].x1 = topLinks[tlPelv].x2; topLinks[tlHipT].y1 = topLinks[tlPelv].y2; topLinks[tlHipT].x2 = topLinks[tlHipT].x1 + FOOT_LENGTH*sin(angle[lHipT]*M_PI/180); topLinks[tlHipT].y2 = topLinks[tlHipT].y1 + FOOT_LENGTH*cos(angle[lHipT]*M_PI/180); /* draw side links and head*/ XDrawSegments(disp, FL_ObjWin(mainform->sideView), gcBox, sideLinks, 7); XDrawArcs(disp, FL_ObjWin(mainform->sideView), gcBox, heads, 3); /* draw front links */ XDrawSegments(disp, FL_ObjWin(mainform->frontView), gcBox, frontLinks, 8); /* draw top links */ XDrawSegments(disp, FL_ObjWin(mainform->topView), gcBox, topLinks, 4); XFlush(disp); } /* load a file */ void Load(FL_OBJECT *x, long num) { FILE *loadLnk; int i, tmp; ANGLES readAngle; int readTime; ACCDATA readAcc; load = fl_show_fselector("Load file...","","",""); fprintf(stderr, "load file: %s\n", load); numFrames = 0; free(angles); angles = NULL; free(times); times = NULL; free(accData); accData = NULL; loadLnk = fopen(load, "r"); do { if((tmp = fscanf(loadLnk, "#%*[^\n]\n")) == EOF) { fprintf(stderr, "Unexpected EOF\n"); } else if(tmp == 0) { if((tmp = fscanf(loadLnk, "%d", &readTime)) == EOF) { fprintf(stderr, "Unexpected EOF\n"); } else if(tmp == 0) { fprintf(stderr, "File format incorrect - no times or angles found.\n"); tmp = EOF; } else { for(i=0; isideView)); } else { currAccData = accData; currTime = times; currAngle = angles; fl_set_counter_value(mainform->framePos, 1); for(i=0; iframePos, 0); } } /* save a file, emit .[cgh] files */ void Save(FL_OBJECT *x, long num) { FILE *saveLnk; int i, j, tmp; char *saveTmp; char saveHead[100], tmpBuff[100]; char **searchBase, *basePos; save = fl_show_fselector("Save file...","","",""); fprintf(stderr, "save file: %s\n", save); saveTmp = (char *)malloc((5 + strlen(save))*sizeof(char)); /* write the gaitgenerator .gg link angle file */ sprintf(saveTmp, "%s.gg", save); if((saveLnk = fopen(saveTmp, "w")) == NULL) { fprintf(stderr, "Error - cannot open file %s\n", saveTmp); } else { fprintf(saveLnk, "# gait generator link file - this file was automatically generated\n"); currAngle = angles; currTime = times; currAccData = accData; for(j=0; jframePos, 0); frame = (int)fl_get_counter_value(mainform->framePos); fprintf(stderr, "initial frame=%d\n", frame); for(k=frame; kframePos, ++frame); } for(i=0; iframePos, 0); } /* respond to change in angles and redraw the stick figure views */ void AngleUpdate(FL_OBJECT *x, long num) { angle[torso] = fl_get_slider_value(mainform->torso); angle[rHipT] = fl_get_slider_value(mainform->rHipT); angle[rHipB] = fl_get_slider_value(mainform->rHipB); angle[rKnee] = fl_get_slider_value(mainform->rKnee); angle[rAnkle] = fl_get_slider_value(mainform->rAnkle); angle[lHipT] = fl_get_slider_value(mainform->lHipT); angle[lHipB] = fl_get_slider_value(mainform->lHipB); angle[lKnee] = fl_get_slider_value(mainform->lKnee); angle[lAnkle] = fl_get_slider_value(mainform->lAnkle); angle[rArm] = fl_get_slider_value(mainform->rArm); angle[lArm] = fl_get_slider_value(mainform->lArm); angle[rotSide] = fl_get_slider_value(mainform->rotSide); acc[sideAcc] = fl_get_slider_value(mainform->sideAcc); acc[frontAcc] = fl_get_slider_value(mainform->frontAcc); DrawLinks(); } /* show the about box for 5 seconds */ void About(FL_OBJECT *x, long num) { fl_add_timeout(5000, HideAbout, 0); fl_show_form(aboutform->about,FL_PLACE_MOUSE,FL_NOBORDER,"About gait generator"); } /* remove the about box */ void HideAbout(int id, void *data) { fl_hide_form(aboutform->about); } /* respond to the user changing the time */ void TimeDelta(FL_OBJECT *x, long num) { strcpy(buff, fl_get_input(x)); fprintf(stderr, "time string entered: %s\n", buff); if(sscanf(buff, "%d", &time)) { sprintf(buff, "%d", time); fprintf(stderr, "time=%d\n", time); fl_set_input(x, buff); } else { fprintf(stderr, "invalid time string entered: %s\n", buff); fl_show_alert("Error","Invalid time entered. Time is in milliseconds and must be an integer.","Please re-enter this number.",0); } } /* respond to the user changing the current frame */ void ChangeFrame(FL_OBJECT *x, long num) { int value, i; /* read user input value */ value = (int)fl_get_counter_value(x); /* put current angle and time values into angles and times */ for(i=0; i numFrames) { /* add new frame */ fl_set_counter_value(x, ++numFrames); fprintf(stderr, "numFrames=%d\n", numFrames); fl_set_counter_bounds(x, 1, numFrames + 1); sprintf(buff, "%d", numFrames); mainform->NumFrames->label = buff; fl_redraw_object(mainform->NumFrames); angles = (ANGLES *)realloc(angles, numFrames*sizeof(ANGLES)); times = (int *)realloc(times, numFrames*sizeof(int)); accData = (ACCDATA *)realloc(accData, numFrames*sizeof(ACCDATA)); currAngle = angles + (numFrames - 1); currTime = times + (numFrames - 1); currAccData = accData + (numFrames - 1); for(i=0; itorso, angle[torso]); fl_set_slider_value(mainform->rHipT, angle[rHipT]); fl_set_slider_value(mainform->rHipB, angle[rHipB]); fl_set_slider_value(mainform->rKnee, angle[rKnee]); fl_set_slider_value(mainform->rAnkle, angle[rAnkle]); fl_set_slider_value(mainform->lHipT, angle[lHipT]); fl_set_slider_value(mainform->lHipB, angle[lHipB]); fl_set_slider_value(mainform->lKnee, angle[lKnee]); fl_set_slider_value(mainform->lAnkle, angle[lAnkle]); fl_set_slider_value(mainform->rArm, angle[rArm]); fl_set_slider_value(mainform->lArm, angle[lArm]); fl_set_slider_value(mainform->rotSide, angle[rotSide]); fl_set_slider_value(mainform->sideAcc, acc[sideAcc]); fl_set_slider_value(mainform->frontAcc, acc[frontAcc]); sprintf(buff, "%d", time); fl_set_input(mainform->time, buff); sprintf(buff, "%d", numFrames); mainform->NumFrames->label = buff; fl_redraw_object(mainform->NumFrames); } short AConvert(LINK name, int angle) { return (angle * sFact[name])/100 + offset[name]; }