/* ___________________________________________________________________________ (C) 1995 Copyright by Denning Branch International Robotics Pittsburgh, Pensylvania, U.S.A. All rights reserved. ___________________________________________________________________________ */ #include "comp_dep.h" #include "config.h" #include "general.h" #include #include // only for debugging #include #define CONFIG_LINE_MAXLENGTH 128 #define COMMENT_CHAR '*' // define configuration variables with defaults boolean CONFIG_enable_lasernav = TRUE; int CONFIG_com_port_for_lasernav = 1; boolean CONFIG_lasernav_ACW = TRUE; boolean CONFIG_steer_swap_direction = FALSE; boolean CONFIG_drive_swap_direction = FALSE; int CONFIG_steer_samp = MRV4_STEER_SAMP; // only lo-byte is used int CONFIG_steer_gain = MRV4_STEER_GAIN; int CONFIG_steer_pole = MRV4_STEER_POLE; int CONFIG_steer_zero = MRV4_STEER_ZERO; int CONFIG_drive_samp = MRV4_DRIVE_SAMP; int CONFIG_drive_gain = MRV4_DRIVE_GAIN; int CONFIG_drive_pole = MRV4_DRIVE_POLE; int CONFIG_drive_zero = MRV4_DRIVE_ZERO; double CONFIG_drive_encoder_counts_per_metre = MRV4_DRIVE_COUNTS_PER_METRE; double CONFIG_steer_encoder_counts_per_radian = MRV4_STEER_COUNTS_PER_RADIAN; double CONFIG_sample_clockrate = CLOCKRATE_MRV4; boolean CONFIG_user_io_imperial = FALSE; //otherwise metric boolean CONFIG_robotbase_MRV4 = TRUE; struct {char *name; boolean *ptr;} tokenlist_booleans[] = { {"enable_lasernav", &CONFIG_enable_lasernav}, {"steer_swap_direction", &CONFIG_steer_swap_direction}, {"drive_swap_direction", &CONFIG_drive_swap_direction}, {"lasernav_ACW", &CONFIG_lasernav_ACW}, {"user_io_imperial", &CONFIG_user_io_imperial}, {"robotbase_MRV4", &CONFIG_robotbase_MRV4}, {"",NULL} }; struct {char *name; int *ptr;} tokenlist_ints[] = { {"com_port_for_lasernav", &CONFIG_com_port_for_lasernav}, {"steer_samp", &CONFIG_steer_samp}, {"steer_gain", &CONFIG_steer_gain}, {"steer_pole", &CONFIG_steer_pole}, {"steer_zero", &CONFIG_steer_zero}, {"drive_samp", &CONFIG_drive_samp}, {"drive_gain", &CONFIG_drive_gain}, {"drive_pole", &CONFIG_drive_pole}, {"drive_zero", &CONFIG_drive_zero}, {"",NULL} }; struct {char *name; double *ptr;} tokenlist_doubles[] = { {"drive_encoder_counts_per_metre", &CONFIG_drive_encoder_counts_per_metre}, {"steer_encoder_counts_per_radian", &CONFIG_steer_encoder_counts_per_radian}, {"sample_clockrate", &CONFIG_sample_clockrate}, {"", NULL} }; // other variables static char config_error_message[100] = ""; char* ReadConfigFile(char *filename) // This file reads the configuration file and sets up the CONFIG variables // If a variable is not mentioned in the file - the default is used // If an extra variable is mentioned in the file - this is not an error // If a line is longer than CONFIG_LINE_MAXLENGTH then an error is reported // This routine returns a NULL pointer on success and an error message for // failure. { FILE *infile; char *errmsg = config_error_message; char inbuf[CONFIG_LINE_MAXLENGTH]=""; infile = fopen(filename, "r"); // open the file for read if (infile!=NULL) { // not NULL must be ok int done=0; while(!done && !feof(infile)) { if(fgets(inbuf,CONFIG_LINE_MAXLENGTH,infile)!=NULL){ //non NULL if ok // Now we check that the string "inbuf" ends in a '\n' // otherwise the line in the file exceeded CONFIG_LINE_MAXLENGTH int length = strlen(inbuf); if (length>0 && inbuf[length-1]=='\n') { // valid char *token1, *token2; token1 = strtok(inbuf," \t\n"); if (token1 && token1[0]!=COMMENT_CHAR) { token2 = strtok(NULL," \t\n"); // Now search the lists of booleans, ints and doubles // - stopping when a match is found // or when the lists are exhausted boolean token_done=0; int i; if (!token_done) { for (i=0; tokenlist_booleans[i].ptr; i++) { if (!stricmp(token1,tokenlist_booleans[i].name)){ *tokenlist_booleans[i].ptr = !stricmp(token2,"TRUE"); token_done=1; break; } } } if (!token_done) { for (i=0; tokenlist_ints[i].ptr; i++) { if (!stricmp(token1,tokenlist_ints[i].name)){ sscanf(token2,"%d",tokenlist_ints[i].ptr); token_done=1; break; } } } if (!token_done) { for (i=0; tokenlist_doubles[i].ptr; i++) { if (!stricmp(token1,tokenlist_doubles[i].name)){ sscanf(token2,"%lf",tokenlist_doubles[i].ptr); token_done=1; break; } } } if (!token_done) { sprintf(errmsg,"Error reading file: %s - Token '%s' not recognised!", CONFIG_FILE, token1); done=TRUE; } } } else { // line too long sprintf(errmsg,"Error reading file: %s - Line too long!", CONFIG_FILE); done=TRUE; } } else { // Here we had an error reading a line //sprintf(errmsg,"Error reading file: %s - Unknown Error", // CONFIG_FILE); //done=TRUE; } } // while } else { sprintf(errmsg,"Could not open file: %s",CONFIG_FILE); } return errmsg; } void DisplayCurrentConfig() // This routine expects the Text screen and provides a no-frills listing // of the CONFIG variable values in the same form that they would appear // in the file: { printf("enable_lasernav %s\n",CONFIG_enable_lasernav?"TRUE":"FALSE"); printf("com_port_for_lasernav %d\n",CONFIG_com_port_for_lasernav); printf("lasernav_ACW %s\n",CONFIG_lasernav_ACW?"TRUE":"FALSE"); printf("\n"); printf("steer_swap_direction %s\n",CONFIG_steer_swap_direction?"TRUE":"FALSE"); printf("drive_swap_direction %s\n",CONFIG_drive_swap_direction?"TRUE":"FALSE"); printf("\n"); printf("steer_samp %3d drive_samp %3d\n",CONFIG_steer_samp,CONFIG_drive_samp); printf("steer_gain %3d drive_gain %3d\n",CONFIG_steer_gain,CONFIG_drive_gain); printf("steer_pole %3d drive_pole %3d\n",CONFIG_steer_pole,CONFIG_drive_pole); printf("steer_zero %3d drive_zero %3d\n",CONFIG_steer_zero,CONFIG_drive_zero); printf("\n"); printf("sample_clockrate %.2lf\n",CONFIG_sample_clockrate); printf("drive_counts_per_metre %.2lf\n",CONFIG_drive_encoder_counts_per_metre); printf("steer_counts_per_radian %.2lf\n",CONFIG_steer_encoder_counts_per_radian); printf("user_io_imperial %s\n",CONFIG_user_io_imperial?"TRUE":"FALSE"); printf("robotbase_MRV4 %s\n",CONFIG_robotbase_MRV4?"TRUE":"FALSE"); }