void ReRaceAbort() { ReShutdownUpdaters(); RePhysicsEngine().shutdown(); RaceEngine::self().unloadPhysicsEngine(); ReUI().onRaceFinishing(); ReRaceCleanDrivers(); if (NetGetNetwork()) NetGetNetwork()->Disconnect(); FREEZ(ReInfo->_reCarInfo); if (ReInfo->params != ReInfo->mainParams) { GfParmReleaseHandle(ReInfo->params); ReInfo->params = ReInfo->mainParams; } // Return to race configuration step ReStateApply((void*)RE_STATE_CONFIG); }
static void reNetworkSetCarPhysics(double timeDelta,CarControlsData *pCt) { tDynPt *pDynCG = RePhysicsEngine().getCar(pCt->startRank); // double errX = pDynCG->pos.x-pCt->DynGCg.pos.x; // double errY = pDynCG->pos.y-pCt->DynGCg.pos.y; // double errZ = pDynCG->pos.z-pCt->DynGCg.pos.z; int idx = NetGetNetwork()->GetCarIndex(pCt->startRank,ReInfo->s); //Car controls (steering,gas,brake, gear tCarElt *pCar = ReInfo->s->cars[idx]; pCar->ctrl.accelCmd = pCt->throttle; pCar->ctrl.brakeCmd = pCt->brake; pCar->ctrl.clutchCmd = pCt->clutch; pCar->ctrl.gear = pCt->gear; pCar->ctrl.steer = pCt->steering; pDynCG->pos = pCt->DynGCg.pos; pDynCG->acc = pCt->DynGCg.acc; pDynCG->vel = pCt->DynGCg.vel; double step = 0.0; if (timeDelta>0.0) { //predict car position while(timeDelta>0.0) { if (timeDelta>RCM_MAX_DT_SIMU) { step = RCM_MAX_DT_SIMU; } else step = timeDelta; timeDelta-=step; RePhysicsEngine().updateCar(ReInfo->s, step, pCt->startRank); } } //GfLogTrace("Network position error is %lf %lf %lf and delta is %lf\n",errX,errY,errZ,timeDelta); //Car physics // RePhysicsEngine().setCar(pCt->DynGCg, pCt->startRank); }
void ReRaceCleanup(void) { RePhysicsEngine().shutdown(); StandardGame::self().unloadPhysicsEngine(); ReStoreRaceResults(ReInfo->_reRaceName); ReRaceCleanDrivers(); #ifdef THIRD_PARTY_SQLITE3 GfLogInfo("Replay: Database closed\n"); if (replayDB) sqlite3_close(replayDB); replayDB = NULL; #endif replayRecord = 0; }
/* Compute Pit stop time */ void ReCarsUpdateCarPitTime(tCarElt *car) { tSituation *s = ReInfo->s; tReCarInfo *info = &(ReInfo->_reCarInfo[car->index]); tCarPenalty *penalty; int i; // GfLogDebug("ReCarsUpdateCarPitTime(%s) : typ=%d, fuel=%f, rep=%d\n", // car->_name, car->_pitStopType, car->_pitFuel, car->_pitRepair); switch (car->_pitStopType) { case RM_PIT_REPAIR: info->totalPitTime = 2.0f + fabs((double)(car->_pitFuel)) / 8.0f + (tdble)(fabs((double)(car->_pitRepair))) * 0.007f; car->_scheduledEventTime = s->currentTime + info->totalPitTime; RePhysicsEngine().reconfigureCar(car); for (i=0; i<4; i++) { car->_tyreCondition(i) = 1.01f; car->_tyreT_in(i) = 50.0f; car->_tyreT_mid(i) = 50.0f; car->_tyreT_out(i) = 50.0f; } GfLogInfo("%s in repair pit stop for %.1f s (refueling by %.1f l, repairing by %d).\n", car->_name, info->totalPitTime, car->_pitFuel, car->_pitRepair); break; case RM_PIT_STOPANDGO: penalty = GF_TAILQ_FIRST(&(car->_penaltyList)); if (penalty && penalty->penalty == RM_PENALTY_10SEC_STOPANDGO) info->totalPitTime = 10.0; else info->totalPitTime = 0.0; car->_scheduledEventTime = s->currentTime + info->totalPitTime; // Prevent car->_state & RM_CAR_STATE_PIT from being true for a too short delay, // in order for the penalty management to detect it. if (car->_scheduledEventTime < s->currentTime + RCM_MAX_DT_SIMU) car->_scheduledEventTime += RCM_MAX_DT_SIMU; GfLogInfo("%s in Stop-and-Go pit stop for %.1f s.\n", car->_name, info->totalPitTime); break; } }
/* return state mode */ int ReRaceRealStart(void) { int i, j; tRobotItf *robot; tReCarInfo *carInfo; char buf[128]; int foundHuman; void *params = ReInfo->params; tSituation *s = ReInfo->s; tMemoryPool oldPool = NULL; void* carHdle; // Load the physics engine if (!RaceEngine::self().loadPhysicsEngine()) return RM_ERROR; // Get the session display mode (default to "All sessions" ones, or else "normal"). std::string strDispMode = GfParmGetStr(params, ReInfo->_reRaceName, RM_ATTR_DISPMODE, ""); if (strDispMode.empty()) strDispMode = GfParmGetStr(params, RM_VAL_ANYRACE, RM_ATTR_DISPMODE, RM_VAL_VISIBLE); if (strDispMode == RM_VAL_INVISIBLE) ReInfo->_displayMode = RM_DISP_MODE_NONE; else if (strDispMode == RM_VAL_VISIBLE) ReInfo->_displayMode = RM_DISP_MODE_NORMAL; else if (strDispMode == RM_VAL_SIMUSIMU) ReInfo->_displayMode = RM_DISP_MODE_SIMU_SIMU; else { GfLogError("Unsupported display mode '%s' loaded from race file ; " "assuming 'normal'\n", strDispMode.c_str()); ReInfo->_displayMode = RM_DISP_MODE_NORMAL; } //GfLogDebug("ReRaceRealStart: Loaded dispMode=0x%x\n", ReInfo->_displayMode); // Check if there is a human in the driver list foundHuman = ReHumanInGroup() ? 2 : 0; // Reset SimuSimu bit if any human in the race. // Note: Done here in order to make SimuSimu faster. if ((ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU) && foundHuman) { ReInfo->_displayMode &= ~RM_DISP_MODE_SIMU_SIMU; } // Initialize & place cars // Note: if SimuSimu display mode, robot->rbNewTrack isn't called. This is a lot faster. if (ReInitCars()) return RM_ERROR; // Check if there is a human in the current race // Warning: Don't move this before ReInitCars (initializes s->cars). for (i = 0; i < s->_ncars; i++) { if (s->cars[i]->_driverType == RM_DRV_HUMAN) { foundHuman = 1; break; }//if human }//for i // Force "normal" display mode if any human in the session if (foundHuman == 1) { ReInfo->_displayMode = RM_DISP_MODE_NORMAL; } // Force "result only" mode in Practice / Qualif. sessions without any human, // but at least 1 in another session (why this ?), and SimuSimu bit on. else if (foundHuman == 2 && (ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU) && (ReInfo->s->_raceType == RM_TYPE_QUALIF || ReInfo->s->_raceType == RM_TYPE_PRACTICE)) { ReInfo->_displayMode = RM_DISP_MODE_NONE; } GfLogInfo("Display mode : %s\n", (ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU) ? "SimuSimu" : ((ReInfo->_displayMode & RM_DISP_MODE_NORMAL) ? "Normal" : "Results-only")); // Notify the UI that it's "race loading time". ReUI().onRaceLoadingDrivers(); // Load drivers for the race for (i = 0; i < s->_ncars; i++) { snprintf(buf, sizeof(buf), "cars/%s/%s.xml", s->cars[i]->_carName, s->cars[i]->_carName); carHdle = GfParmReadFile(buf, GFPARM_RMODE_STD); snprintf(buf, sizeof(buf), "Loading %s driver (%s) ...", s->cars[i]->_name, GfParmGetName(carHdle)); ReUI().addLoadingMessage(buf); if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { //Tell robots they are to start a new race robot = s->cars[i]->robot; GfPoolMove( &s->cars[i]->_newRaceMemPool, &oldPool ); robot->rbNewRace(robot->index, s->cars[i], s); GfPoolFreePool( &oldPool ); }//if ! simusimu }//for i RtTeamManagerStart(); // Notify the UI that the drivers have been loaded now. ReUI().onRaceDriversLoaded(); // Initialize the physics engine RePhysicsEngine().updateSituation(s, RCM_MAX_DT_SIMU); carInfo = ReInfo->_reCarInfo; for (i = 0; i < s->_ncars; i++) { carInfo[i].prevTrkPos = s->cars[i]->_trkPos; } // All cars start with max brakes on ReUI().addLoadingMessage("Running Prestart ..."); for (i = 0; i < s->_ncars; i++) { memset(&(s->cars[i]->ctrl), 0, sizeof(tCarCtrl)); s->cars[i]->ctrl.brakeCmd = 1.0; } for (j = 0; j < (int)(1.0 / RCM_MAX_DT_SIMU); j++) RePhysicsEngine().updateSituation(s, RCM_MAX_DT_SIMU); // Initialize current result manager. ReInitCurRes(); // More initializations. ReInfo->_reTimeMult = 1.0; ReInfo->_reLastRobTime = -1.0; if (NetGetNetwork()) ReInfo->s->currentTime = GfTimeClock() - NetGetNetwork()->GetRaceStartTime(); else ReInfo->s->currentTime = -2.0; // We start 2 seconds before the real race start ReInfo->s->deltaTime = RCM_MAX_DT_SIMU; ReInfo->s->_raceState = RM_RACE_STARTING; ReInfo->_rePitRequester = 0; ReInfo->_reMessage = 0; ReInfo->_reMessageEnd = 0.0; ReInfo->_reBigMessage = 0; ReInfo->_reBigMessageEnd = 0.0; ReInitUpdaters(); // Notify the UI that the race simulation is ready now. ReUI().onRaceSimulationReady(); // Initialize the network if needed. if (NetGetNetwork()) { ReUI().addLoadingMessage("Preparing online race ..."); NetGetNetwork()->RaceInit(ReOutputSituation()->s); NetGetNetwork()->SetRaceActive(true); } // Notify the UI that the race is now started. ReUI().addLoadingMessage("Ready."); ReUI().onRaceStarted(); // And go on looping the race state automaton. return RM_SYNC | RM_NEXT_STEP; }//ReRaceRealStart
/** * Function to load a car. * * @param carindex The index whichs will be used as car->index for the car. * @param listindex The listindex in RM_SECT_DRIVERS_RACING * @param modindex The index of the mod; must be MAX_MOD_ITF if normal_carname is FALSE. * @param robotIdx The index of the robot. * @param normal_carname If this member is TRUE, the car is treated as an ordinary car; * if this member is FALSE, then the car used is the one given * in the xml-file, and there is no restriction on the number of instances. * @param cardllname The dllname of the driver * @return A pointer to the newly created car if successfull; NULL otherwise */ static tCarElt* reLoadSingleCar( int carindex, int listindex, int modindex, int relativeRobotIdx, char normal_carname, char const *cardllname ) { tCarElt *elt; tMemoryPool oldPool; char path[256]; char path2[256]; char buf[256]; char buf2[256]; char const *str; char const *category; char const *subcategory; char const *teamname; std::string carname; tModInfoNC *curModInfo; tRobotItf *curRobot; void *robhdle; void *cathdle; void *carhdle; void *handle; int k; int xx; char isHuman; int robotIdx = relativeRobotIdx; /* good robot found */ curModInfo = &((*(ReInfo->robModList))->modInfo[modindex]); subcategory = ReInfo->track->subcategory; #if 0 //SDW if (replayReplay) GfLogInfo("Driver in car %d being driven by replay\n", carindex); else #endif GfLogInfo("Driver's name: %s\n", curModInfo->name); isHuman = strcmp( cardllname, "human" ) == 0 || strcmp( cardllname, "networkhuman" ) == 0; /* Extended is forced for humans, so no need to increase robotIdx */ if (!normal_carname && !isHuman) robotIdx += curModInfo->index; /* Retrieve the driver interface (function pointers) */ curRobot = (tRobotItf*)calloc(1, sizeof(tRobotItf)); /* ... and initialize the driver */ #if 0 // SDW if (replayReplay) { // Register against the Replay driver (which does nothing) curModInfo->fctInit(carindex, (void*)(curRobot)); } else if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { #else if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { #endif curModInfo->fctInit(robotIdx, (void*)(curRobot)); } else { curRobot->rbNewTrack = NULL; curRobot->rbNewRace = NULL; curRobot->rbResumeRace = NULL; curRobot->rbDrive = NULL; curRobot->rbPitCmd = NULL; curRobot->rbEndRace = NULL; curRobot->rbShutdown = NULL; curRobot->index = 0; } /* Retrieve and load the robotXML file : 1) from user settings dir (local dir) 2) from installed data dir */ snprintf(buf, sizeof(buf), "%sdrivers/%s/%s.xml", GfLocalDir(), cardllname, cardllname); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); if (!robhdle) { snprintf(buf, sizeof(buf), "drivers/%s/%s.xml", cardllname, cardllname); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); } if (normal_carname || isHuman) snprintf(path, sizeof(path), "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, robotIdx); else snprintf(path, sizeof(path), "%s", ROB_SECT_ARBITRARY); /* Load car/driver info (in race engine data structure) */ if (robhdle) { elt = &(ReInfo->carList[carindex]); GF_TAILQ_INIT(&(elt->_penaltyList)); const std::string strDType = GfParmGetStr(robhdle, path, ROB_ATTR_TYPE, ROB_VAL_ROBOT); if (strDType == ROB_VAL_ROBOT){ elt->_driverType = RM_DRV_ROBOT; elt->_networkPlayer = 0; } else if (strDType == ROB_VAL_HUMAN) { elt->_driverType = RM_DRV_HUMAN; std::string strNetPlayer = GfParmGetStr(robhdle, path, "networkrace", "no"); elt->_networkPlayer = (strNetPlayer == "yes") ? 1 : 0; } elt->index = carindex; elt->robot = curRobot; elt->_paramsHandle = robhdle; elt->_driverIndex = robotIdx; elt->_moduleIndex = relativeRobotIdx; strncpy(elt->_modName, cardllname, MAX_NAME_LEN - 1); elt->_modName[MAX_NAME_LEN - 1] = 0; //snprintf(path, sizeof(path), "%s/%s/%d", ROB_SECT_ROBOTS, ROB_LIST_INDEX, robotIdx); snprintf( path2, sizeof(path2), "%s/%s/%d/%d", RM_SECT_DRIVERINFO, elt->_modName, normal_carname ? 0 : 1, elt->_moduleIndex ); if (normal_carname || elt->_driverType == RM_DRV_HUMAN) { strncpy(elt->_name, GfParmGetStr(robhdle, path, ROB_ATTR_NAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_sname, GfParmGetStr(robhdle, path, ROB_ATTR_SNAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_cname, GfParmGetStr(robhdle, path, ROB_ATTR_CODE, "---"), 3); } else { strncpy(elt->_name, GfParmGetStr(ReInfo->params, path2, ROB_ATTR_NAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_sname, GfParmGetStr(ReInfo->params, path2, ROB_ATTR_SNAME, "none"), MAX_NAME_LEN - 1); strncpy(elt->_cname, GfParmGetStr(ReInfo->params, path2, ROB_ATTR_CODE, "---"), 3); } elt->_name[MAX_NAME_LEN - 1] = 0; elt->_sname[MAX_NAME_LEN - 1] = 0; elt->_cname[3] = 0; teamname = GfParmGetStr(robhdle, path, ROB_ATTR_TEAM, "none"); teamname = GfParmGetStr(ReInfo->params, path2, ROB_ATTR_TEAM, teamname ); //Use the name in params if it has a team name strncpy(elt->_teamname, teamname, MAX_NAME_LEN - 1); elt->_teamname[MAX_NAME_LEN - 1] = 0; elt->_driveSkill = GfParmGetNum(ReInfo->params, path2, RM_ATTR_SKILLLEVEL, NULL, -1.0f); if (normal_carname) /* Even if we get a normal_carname for humans we use it despite of forced extended mode*/ strncpy(elt->_carName, GfParmGetStr(robhdle, path, ROB_ATTR_CAR, ""), MAX_NAME_LEN - 1); else strncpy(elt->_carName, GfParmGetStr(ReInfo->params, path2, RM_ATTR_CARNAME, ""), MAX_NAME_LEN - 1); elt->_carName[MAX_NAME_LEN - 1] = 0; /* XML file name */ // Load custom skin name and targets from race info (if specified). snprintf(path2, sizeof(path2), "%s/%d", RM_SECT_DRIVERS_RACING, listindex); if (GfParmGetStr(ReInfo->params, path2, RM_ATTR_SKINNAME, 0)) { strncpy(elt->_skinName, GfParmGetStr(ReInfo->params, path2, RM_ATTR_SKINNAME, ""), MAX_NAME_LEN - 1); elt->_skinName[MAX_NAME_LEN - 1] = 0; // Texture name } elt->_skinTargets = (int)GfParmGetNum(ReInfo->params, path2, RM_ATTR_SKINTARGETS, (char*)NULL, 0); // Load other data from robot descriptor. elt->_raceNumber = (int)GfParmGetNum(robhdle, path, ROB_ATTR_RACENUM, (char*)NULL, 0); if (!normal_carname && elt->_driverType != RM_DRV_HUMAN) // Increase racenumber if needed elt->_raceNumber += elt->_moduleIndex; elt->_skillLevel = 0; str = GfParmGetStr(robhdle, path, ROB_ATTR_LEVEL, ROB_VAL_SEMI_PRO); for(k = 0; k < NSkillLevels; k++) { if (strcmp(aPszSkillLevelNames[k], str) == 0) { elt->_skillLevel = k; break; } } elt->_startRank = carindex; elt->_pos = carindex+1; elt->_remainingLaps = ReInfo->s->_totLaps; elt->_newTrackMemPool = NULL; elt->_newRaceMemPool = NULL; elt->_endRaceMemPool = NULL; elt->_shutdownMemPool = NULL; carname = elt->_carName; GfLogTrace("Driver #%d(%d) : module='%s', name='%s', car='%s', cat='%s', skin='%s' on %x\n", carindex, listindex, elt->_modName, elt->_name, elt->_carName, elt->_category, elt->_skinName, elt->_skinTargets); if ((strncmp(carname.c_str(), "mpa1", 4) == 0)) { if (strcmp(subcategory, "long") == 0) carname = carname+"-long"; else if (strcmp(subcategory, "short") == 0) carname = carname+"-short"; else carname = carname+"-road"; GfLogTrace("MPA... Category car = %s \n", carname.c_str()); /* Retrieve and load car specs : merge car default specs, category specs and driver modifications (=> handle) */ /* Read Car model specifications */ snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", elt->_carName, carname.c_str()); carhdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); } else { /* Retrieve and load car specs : merge car default specs, category specs and driver modifications (=> handle) */ /* Read Car model specifications */ snprintf(buf, sizeof(buf), "cars/models/%s/%s.xml", elt->_carName, elt->_carName); carhdle = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); } category = GfParmGetStr(carhdle, SECT_CAR, PRM_CATEGORY, NULL); if (category) { GfLogTrace("Checking/Merging %s specs into %s base setup for %s ...\n", category, elt->_carName, curModInfo->name); strncpy(elt->_category, category, MAX_NAME_LEN - 1); elt->_category[MAX_NAME_LEN - 1] = 0; /* Read Car Category specifications */ snprintf(buf2, sizeof(buf2), "cars/categories/%s.xml", elt->_category); cathdle = GfParmReadFile(buf2, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); int errorcode = 0; if ((errorcode = GfParmCheckHandle(cathdle, carhdle))) { switch (errorcode) { case -1: GfLogError("Car %s NOT in category %s (driver %s) !!!\n", elt->_carName, category, elt->_name); break; case -2: GfLogError("Parameters out of bound for car %s (driver %s)!!!\n",elt->_carName, elt->_name); break; case -3: GfLogError("Parameter not allowed for car %s (driver %s)!!!\n",elt->_carName, elt->_name); break; default: GfLogError("Unknown error for %s (driver %s)!!!\n",elt->_carName, elt->_name); break; } return NULL; } carhdle = GfParmMergeHandles(cathdle, carhdle, GFPARM_MMODE_SRC | GFPARM_MMODE_DST | GFPARM_MMODE_RELSRC | GFPARM_MMODE_RELDST); /* The code below stores the carnames to a separate xml-file such that at newTrack it is known which car is used. TODO: find a better method for this */ snprintf (buf, sizeof(buf), "%sdrivers/curcarnames.xml", GfLocalDir()); handle = GfParmReadFile(buf, GFPARM_RMODE_CREAT); if (handle) { snprintf(path, sizeof(path), "drivers/%s/%d", cardllname, elt->_driverIndex); GfParmSetStr (handle, path, RM_ATTR_CARNAME, elt->_carName); GfParmWriteFile (0, handle, "Car names"); GfParmReleaseHandle (handle); } if (!(ReInfo->_displayMode & RM_DISP_MODE_SIMU_SIMU)) { GfPoolMove(&elt->_newTrackMemPool, &oldPool); curRobot->rbNewTrack(elt->_driverIndex, ReInfo->track, carhdle, &handle, ReInfo->s); GfPoolFreePool( &oldPool ); } else handle = NULL; if (handle && !replayReplay) { GfLogTrace("Checking/Merging %s specific setup into %s setup.\n", curModInfo->name, elt->_carName); if (GfParmCheckHandle(carhdle, handle)) { GfLogError("Bad Car parameters for driver %s\n", elt->_name); return NULL; } handle = GfParmMergeHandles(carhdle, handle, GFPARM_MMODE_SRC | GFPARM_MMODE_DST | GFPARM_MMODE_RELSRC | GFPARM_MMODE_RELDST); } else { GfLogTrace("Keeping %s setup as is for %s (no specific setup).\n", elt->_carName, curModInfo->name); handle = carhdle; } elt->_carHandle = handle; /* Initialize sectors */ elt->_currentSector = 0; elt->_curSplitTime = (double*)malloc( sizeof(double) * ( ReInfo->track->numberOfSectors - 1 ) ); elt->_bestSplitTime = (double*)malloc( sizeof(double) * ( ReInfo->track->numberOfSectors - 1 ) ); for (xx = 0; xx < ReInfo->track->numberOfSectors - 1; ++xx) { elt->_curSplitTime[xx] = -1.0f; elt->_bestSplitTime[xx] = -1.0f; } } else { elt->_category[ 0 ] = '\0'; GfLogError("Bad Car category for driver %s\n", elt->_name); return NULL; } return elt; } else { GfLogError("No description file for robot %s\n", cardllname); } return NULL; } /** Initialize the cars for a race. The cars are positionned on the starting grid. @return 0 Ok, -1 Error */ int ReInitCars(void) { char buf[512]; char path[512]; int nCars; int index; int i, j; const char *robotModuleName; int robotIdx; void *robhdle; tCarElt *elt; //const char *focused; // Never used. //int focusedIdx; // Never used. void *params = ReInfo->params; /* Get the number of cars (= drivers) racing */ nCars = GfParmGetEltNb(params, RM_SECT_DRIVERS_RACING); GfLogTrace("Loading %d car(s)\n", nCars); FREEZ(ReInfo->carList); ReInfo->carList = (tCarElt*)calloc(nCars, sizeof(tCarElt)); FREEZ(ReInfo->rules); ReInfo->rules = (tRmCarRules*)calloc(nCars, sizeof(tRmCarRules)); //focused = GfParmGetStr(ReInfo->params, RM_SECT_DRIVERS, RM_ATTR_FOCUSED, ""); //focusedIdx = (int)GfParmGetNum(ReInfo->params, RM_SECT_DRIVERS, RM_ATTR_FOCUSEDIDX, NULL, 0); index = 0; /* For each car/driver : */ for (i = 1; i < nCars + 1; i++) { /* Get the name of the module (= shared library) of the robot */ snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS_RACING, i); robotModuleName = GfParmGetStr(ReInfo->params, path, RM_ATTR_MODULE, ""); robotIdx = (int)GfParmGetNum(ReInfo->params, path, RM_ATTR_IDX, NULL, 0); #if 0 // SDW if (replayReplay) // Register against the Replay driver snprintf(path, sizeof(path), "%sdrivers/replay/replay.%s", GfLibDir(), DLLEXT); else #endif snprintf(path, sizeof(path), "%sdrivers/%s/%s.%s", GfLibDir(), robotModuleName, robotModuleName, DLLEXT); /* Load the robot shared library */ if (GfModLoad(CAR_IDENT, path, ReInfo->robModList)) { GfLogError("Failed to load robot module %s\n", path); continue; } /* Load the racing driver info in the race data structure */ elt = NULL; snprintf(path, sizeof(path), "%s/%d", RM_SECT_DRIVERS_RACING, i); if ((int)GfParmGetNum(ReInfo->params, path, RM_ATTR_EXTENDED, NULL, 0) == 0) { /* Search for the index of the racing driver in the list of interfaces of the module */ for (j = 0; j < (*(ReInfo->robModList))->modInfoSize; j++) { if ((*(ReInfo->robModList))->modInfo[j].name && (*(ReInfo->robModList))->modInfo[j].index == robotIdx) { /* We have the right driver : load it */ elt = reLoadSingleCar( index, i, j, robotIdx, TRUE, robotModuleName ); if (!elt) { GfLogError("No descriptor file for robot %s or parameter errors (1)\n", robotModuleName); snprintf(buf, sizeof(buf), "Error: May be no driver, or some parameters are out of bound"); ReUI().addLoadingMessage(buf); snprintf(buf, sizeof(buf), " Have a look at the console window for mode details about the error"); ReUI().addLoadingMessage(buf); snprintf(buf, sizeof(buf), " Back to the config menu in 10 s ..."); ReUI().addLoadingMessage(buf); // Wait some time to allow the user to read the message! GfSleep(10.0); // 10 seconds } } } } else { GfLogTrace("Loading robot %s descriptor file\n", robotModuleName ); snprintf(buf, sizeof(buf), "%sdrivers/%s/%s.xml", GfLocalDir(), robotModuleName, robotModuleName); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); if (!robhdle) { snprintf(buf, sizeof(buf), "drivers/%s/%s.xml", robotModuleName, robotModuleName); robhdle = GfParmReadFile(buf, GFPARM_RMODE_STD); } if (robhdle && ( strcmp( robotModuleName, "human" ) == 0 || strcmp( robotModuleName, "networkhuman" ) == 0 ) ) { /* Human driver */ elt = reLoadSingleCar( index, i, robotIdx - (*(ReInfo->robModList))->modInfo[0].index, robotIdx, FALSE, robotModuleName ); } else if (robhdle && ( strcmp( GfParmGetStr( robhdle, ROB_SECT_ARBITRARY, ROB_ATTR_TEAM, "foo" ), GfParmGetStr( robhdle, ROB_SECT_ARBITRARY, ROB_ATTR_TEAM, "bar" ) ) == 0 ) ) { elt = reLoadSingleCar( index, i, (*(ReInfo->robModList))->modInfoSize, robotIdx, FALSE, robotModuleName ); } else GfLogError("No descriptor for robot %s (2)\n", robotModuleName ); } if (elt) ++index; } nCars = index; /* real number of cars */ if (nCars == 0) { GfLogError("No driver for that race ; exiting ...\n"); return -1; } else { GfLogInfo("%d driver(s) ready to race\n", nCars); } if (replayReplay) replayRecord = 0; else { char buf[1024]; const char *replayRateSchemeName; snprintf(buf, sizeof(buf), "%s%s", GfLocalDir(), RACE_ENG_CFG); void *paramHandle = GfParmReadFile(buf, GFPARM_RMODE_REREAD | GFPARM_RMODE_CREAT); replayRateSchemeName = GfParmGetStr(paramHandle, RM_SECT_RACE_ENGINE, RM_ATTR_REPLAY_RATE, "0"); GfParmReleaseHandle(paramHandle); replayRecord = atoi(replayRateSchemeName); } if (replayRecord || replayReplay) { #ifdef THIRD_PARTY_SQLITE3 int result; result = sqlite3_open("/tmp/race.sqlite", &replayDB); if (result) { GfLogError("Replay: Unable to open Database: %s\n", sqlite3_errmsg(replayDB)); sqlite3_close(replayDB); replayDB = NULL; } else { GfLogInfo("Replay: Database Opened 0x8%8.8X\n", replayDB); if (replayRecord) GfLogInfo("Replay: Record Timestep = %f\n", 1/(float)replayRecord); if (replayReplay) GfLogInfo("Replay: Playback from file\n"); /* speed up database by turning of synchronous behaviour/etc */ sqlite3_exec(replayDB, "PRAGMA synchronous = OFF", NULL, NULL, NULL); sqlite3_exec(replayDB, "PRAGMA journal_mode = OFF", NULL, NULL, NULL); sqlite3_exec(replayDB, "PRAGMA count_changes = OFF", NULL, NULL, NULL); #if 0 // This pragma seems to prevent re-opening the sqlite3 database sqlite3_exec(replayDB, "PRAGMA locking_mode = EXCLUSIVE", NULL, NULL, NULL); #endif sqlite3_exec(replayDB, "PRAGMA default_temp_store = MEMORY", NULL, NULL, NULL); //replayBlobs = (sqlite3_stmt *) calloc(nCars, sizeof(void *)); //sqlite3_stmt)); replayTimestamp = -5; ghostcarActive = 0; } #endif } ReInfo->s->_ncars = nCars; FREEZ(ReInfo->s->cars); ReInfo->s->cars = (tCarElt **)calloc(nCars, sizeof(tCarElt *)); for (i = 0; i < nCars; i++) { ReInfo->s->cars[i] = &(ReInfo->carList[i]); #ifdef THIRD_PARTY_SQLITE3 //open a table for each car if (replayDB) { char command[200]; int result; if (replayRecord) { sprintf(command, "DROP TABLE IF EXISTS car%d", i); result = sqlite3_exec(replayDB, command, 0, 0, 0); if (result) GfLogInfo("Replay: Unable to drop table car%d: %s\n", i, sqlite3_errmsg(replayDB)); } sprintf(command, "CREATE TABLE IF NOT EXISTS car%d (timestamp, lap, datablob BLOB)", i); result = sqlite3_exec(replayDB, command, 0, 0, 0); if (result) { GfLogInfo("Replay: Unable to create table car%d: %s\n", i, sqlite3_errmsg(replayDB)); exit(0); } if (replayReplay) { // Build index to allow faster read access sprintf(command, "CREATE UNIQUE INDEX IF NOT EXISTS index%d ON car%d (timestamp)", i, i); result = sqlite3_exec(replayDB, command, 0, 0, 0); if (result) GfLogInfo("Replay: Unable to create index car%d: %s\n", i, sqlite3_errmsg(replayDB)); } } #endif } ReInfo->_rePitRequester = 0; // TODO: reconsider splitting the call into one for cars, track and maybe other objects. // I stuff for now anything into one call because collision detection works with the same // library on all objects, so it is a bit dangerous to distribute the handling to various // locations (because the library maintains global state like a default collision handler etc.). RePhysicsEngine().initialize(nCars, ReInfo->track); initStartingGrid(); initPits(); return 0; }
/* * Function * initStartingGrid * * Description * Place the cars on the starting grid * * Parameters * Race Information structure initialized * * Return * none */ static void initStartingGrid(void) { char path[64]; int i; tTrackSeg *curseg; int rows; tdble a, b; //tdble wi2; // Never used. tdble d1, d2,d3; tdble startpos, tr, ts; tdble speedInit; tdble heightInit; tCarElt *car; const char *pole; void *trHdle = ReInfo->track->params; void *params = ReInfo->params; snprintf(path, sizeof(path), "%s/%s", ReInfo->_reRaceName, RM_SECT_STARTINGGRID); /* Search for the first turn for find the pole side */ curseg = ReInfo->track->seg->next; while (curseg->type == TR_STR) { /* skip the straight segments */ curseg = curseg->next; } /* Set the pole for the inside of the first turn */ if (curseg->type == TR_LFT) { pole = GfParmGetStr(params, path, RM_ATTR_POLE, "left"); } else { pole = GfParmGetStr(params, path, RM_ATTR_POLE, "right"); } /* Tracks definitions can force the pole side */ pole = GfParmGetStr(trHdle, RM_SECT_STARTINGGRID, RM_ATTR_POLE, pole); if (strcmp(pole, "left") == 0) { a = ReInfo->track->width; b = -a; } else { a = 0; b = ReInfo->track->width; } //wi2 = ReInfo->track->width * 0.5f; // Never used. rows = (int)GfParmGetNum(params, path, RM_ATTR_ROWS, (char*)NULL, 2); rows = (int)GfParmGetNum(trHdle, RM_SECT_STARTINGGRID, RM_ATTR_ROWS, (char*)NULL, (tdble)rows); d1 = GfParmGetNum(params, path, RM_ATTR_TOSTART, (char*)NULL, 10); d1 = GfParmGetNum(trHdle, RM_SECT_STARTINGGRID, RM_ATTR_TOSTART, (char*)NULL, d1); d2 = GfParmGetNum(params, path, RM_ATTR_COLDIST, (char*)NULL, 10); d2 = GfParmGetNum(trHdle, RM_SECT_STARTINGGRID, RM_ATTR_COLDIST, (char*)NULL, d2); d3 = GfParmGetNum(params, path, RM_ATTR_COLOFFSET, (char*)NULL, 5); d3 = GfParmGetNum(trHdle, RM_SECT_STARTINGGRID, RM_ATTR_COLOFFSET, (char*)NULL, d3); speedInit = GfParmGetNum(params, path, RM_ATTR_INITSPEED, (char*)NULL, 0.0); heightInit = GfParmGetNum(params, path, RM_ATTR_INITHEIGHT, (char*)NULL, 0.3f); heightInit = GfParmGetNum(trHdle, RM_SECT_STARTINGGRID, RM_ATTR_INITHEIGHT, (char*)NULL, heightInit); if (rows < 1) { rows = 1; } for (i = 0; i < ReInfo->s->_ncars; i++) { car = &(ReInfo->carList[i]); car->_speed_x = speedInit; startpos = ReInfo->track->length - (d1 + (i / rows) * d2 + (i % rows) * d3); tr = a + b * ((i % rows) + 1) / (rows + 1); curseg = ReInfo->track->seg; /* last segment */ while (startpos < curseg->lgfromstart) { curseg = curseg->prev; } ts = startpos - curseg->lgfromstart; car->_trkPos.seg = curseg; car->_trkPos.toRight = tr; switch (curseg->type) { case TR_STR: car->_trkPos.toStart = ts; RtTrackLocal2Global(&(car->_trkPos), &(car->_pos_X), &(car->_pos_Y), TR_TORIGHT); car->_yaw = curseg->angle[TR_ZS]; break; case TR_RGT: car->_trkPos.toStart = ts / curseg->radius; RtTrackLocal2Global(&(car->_trkPos), &(car->_pos_X), &(car->_pos_Y), TR_TORIGHT); car->_yaw = curseg->angle[TR_ZS] - car->_trkPos.toStart; break; case TR_LFT: car->_trkPos.toStart = ts / curseg->radius; RtTrackLocal2Global(&(car->_trkPos), &(car->_pos_X), &(car->_pos_Y), TR_TORIGHT); car->_yaw = curseg->angle[TR_ZS] + car->_trkPos.toStart; break; } car->_pos_Z = RtTrackHeightL(&(car->_trkPos)) + heightInit; FLOAT_NORM0_2PI(car->_yaw); RePhysicsEngine().configureCar(car); } }
void ReSituationUpdater::runOneStep(double deltaTimeIncrement) { tRmInfo* pCurrReInfo = ReSituation::self().data(); tSituation *s = pCurrReInfo->s; // Race messages life cycle management. ReRaceMsgManage(pCurrReInfo); if (NetGetNetwork()) { // Resync clock in case computer falls behind if (s->currentTime < 0.0) { s->currentTime = GfTimeClock() - NetGetNetwork()->GetRaceStartTime(); } if (s->currentTime < -2.0) { std::ostringstream ossMsg; ossMsg << "Race will start in " << -(int)s->currentTime << " seconds"; ReRaceMsgSetBig(pCurrReInfo, ossMsg.str().c_str()); } } //GfLogDebug("ReSituationUpdater::runOneStep: currTime=%.3f\n", s->currentTime); if (s->currentTime >= -2.0 && s->currentTime < deltaTimeIncrement - 2.0) { ReRaceMsgSetBig(pCurrReInfo, "Ready", 1.0); GfLogInfo("Ready.\n"); } else if (s->currentTime >= -1.0 && s->currentTime < deltaTimeIncrement - 1.0) { ReRaceMsgSetBig(pCurrReInfo, "Set", 1.0); GfLogInfo("Set.\n"); } else if (s->currentTime >= 0.0 && s->currentTime < deltaTimeIncrement) { ReRaceMsgSetBig(pCurrReInfo, "Go", 1.0); GfLogInfo("Go.\n"); } // Update times. pCurrReInfo->_reCurTime += deltaTimeIncrement * pCurrReInfo->_reTimeMult; /* "Real" time */ s->currentTime += deltaTimeIncrement; /* Simulated time */ if (s->currentTime < 0) { /* no simu yet */ pCurrReInfo->s->_raceState = RM_RACE_PRESTART; } else if (pCurrReInfo->s->_raceState == RM_RACE_PRESTART) { pCurrReInfo->s->_raceState = RM_RACE_RUNNING; s->currentTime = 0.0; /* resynchronize */ pCurrReInfo->_reLastRobTime = 0.0; } tTrackLocalInfo *trackLocal = &ReInfo->track->local; if (s->currentTime > 0 && trackLocal->timeofdayindex == 9) { //RM_VAL_TIME_24HR if (s->_totTime > 0) { // Scaled on Total Time s->accelTime = 24 * 3600 * s->currentTime / s->_totTime; } else { // Scaled on Number of Laps that the lead driver has completed if (s->cars[0]->_laps > 0 && s->cars[0]->_laps <= s->_totLaps) { // prevent issues if lead driver crosses line the wrong way if (pCurrReInfo->raceEngineInfo.carInfo->lapFlag) s->accelTime = s->cars[0]->_laps - 1; else s->accelTime = s->cars[0]->_laps - 1 + (s->cars[0]->_distFromStartLine / pCurrReInfo->track->length); s->accelTime = 24 * 3600 * s->accelTime / s->_totLaps; } else s->accelTime = 0; } } else s->accelTime = s->currentTime; GfProfStartProfile("rbDrive*"); GfSchedBeginEvent("raceupdate", "robots"); if ((s->currentTime - pCurrReInfo->_reLastRobTime) >= RCM_MAX_DT_ROBOTS) { s->deltaTime = s->currentTime - pCurrReInfo->_reLastRobTime; tRobotItf *robot; for (int i = 0; i < s->_ncars; i++) { if ((s->cars[i]->_state & RM_CAR_STATE_NO_SIMU) == 0) { robot = s->cars[i]->robot; robot->rbDrive(robot->index, s->cars[i], s); } else if (! (s->cars[i]->_state & RM_CAR_STATE_ENDRACE_CALLED ) && ( s->cars[i]->_state & RM_CAR_STATE_OUT ) == RM_CAR_STATE_OUT ) { // No simu, look if it is out robot = s->cars[i]->robot; if (robot->rbEndRace) robot->rbEndRace(robot->index, s->cars[i], s); s->cars[i]->_state |= RM_CAR_STATE_ENDRACE_CALLED; } } pCurrReInfo->_reLastRobTime = s->currentTime; } GfSchedEndEvent("raceupdate", "robots"); GfProfStopProfile("rbDrive*"); if (NetGetNetwork()) ReNetworkOneStep(); GfProfStartProfile("physicsEngine.update*"); GfSchedBeginEvent("raceupdate", "physics"); RePhysicsEngine().updateSituation(s, deltaTimeIncrement); bool bestLapChanged = false; for (int i = 0; i < s->_ncars; i++) ReCarsManageCar(s->cars[i], bestLapChanged); GfSchedEndEvent("raceupdate", "physics"); GfProfStopProfile("physicsEngine.update*"); ReCarsSortCars(); // Update results if a best lap changed if (pCurrReInfo->_displayMode == RM_DISP_MODE_NONE && s->_ncars > 1 && bestLapChanged) { if (pCurrReInfo->s->_raceType == RM_TYPE_PRACTICE) ReUpdatePracticeCurRes(pCurrReInfo->s->cars[0]); else if (pCurrReInfo->s->_raceType == RM_TYPE_QUALIF) ReUpdateQualifCurRes(pCurrReInfo->s->cars[0]); } }