Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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;
}
Beispiel #4
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;
	}
}
Beispiel #5
0
/* 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
Beispiel #6
0
/**
 * 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;
}
Beispiel #7
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);
  }
}
Beispiel #8
0
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]);
	}
}