- RARS ver. 0.50 - by Mitchell E. Timin (met7@cac.psu.edu) beta release date - April 5, 1995 WHAT'S NEW (compared to version 0.45) - A digital "instrument panel". Any of the racers may be selected with a cursor by using the up & down arrow keys. Six key variables for the selected car are shown during the race, updating every .25 seconds. Following are definitions of the six readings: speedometer = speed of the bottom of the tire relative to the car true speed = magnitude of the car's velocity vector lateral g's = centripetal acceleration in g's in-line g's = tangential acceleration in g's skid angle = angle between car centerline and velocity vector power, pct. = percentage of maximum engine power The panel is initially blank; it appears when the down arrow key is pressed. If the up arrow key is used to try to move off of the top of the scoreboard, then the panel will disappear again. - During the race the F and S keys will change the apparent speed. S will select realistic mode, and F will select fast mode. - There are several new command line options: -v displays the version number. (nothing else happens) -k does not wait for keystrokes. (In case you don't want to be there.) -nR makes the simulation deterministic; the R.V.G. is not used. -H or -h or -? bring the help screens, which now page. - The draw_arc() function is now portable; it now longer calls an arc drawing primitive function. (It uses many straight line segments.) Version 0.45 introduced the following features when it replaced version 0.39: - The drivers which are to race can be named on the command line, or they can be taken in the order in which they are named in CARZ.CPP. - The computer can generate a random starting order, or the starting order can be the same as the order in which they are named. When random order is selected, then only odd-numbered races have random order; even-numbered races have the reverse order of the previous race. - The race can be run with no graphics display. - A series of races can be run, on the same track with the same drivers. The user specifies how many races. - A report is generated in a file, giving the results of all races in a series. Points are accumulated using the F1 scoring system. - Degrees or radians may be used in any track definition file. - Clockwise tracks will work now. - There is a private RAM area of 512 bytes allocated for each car. The robot will get a pointer to that area, and can use it as desired. (The robot program CNTRLR.CPP shows one way of using it.) What was new in ver. 0.39 compared to ver. 0.3: It has all system dependent code in files called gi.cpp and os.cpp, and their accompanying os.h and gi.h. Theoretically, those are the only files to be changed for porting. A few other small changes have been made to ease porting, based on the advice of Lars Clausen of Denmark, who has a UNIX port running. (e-mail: elascurn@daimi.aau.dk) If the robot requests a vc which would deliver more than full power, a new vc is automatically computed which delivers 100% power. This is achieved using a sophisticated search method. (Brent's algorithm.) The situation structure delivered to the robot includes a backward flag, set whenever the car is going the wrong way down the track. (Backward does not mean the car is in reverse gear. If vc is less than zero, that is reverse gear.) The situation also includes the relative position and velocity of up to three nearby cars. Situation contains a pointer to an array of three structures containing this data. This only refers to cars ahead of your car, and will always contain the closest cars, in order of distance. There is a service function in CARZ.CPP called stuck(). It is meant to be called by any robot that wants to, usually at the beginning of the robot's code. It tests for abnormal situations and extricates the car from them. It returns a flag indicating that the robot should return immediately. stuck() is used by the robots included with the package. (Your robot does not have to use it, but it works rather well.) The robots should no longer use the "out" flag; it is handled by the simulation proper, and dead cars are no longer redrawn on the screen. It is no longer part of the situation structure. Dead cars are produced now by accumulated damage. The damage results both from bumping other cars and running through the fields. The rate of damage is velocity dependent. The length of the track was the mean of the lengths of the two rails. Now it is the shorter of the two. This reduces the average speed calculated, making it closer to the true average speed. On tracks with no right turns the calculated average speed will be less than a true average speed. If there are any right turns it could be higher or lower. There is now a limit on how fast the robots can change alpha. This is currently set at 4.6 radians per second, which is still quite rapid, but does affect some of the cars. Alpha will change at the limit rate if a faster rate is requested. There is also a limit of 1 radian on the magnitude of alpha. If the robot asks for more than the limit it will get the limit instead. Finally, the cars have better performance due to reduced mass, reduced air drag, and slightly increased traction. The track files have one change. In order to make the track file independent of the display screen pixel count, SCALE has been replaced by X_MAX and Y_MAX. This means that the second line of the file, which formerly held the scale, now has two numbers. The first is the maximum value of x, in feet, that needs to be displayed. The second is the same thing for y. (Either of those, but not both, can be zero, and then the other will control the scale.) The name of the executable file has been changed to RARS.EXE. ------------ end of What's New ----------------------------- After unzipping, you should have these files: PACKING.LST - a file with more-or-less the same names as this list CAR.H - the Car class and various structures TRACK.H - some const and extern statements related to the race track OS.H - Operating System dependent stuff GI.H - Graphics Interface dependent stuff OS.CPP - everything that is platform dependent, except for what is in GI.CPP GI.CPP - everything that is dependent on the Graphics Interface. TRACK.CPP - the track definition software DRAW.CPP - all of the graphics interface. (makes Borland calls) CARZ.CPP - everything else except the control programs for the cars REPORT.CPP - reporting to a file. CNTRL?.CPP (? means 0 - 5) - six robot driver (control) programs RARS.HLP - a command line help screen. (also, seven other robots are included, for a total of 13 sample robots) RARS.EXE - built from the above with Borland C++ ver. 3.1 for DOS EGAVGA.BGI - borland drivers (must be in directory with car.exe to run) RARS050.DOC - this file RARS050.ANN - The announcement about this version, and about RARS RARS.PRJ - Borland C++ 3.1 project file *.TRK - various track definition files RUNALL.BAT - batch file that runs a race on each track We used the "medium" memory model to build RARS.EXE. We used automatic floating point, automatic far pointers, pre-compiled headers, debugging info included in .obj, and Borland C++ language definition. By "automatic floating point" I mean that RARS.EXE will use floating point hardware if it is there, but will use emulation software otherwise. Your might have to experiment with Borland's options. When you write your own driver you can use ANSI C or TASM or PASCAL if you want to. A VGA or EGA display is assumed. How to invoke RARS from the command line: The command line may name a track file, how many cars, how many laps and several other options. There are defaults for everything, so the command line may be simply "RARS". In general, we could say this: RARS [track file] [no. of cars] [no. of laps] [options] except you are not restricted to that order. The default track file is called "TRACKFIL.TRK". Other defaults are: number of cars, 6 number of laps, 4 number of races 2 random starting position randomized r.v.g. These are the "options", they may go anywhere on the command line, and in any order: (/ may be used instead of - to begin an option) -? or -H or -h shows help text. -d meaning drivers (followed by list of drivers names) -f meaning fastest that computer can compute (default is realistic) -k meaning keystrokes supplied by computer, no waiting. -nd meaning no display (there is a results report at end) -nr meaning no randomization of r.v.g. (same initial seed every time) -nR meaning car motion is deterministic, and also r.v.g. not randomized -o meaning order (starting order as given in driver list or as compiled) -r meaning races, how many (default is 2 races if -r is omitted) (The r must be followed by the number of races, with or without a space.) -v meaning Just show the version and exit. In addition to any of those options, you may put one or two numbers anywhere on the line. The first number is the number of cars in the race. If there is a second number, it is the number of laps. The filename of a track definition file may be placed anywhere on the line. The .trk extension is assumed; it does not have to be typed. This should be the only item that is not a number and does not begin with - or /. The -o option is used to turn off random generation of starting position. The -nr option is used to ensure that the random variable generator generates the same sequence on each run. With -nR the rvg is not even used during the race. The -k option is used when you want to run a series of races, but not always be present to start each one. It is not required when -nd is used. ESC will still end the race, even with -k. If you just type "RARS" you will get 6 cars racing 4 laps at simulated realistic speed, on the track defined by TRACKFIL.TRK. There will be two races, the first will have a random starting order and the second will have the reverse order. "RARS 7" will get you 7 cars racing 4 laps at realistic speed. "RARS 9 12" will get you 9 cars racing 12 laps at realistic speed. "RARS SPEED 9 12" will be the same except the track is defined by the file SPEED.TRK. "RARS 9 12 -f" will get you 9 cars racing 12 laps as fast as the computer can compute. With many cars and a slow computer there will be no difference between the speeds. With few cars and a fast computer there is a big difference. "RARS BRAZIL -f -nr -r4 8 5 -d Kernign Knuth Ritchie Stroust Wirth" will get you 4 fast races on BRAZIL.TRK with 8 cars, 5 laps, no randomization, and the five drivers named, plus the next three that were compiled in, since 8 cars are requested. How to choose which "drivers" drive which cars: This is done by editing the initialization for the drovers[] array, which is near the start of CARZ.CPP. (Note that this was formerley called "drivers[]".) look for this line: con_vec (*drovers[])(situation) = { // pointers to their control programs This line is followed by names of the control functions. You don't have to change it; the -d option lets you select and re-order that list. (The -d option uses the text string names from within the function, while the drovers[] array uses the function names.) It is possible to run more cars than there are "drivers". This requires that some of the drivers operate more than one car. This works correctly only with a robot driver that has no static variables. For this reason the robot driver "Dynamic" has been included; it has no static variables. If "drivers" have static variables their algorithms won't perform properly. What happens is that the 2nd car changes the 1st car's variable, and vice-versa. Therefore, if the drovers[] array only has N different drivers, run your races with N cars or less for best results. If you want to run more cars than drivers, then fill up all of the extra positions in drovers[] with "dynamic". Up to sixteen cars can race. If you want to have truly private non-volatile RAM in your robot, use the 512 byte data area. (see CNTRLR.CPP) Report File Name: The file name of the race report is RACE.OUT. The same name is used every time, so if you want to save the results, rename the file after the races are over. The Keyboard: When RARS is executed the cars will be shown in their starting positions, not moving. Any keystroke begins the race. At the end of the race the cars will stop and stay where they are. Any keystroke moves the cars to their starting positions for the next race, or ends execution if the series is over. The ESC key will end a race in progress. If the ESC key is hit when the cars are not moving, then execution will terminate. When the -nd option is used, only the ESC key is active. It ends the current race, but does not end execution unless this is the last race. Tracks Definition Files: The tracks are defined as a sequence of segments, each segment having a radius and a length. A radius of zero is used to indicate a straight segment. The length of straight segments is given in feet. The length of curved segments is their arc length, which can be given in degrees or radians. To indicate a right turn, the radius must be given as negative. The sequence of segments defines the right-hand wall of the track. The computer calculates the left-hand wall by adding the track width, which is also defined in the file. Commentary is placed after all of the track data. There is also some other data in a track file; See V03.TRK for an example with explanations, and both right and left turns. See DEGREES.TRK for a track with arc lengths in degrees. Tracks using degrees must have the first turn with at least 5 degrees of arc length; radian tracks must have less than 5 radians for the length of the first turn. Two examples of clockwise tracks are included, named CLKWIS.TRK and DREIW.TRK. Clockwise track have their initial straigtaway near the top. The segment data in the .TRK file defines the inner wall of the track. Building Robot Drivers: First, don't expect it to be very easy; this is a non-trivial task. Next, begin with CNTRL0.CPP. Study that file, and get familiar with the situation structure defined in CAR.H. Later, study some of the other robot driver files. Ask questions of other robot authors; use the mailing list if you don't know any personally. Anything you can learn about math, Newtonian physics and control theory may help you. It would also be a good idea to familiarize yourself as much as possible with CARZ.CPP, TRACK.CPP, and CAR.H. Use the source level debugger a lot to step through interesting parts of the code and see how the values change. Some notes on the simulation: The car is treated like a point mass moving under a time varying force vector. This vector is the sum of an air drag force and a track-to-wheel force. Also, the latter is far stronger in most situations. We compute the track-to-wheel force by first computing the slip vector of the tire slipping against the track. The magnitude of the force depends on the magnitude of the slip vector. (see friction() function in CARZ.CPP) The direction of the force is parallel to the slip vector, but in the opposite direction. Since there is no difference between front and rear wheels, this is equivalent to a four-wheel drive car. (or a car with only one wheel!) F = Ma gives us the vector acceleration, which is integrated to yield the trajectory in the form of x(t), y(t), xdot(t) and ydot(t). The angle of the cars path at any instant is given by the velocity vector, whose components are xdot(t) and ydot(t). It is assumed that the driver is always able to steer so as to orient his vehicle approximately in the direction of the velocity vector. Furthermore, the driver can control the angle alpha, which is the deviation between the angle that the car is pointing and the velocity vector. This angle, the slip angle, or angle of attack in aeronautical terminology, affects the slip vector. The other thing that the driver controls is the speed of the bottom of the wheel relative to the car. He makes this larger than the cars speed to increase the speed; He makes it smaller to decelerate. We call the vc for "Velocity Commanded". (under some conditions the cars speed will approach vc.) It is also helpful to note that vc is what would be shown on the cars speedometer, if it had one. To understand vc and alpha, remember that in this model, the wheels are always slipping, at least a little. (Think of a cinder track.) vc is the speed of the bottom of the wheel relative to the car. (Velocity Commanded) If the car is coasting at zero power then vc == s.v, the speed of the car. If vc is held constant for a while the car's speed will approach vc, unless it is cornering, in which case vc may greatly exceed the speed. The angle "alpha" is the angle between the car's orientation angle and its velocity vector. (like angle of attack of an aircraft) Cornering force depends on alpha. (It is also thought of as a slip angle.) Alpha is not directly related to the steering wheel angle, which is not modeled here, and is assumed to rapidly oscillate about alpha to keep the car under control, and acheive the desired alpha. There is more about vc and alpha in CNTRL0.CPP. The slip angle, and hence the force vector, is determined both by alpha and vc. Furthermore, the positive direction of vc is limited by the power available. We assume that the power available to be delivered to the track is constant. The driver can request a vc that would exceed the available power; in that case the simulation (the move_car() function) reduces the requested vc just enough to use full power. The power_req variable tell the robot how much power he requested. The main loop of the race consists of observe(), control(), move_car(), and draw_car(). This loop is repeated at the speed of the PC clock, about 18 times per second. (unless the user enters the -f option to set real_speed to 0.) The observe() routine mostly translates the car's state from the global x, y coordinate system into a local car-centered system with the x-axis along the track direction. This and other information is passed to the driver function via the "situation" structure. (see CAR.H) control() gets the situation and returns alpha and vc. move_car() uses the alpha and vc along with the current state of the car to calculate the slip vector, the forces, and finally a new state for the car. It also calculates the power delivered by the wheel to the track, and if this would exceed the available power then vc is reduced substantially to get the power to be no more than is available. draw_car() visibly moves the car to its new position and orientation. - FEEDBACK WANTED - If you want this documentation improved, e-mail me with specific questions, or topics you want covered better. If you want the code enhanced, e-mail me with your requests. If you want to work on the code yourself, great! You can use the mailing list to stay in touch with others working on the same thing. If you want to work on porting it to another platform, great! Again, use the mailing list so you can be part of a cooperative effort. If you have a "driver" function that goes pretty fast, put it on the ftp site, in the /pub/ijs/rars/robots directory. If you want to keep your source code secret, then just send a .obj file. Another secrecy option is to use C source code, but remove all comments, substitute random strings for all identifiers, and remove all possible whitespace. This will produce a very obscure, but compilable, C program. Another approach is to keep your fastest car at home and send in a slightly slower one to the ftp site. I would like to encourage robot authors to contribute source code to the ftp site. Many people would like to participate by developing their own robots, but they find it very difficult. The more examples there are for them to learn from, the more success they will have. m