Building an F1/10th TrakSim Map


This document describes how I used BuildMap to create the F1/10th race track maps for TrakSim.

The proposed AVP-HS (the High School Autonomous Vehicle Project) project for the summer of 2019 is to take the car to the F1/10th race in the fall. The first three international races (2017, then 2018 spring and fall) were nothing more than timed laps, but this spring at Montreal they actually ran two cars head-to-head (see the winning team's video here). TrakSim cannot do full 2-car simulations -- at least not without a lot more work and computation time better used in making your car go fast. You can still place a second car on the track as an "artifact" and even move it along a pre-programmed line over time. Until now TrakSim couldn't do tracks with walls instead of painted (or taped) lines. I think I got the bugs in the walls fixed in this release.

The distributed track descriptor file "TrackImg.txt" contains several example track descriptors. This document describes the four that model all the actual F1/10th race tracks to date. What I did was watch the videos (apparently posted by the winning teams in a couple cases) and extract some screen shots, from which I was able to infer the track dimensions and superstructure. In an ideal world, TrakSim would have a direct manipulation tool for laying out tracks, but that's hard to program. So instead I wrote up the track descriptors one text line at a time, trying each piece until it looked right. I'm not sure it was faster, but considering how long it took to get the tube-walls to display properly, and the fact that user interface (like direct manipulation) is the hardest kind of program to get right, I suspect I made the right choice.

Although you would be using the tube-wall track boundaries instead of the painted lines TrakSim was originally designed for, in each of these tracks I outlined the track both ways. The Stay-in-Track (SiT) mode of running works from the track edges as defined by the "painted lines" (even if the lines are zero-width, the simulator still tracks the lines). In some cases I smoothed out the curves, because SiT needs the curved edge to repoint the car along the track. It's a little clumsey, but as soon as your own driving code keeps the car on-track, you don't need the Sit mode at all.


Montreal (spring 2019)
Turin (fall 2018)
Porto (spring 2018)
U.Penn (2017)

TrakSim home page
Building a TrakSim Map
Tech Topics "Page 0"

Porto (spring 2018)

This is the first F1/10th track I built. The race was held in some kind of palatial indoor atrium or courtyard with balconies and windows on all four sides looking down at the floor where the track was laid out. I worked from videos of the races, and I could not get clean images of the backgrounds, so I settled for a one-frame composite of the window walls, which I repeated around the whole perimeter. I added a couple of shots as seen from the track. To get the perspective right, I needed to deskew the screen shots, because TrakSim adds its own perspective based on the angle of view from the car.

I captured some screen shots of the tube walls in the Turin video, then edited them into some generic tube wall images (in the distributed "TrackImg.tiff" file), which I used in all of these tracks. The Turin tubes appear to be 6" HVAC tubing, whereas the U.Penn and Porto tracks were laid out with 4" dryer tubing. The same images are easily scaled by changing the "pixels per meter" value for the image reference (see the "Image File Coordinates" page of this website).

We had a lot of trouble with floor color variations in 2018, and TrakSim had no way to simulate that at the time. The result was that the car would run well in simulation, but fail on the floor. So I added both variable illumination and "pebble" texture coloring in the fall (after the summer program was over) in preparation for the next year. When we decided to aim for the F1/10th race as a project for 2018, and I started to look at what kinds of tracks they were racing in, it became obvious that if we didn't need the floor coloring to be rigidly patterned (like the Porto parquet floor), a large (but random) pebble size could adequately simulate it. I see the Montreal venue has a lot of variability in track illumination, much more than the uniform high overhead lighting in Porto. The new illumination support currently does not extend to the vertical walls, but it probably should. Perhaps I'll get that working before July. For now it's just flat lighting.

I started by measuring the height in pixels of the people in my screen shots. Assuming them to be about 2 meters (perhaps more accurately 1.8m) tall, I then measured the width of the track in the immediate vicinity (approximately the same pixels per meter) and noticed that the parquet diamond pattern was about 90cm corner to corner, which enabled me to estimate the total track dimensions by counting the number of patterns. These are only approximations, but the programmed AVP-HS car should be able to adapt to greater variations than these. Although the "pebble" pattern is pseudo-random, it is fixed to the coordinate system, so you can still use it to memorize the track coordinates, if you choose to do that.

Porto (and now also Montreal) had a goal line marked on the floor (perhaps there was one at Turin also, but I didn't see it in any of the videos). At Porto they also had a similarly colored bar raised over the track, where it was visible from a distance. I had added overhead luminaries to simulate the variable lighting we previously encountered in the various venues; by setting the amount of light provided by a luminary to zero, I was able to simulate a reasonable raised goal bar. Then I created a short segment of tube wall with a black vertical bar attached, which I used for the supports.

The F1/10th tracks have no lines on the floor, the cars are apparently expected to use LIDAR to detect the reflection from vertical track boundary walls for navigation. Our team from the very beginning has the superior technology of extracting track information from the image alone, so we looked for lines to mark off the track edges. I added vertical walls to support the F1/10th format, and that would be sufficient for cars programmed to drive in the F1/10th races, but the TrakSim "Stay-In-Track" (SiT) mode works off the line generation geometry. If that is to remain useful for early development (before the teams have integrated their software components), then the simulated tracks need both the line geometry (with the line width set to zero, because the SiT is using the geometry from the map, not the image itself) and the matching tube wall. The two track-edge technologies are supposed to be compatible in TrakSim, but getting them to line up properly took a lot of trial and error. One of the discrepancies is that the track edge geometry follows the right side of the track forward (right-to-left, as seen from the track), whereas the image walls are anchored on their left end, so they are specified left-to-right. One of the joys of incremental software development instead of so-called "waterfall" design, where you know what you need to do, and you plan to make all the parts work together intentionally. The real world isn't like that.

The image walls were originally intended to be rendered in the single back-to-front sweep through the whole track map, so they are implemented in the same 2m grid coordinates. Getting the perspective right that way turned out to be messy and computationally wasteful, so I pulled them out into a separate list that is processed after the rest of the track has been rendered. Because the artifacts are processed separately, overlaps are not well handled. In the current release, if any part of an artifact is behind an image wall, you cannot see any of it that might be visible through holes in the wall, but whatever sticks up over the top will still show. Fortunately, that's not a problem in the Porto track (there are no artifacts to show, and nothing behind holes in the walls). Anyway, there are four layers of wall information. The frontmost is always displayed in front, and the tallest is always displayed (either in front, if it is, or else behind whatever is in front), and then any remaining walls are triaged into the remaining layer(s). Walls shorter than whatever is in front of them are the first to be left out, then the walls that are farther behind, until the layers are filled. The depth of the scene is keyed to the raster line at the base of each visual element on the floor/ground. At short focal lengths, the farther artifacts and/or walls tend to resolve to a very small number of raster lines for depth. If I were doing it over, I'd probably do the calculations in fractional rasters, but that takes more processing time, which I was trying to conserve. So the current version uses a heuristic to depth-sort walls and objects that resolve to one raster line: walls within four park meters (20" on the actual floor) of the track edge are always assumed to be behind objects and mid-park walls. If that isn't enough, walls near the edge are sorted by line number in the track descriptor file (earlier lines are assumed behind) and otherwise shorter walls are assumed to be in front of taller.

None of this affects Porto, except that we have two layers of background scenery behind the tube-walls (on the south and east sides), and as the car comes around the dimple in the south side of the track, there can be up to three layers of tube-walls visible. The tube walls are supposed to rise above the camera height, so that nearer walls rise higher in the scene than farther walls, but something in the scaling code made that fail. sigh. So there's a temporary hack that recognizes the majority of wall segments all the same nominal height, and gives viewing preference to the nearer ones. Anyway, the sequence of the wall descriptor lines is significant, so that they layer properly in the distance. Closer stuff resolves to different raster lines, so it's not a problem.

I laid out the walls first, then covered them over with floor. Otherwise the map view shows gray grid cell blocks where the walls are. The map views still show the wall faces as straight lines (which is how they render). The front and back of a wall are considered separate walls, and they could even cross over each other with impunity, because the car can never see both at the same time. The track edge geometry is part of the floor so it must be laid out after the floor has covered over the wall blocks. There are separate colors for track and non-track; I set them to be approximately the same color for these tracks, except that I turned on the checkerboard for the non-track because it helps me to see the spacing of things in the scene and on the map. Although the line width is set to zero, the checkboarding of non-track helps show where the geometrical track edge is. I had trouble getting the SiT mode to work properly in the variable-width track in Turin, so I brought the geometrical edges in and made them more rounded, but it was not a problem in Porto.

Mostly I used the curve macros when doing track edge curves, but sometimes they didn't work as well as individual line segments. Your mileage may vary if you try to do this.

Turin (fall 2018)

The Turin track introduced non-uniform track boundaries. In addition to the tube walls, they also had pre-printed card stock with the same drawing of a row of houses printed on each. I drew up by hand a similar image of about the same dimension, for use in these walls. Some of the track boundaries were simply the room walls. I made up a low image wall to model the baseboard along the room wall -- and learned about a design flaw in the implementation of the image walls: When rendering the walls, each wall is compared to the car position and orientation to see if it is visible. Rather than look at every grid cell the wall crosses, I only look at the two endpoints of the wall. If one or both ends are within the view wedge (marked off by blue lines in the map) then the wall is visible and processed. If both ends are behind the car, the wall cannot be visible and no more time is spent on it. If one end is off to the left (but not behind) and the other end is off to the right (also not behind), then the middle region of the wall is usually visible. If one end is behind, and the other end is in front but off-screen, then the wall might be partly visible (if it crosses in front of the car) or not (if it crosses behind, or stays on the side that the end is). I assumed (incorrectly, it turns out) that such a wall is generally not visible. The work-around is to cut the wall into shorter pieces so this situation cannot arise. It mostly happens with long walls, which the car can approach from the side inside the range of the two ends and then curve into. Wall segments that are part of a curved wall are usually approached more or less end-on and don't have the problem. In the Turin track the long strips of houses on each end of the track, and the baseboards along the long edges are both vulnerable, so I cut them. The plain walls (behind the baseboards) don't have the problem.

On the far end of the Turin track there were some refreshment tables (sometimes with a waiter setting them up, but I left him out). Different screen shots showed these tables in different positions, but I picked one arrangement and made image walls of them. There were chairs behind the houses wall on the near end, but I could not get a good screen shot of these, so I left them out. There were three or four fire extinguishers along the two long walls; on the north wall it was elevated to shoulder height, so I made it into a wall segment with three view angels (but same image). The two extinguishers on the south side were outside the track boundary, so I made the same image into a couple of artifacts. The effect is about the same. One of the screen shots I have a guy standing in the middle of the track, apparently controlling or photographing his car rounding the far end; I added him as a separate artifact. Because I have only his back side as an image, that's all you see, no matter where you view him from. When seen from a distance his image and the track wall behind him resolve to the same raster, so because he's taller, he's deemed to be behind the wall. It's a little odd when that happens to one of his legs and not the other, so it comes out with him straddling the track wall.

The Turin floor was a light (slightly marbled) beige, which I implemented as a light pebbling, with four stripes of brown the full length of the room, two at the edges, and two more in a couple meters. I implemented these with the TrakSim "paint" feature.

The variability of the track width and curvature made the SiT mode problematic in the Turin track. I mitigated the problem by bringing in the geometric track edges (usually shown by white lines at the edges) and rounding the curves. You can still see the effects where the checkerboard pattern extends into the track area. TrakSim will "crash" your car if you drive into that region, but your optimal racing line shouldn't get anywhere near it. If this becomes a problem, let me know and we'll work out a way to get you a version of the track where the geometrical edges more closely match the image walls.

U.Penn (2017)

The only interesting feature of the first F1/10th race track at the University of Pennsylvania Engineering building are the two floor mats with the Penn logo painted on (or woven into) them. From the size of the car crossing the logo I inferred the size of the logo as 24" wide, and by comparison, the dark mat 10x10 feet square. From this I was able to determine the size of the track. There are two such mats, one nearly covering the near end of the track, and just the corner of one overlapping part of the far end (part of the logo appears behind one of the standees' heads). I Googled "U Penn shield image" and found the artwork on their website, but they wanted a login, so I captured the screen image and scaled it for use. Apart the mats, the floor is rather plain. I considered adding the grouted cracks into the terra-cotta floor tiles on the descriptor file, but it seemed like more effort than value.

Montreal (spring 2019)

When I did this track, I had only the one video prepared by the (winning) U.N.Carolina team videographer, whose interest spent more time on the food than the tech. In particular, the track filled the entire -- let's call it the -- north 80% of the room (leaving a strip behind the south barrier for officials and spectators), and it was filmed mostly from the northwest corner, so I had to guess about some of the dimensions. I never saw any part of the north wall of the room, but I got a brief glimpse of a barrier (boundary) wall of apparently cardboard panels curving north from the east wall of the room, so I assume this continued to the west wall.

The track outline was similar to Turin, but the room was somewhat larger and closer to square, so the lane size (if you can call it that) is much broader. Also, where the previous races were on hard floors like tile, Montreal was on carpet with a very high coefficient of friction -- the winning car took one turn on two wheels, tilted up close to 80o -- compared to (I think it was) Porto, where cars showed their loss of control by skidding. Also unlike thr previous races, there were four structural pillars in the room, but the track was laid out so that the boundary walls came to these pillars as switchback end-points. The 6" HVAC tubing they used for the inside curve connecting two of these pillars had black mounting tape or hardware every two meters, which I did not reproduce. It would be easy enough to add in selected places if you decide you need it for memorizing.

The carpet consisted of a well-worn (almost threadbare, a lighter gray showing through) dark brownish base color, punctuated with random rectangles and rectanglular outlines of several shades of beige and gray. The brief glimpse I got of the northern part of the room suggested to me that the pattern did not extend into a sort of high-traffic area there (with a lot more wear), but I did not reproduce it as either unpatterned or worn. I used a large pebble as in Porto to model the floor.

Montreal had the first head-to-head races, so I added a static car (as seen from behind) in one of the more open areas. With a little more effort, we can have the car move along the track, but I didn't do it in this release.

Tom Pittman
Rev. 2019 May 18