Much of the skill required in operating large vehicles is being able to maneuver them around obstacles when parking or making large angle turns. Driving on a road is relatively straightforward, as one would just turn the steering wheel towards the direction in which to go. Parking, especially if it involves reversing the vehicle, requires increased awareness of the vehicle dynamics and of the relative locations of surrounding objects. Parallel parking a car is a skill that takes time to master, and the difficulty increases with vehicles that are longer or have trailers attached. The goal of the parking simulator developed here is to provide a virtual environment in which the parking of various vehicles may be realistically practiced, so that the operator can build skills that are transferrable to real world scenarios.
The advantage of a virtual environment is that scenarios which are not easily accessible may be practiced. Once a physically realistic implementation of vehicle motion is developed, it is possible to meaningfully work through scenarios such as parking a bus or an articulated bus, maneuvering a truck with one or more trailers, and even pushing back an airplane. Less dramatic scenarios following similar dynamics, such as moving a load on a pallet jack, may also be simulated.
A screenshot of the parking simulator with an airplane pushback level loaded.
It may seem that the motion of a vehicle should be easy enough to simulate. If we are to insist on perfectly matching the physical situation, we must consider aspects such as static and dynamic friction of all the vehicle's pertinent components (the axles, brake pads, and contact patches between each tire and the ground), 3D forces and torques at each wheel, and the velocity and acceleration (linear and angular) of the vehicle. Such a comprehensive model would cover cases such as driving on slippery ground, loss of tire traction due to acceleration or uplift, and engagement of anti-lock braking system. These highly dynamic features are not applicable to parking, and an evaluation of the forces and accelerations would be computationally intensive and likely to lead to unphysical acceleration artifacts if the forces are not perfectly balanced. Thus a model based on integrating F=m*a
over time is not a good approach for this simulator.
We limit the motion to a 2D plane, that of the road surface, so we can ignore forces in the vertical direction which are not expected to be important when parking. Further we assume all the tires are in equal contact with the ground and of equal mechanical properties (friction), and that they move only along circular paths that are always tangent to the tire's contact patch. We assume negligible impact of torque due to turning individual tires (not necessarily that the torque is negligible, but that it is minor relative to the ability of the vehicle's combined tires to counter this torque). We apply the Ackermann circle model, where the rear axle is fixed and moves along a circle whose center is on a line through the axle, and where the front tires are individually adjusted in angle to lie on circular paths that are all centered on the same point. As the vehicle's path is then well defined, we may use an equivalent single fixed wheel to represent the rear axle, and a single steered wheel to represent the front axle, or a bicycle model of the vehicle. Then, a vehicle is defined by the distance between the fixed wheel and the steered wheel, the position of the fixed wheel in the level frame, the vehicle's rotation angle in the level frame, and the angle of the steered wheel relative to the vehicle's forward direction. With the steering angle held constant, the fixed wheel's path will be along the circle whose center is on the line perpendicular to the vehicle's forward direction and passing through the fixed wheel, intersected with the line through and perpendicular to the pointing direction of the steered wheel.
On left, the circular arcs traveled by a vehicle's {blue rectangle} four wheels {black filled rectangles} are shown. The fixed rear axle is drawn as horizontal. On right, the same scenario is represented as a bicycle model with two wheels. Then we can define a wheel base which is a property of the vehicle, and a steering angle which is adjusted by the driver.
The above findings all seem reasonable, but do they apply to real situations? I drove a car to an empty parking lot and carried out multiple turns, going in forward and reverse, while holding the steering wheel in a constant orientation. There was substantial variability in observed vehicle location after each turn, however when averaging the results the ideal scenario was closely matched. I suspect that slight backlash in the mechanical system of the steering, and more significantly variations in how closely I held the front tires to a constant angle, account for the variability.
A single vehicle is then reduced to traveling along a series of circular arcs. The goal of this project was more ambitious, though, as it is desired to simulate trailers attached to the main driving vehicle. The distinction is that the driving vehicle has active steering and supplies the motive force for the entire physical system. The latter is important as it means we can derive the motion of the trailer from the motion of the driving vehicle, which we know from above is along a circular arc. (In dynamic cases, such as a skidding or oscillating trailer when driving at speed, the trailer may accelerate the driving vehicle away from a circular path, which breaks the assumptions of the developed model and is not considered here.) Then if we know the motion of the first trailer, we can similarly derive the motion of the second and subsequent trailers one by one. Therefore a path to the mathematical solution is in sight.
We begin with the simpler case of a driving vehicle traveling along a straight line (a circle with very large diameter) and pulling one trailer. We may take the straight line as the X-axis of an XY plane, and define that at X=0
the trailer is oriented along the positive Y-axis, and that the trailer's fixed wheels are a distance L
behind the hitch point of the driving vehicle. At any point, the trailer travels along a curve that is tangent to the line drawn perpendicular to the trailer's fixed axle and through the midpoint of the axle. The slope of this line is dY/dX = Y/sqrt(L^2-Y^2)
. We may change to a normalized basis, where x_t=X/L, y_t=Y/L
, and then dy_t/dx_t=y_t/sqrt(1-y_t^2)
. This equation is integrated (using wolfram alpha) to give x_t=+-(arctanh(st)-st)
, where st=sqrt(1-y_t^2)
. Note that these (x_t,y_t)
points correspond to the position of the trailer only, and if we want to relate this to the driving vehicle, we may use x_d=x_t+st=+-arctanh(st)
as the x-coordinate of the hitch point and y_t
as the y-coordinate of the trailer.
Geometric construction to find the equation for the "trailer curve". In any small increment the trailer {circle} moves along its existing direction {blue arrow}, and with constant L=1
we can draw a triangle {black lines} to solve for the slope dy_t/dx_t
.
A plot of the "trailer curve", with trailing length L=1
represented by the black line between two circles. The upper circle represents the fixed wheels of the trailer and the lower circle represents the driving vehicle hitch point moving along the x-axis {green arrow}. As the lower circle moves along the horizontal y=0
, the upper circle moves along the blue dashed curve. The black line (trailer forward direction) always remains tangent to the blue dashed curve.
The equation is interesting as its slope is infinite at x=0
but its y-value is finite and continuous across the x=0
boundary; the y=0
boundary separates two regions, with trailer either on the left or on the right of the driving vehicle, both regions approaching y=0
(trailer in line with vehicle) in a negative exponential manner at large x
(limit as y=2*exp(-x-1)
). There is probably a fancy name for this equation (p.s. tractrix), but I have been calling it the "trailer curve", because its shape is characteristic of how all trailers will behave when pulled (or pushed) along a straight line, and any other motion may be represented as a limiting case of many small straight lines, thus the curve can describe all trailer dynamics. Even a trailer-free vehicle follows this curve if the front wheels are steered to point along a straight line, such as when pulling out of a parking spot. It could be argued that the experience of driving is just becoming familiar with specific instances of this curve.
I marked out lines on the floor and used a bicycle as well as a pallet jack to validate the "trailer curve" x_t=+-(arctanh(sqrt(1-y_t^2))-sqrt(1-y_t^2))
as well as the driving vehicle referenced version x_d=+-arctanh(sqrt(1-y_t^2))
. Initial results were not very close to the equation, so I repeated the experiments being extra careful to keep the steered wheels oriented along a straight line with minimal deviation, and then the results were a better match. For each increment in motion, I marked the (x_t,y_t)
position of the fixed axle centerpoint, and the (x_d,0)
position of the steering axle centerpoint (normalized by the measured distance L
between the two centerpoints). These points are then overlaid on the calculated graph of the above equations. With the bicycle, because the steering column is at an angle facing towards the rider, the distance L
would shift as a function of steering angle, so a perfect fit to the equations was not expected or obtained. With the pallet jack, the ideal situation is better represented, and the fit of the points is better as well. I found that the equation is matched when pushing through the x=0
line, with the curve symmetrically reflected about this line. Moreover, even with the pallet jack pulled to be almost parallel with the straight line direction, it was possible to push it back and recreate the initial trajectory (slightly offset due to mechanical backlash), suggesting that precision in angular quantities will be important for the simulation.
A plot of the trailer curve {thick blue line} and experimentally measured locations of pallet jack equivalent wheels {black lines} as the steered wheel is moved along a line (y=0
). All coordinates are normalized to L=1
. The formula developed above appears to be a good match to real vehicle motion.
While we now have an idea of what curve the trailer's back wheels will trace out, this does not directly give a result that can be used to advance a simulation. Instead of using a basis of trailer (x_t,y_t)
locations, it will be more useful to have a basis of (x_d,θ_t)
locations, where the position of the steering axle (x_d,0)
is related to the angle θ_t
between the x-axis and the trailer, defined by an equation which gives θ_t
as a function of x_d
.
With the driving vehicle moving along a line {green arrow on dashed black line}, and a trailer pulled behind it {blue arrow}, we define θ_t
as the clockwise angle from the driving vehicle forward direction to the trailer forward direction.
The angle-based equation may be found from the knowledge of (x_t,y_t,x_d)
with the "trailer curve". We have x_d=arctanh(sqrt(1-y_t^2))
and θ_t=arctan(-y_t/sqrt(1-y_t^2))
. Then substituting a parameter t
instead of y_t
, the desired equation passes through the points (arctanh(sqrt(1-t^2)),arctan(-t/sqrt(1-t^2)))
. We may solve this for t
on either side of the parentheses and substitute into the other side (with some multiples of π/2
added to center the result on θ_t=0
), which gives x_d=arctanh(+-1/sqrt(tan(θ_t)^2+1))
and θ_t=arctan(+-sqrt(1-tanh(x_d)^2)/tanh(x_d))
where programmatically it is better as arctan2(+-sqrt(1-tanh(x_d)^2),tanh(x_d))
. Now in a simulation we may determine the initial angle θ_t
between driving vehicle and trailer, solve for x_d
, then increment or decrement x_d
in accordance with the desired motion of the driving vehicle along a straight line, then use the updated x_d
to solve for an updated θ_t
to apply to the trailer. This is numerically stable because the angle of the trailer is updated without dependence on its position (so small errors between trailer location and hitch location do not turn into gigantic acceleration forces, as would happen if F=m*a
were enforced with a rigid link). It is also independent of the number of simulation steps along a straight line, since an exact solution is used.
A plot of the "angular trailer curve" as defined above.
We may expect that the straight line solution above will give a useful answer for a driving vehicle moving along a circular path as well, when we represent the circle as an inscribed polygon of increasingly many equal sides, and calculate θ_t
along the straight line sides one after another. This gives an opportunity to do another validation.
With the requirement that a trailer moves along a trajectory that is tangent to the direction of its fixed wheels, at the center point of the fixed axle, and given that the towing vehicle moves along a circle, we can determine the limiting radius which the trailer will reach after being towed around the constant radius circle many times. Based on geometric considerations with a right triangle, we find R_lim=sqrt(R_d^2-L^2)
, where R_d
is the radius of the towing vehicle hitch. The trailer will always end up inside the turning circle of the towing vehicle. R_lim=0
for R_d=L
and is not defined for R_d<L
where the situation is unstable, and we will return to these cases later. For the purposes of this validation, we can use cases where R_d>L
, and check that stepping through a circle incrementally will result in a simulated trailer radius that matches R_lim
.
A driving vehicle {blue rectangle} is turning along a circular trajectory such that the hitch point {small filled circle} for the trailer {red rectangle} travels along a circle of radius R_d
. In the limiting case, the trailer (with length L
to equivalent back wheel) is oriented to be tangent to a concentric circle, from which we may calculate R_lim
.
One revolution of the driving vehicle with R_d=(5/3)*L
is simulated by dividing a circle into 50 linear segments and moving along them one by one. The hitch point {green squares} starts at the rightmost side of the circle and travels counter-clockwise, pulling the trailer {red and blue dots} behind it. In the scenario with red dots, the trailer starts directly behind the vehicle and approaches R_lim
from the outside. In the scenario with blue dots, the trailer starts inside the turning circle and approaches R_lim
from the inside. The dashed black circle is the expected R_lim
from the formula above.
The ability of the straight-line equations above to match R_lim
with a sufficiently fine angular step (in this case about 200 per circle) is promising for continuing this derivation. With R_d=L
the trailer radius should indefinitely approach 0 without oscillations. With R_d<L
, interesting patterns of trailer motion emerge, which may eventually loop on themselves. Both of these present "stress tests" for the simulation, and are found to give visually indistinguishable answers with angular steps increased to about 2000 per circle.
Four revolutions of the driving vehicle with R_d=L
, similar configuration as preceding figure. Red dots are calculated on a path divided into 500 segments, while blue dots are calculated on a path divided into 50 segments. The red dots converge towards R_lim=0
as expected from theory; the blue dots pass through this limit due to numerical inaccuracy and the trailer starts to be pushed back to increasing radius.
Four revolutions of the driving vehicle with R_d=(1/2)*L
, similar configuration as preceding figure. Red dots are calculated on a path divided into 500 segments, while blue dots are calculated on a path divided into 50 segments. The simulation is again seen to be sensitive to step size.
Five revolutions of the driving vehicle with R_d=(3/5)*L
{left} and R_d=(4/5)*L
{right}, similar configuration as preceding figure. Red dots are calculated on a path divided into 500 segments, while blue dots are calculated on a path divided into 50 segments. By solving with small step sizes, it is confirmed that the trailer path loops back on itself. Thus, discrepancies between the final and initial locations of the trailer may be used to evaluate numerical inaccuracy. The low-resolution blue steps are significantly in error at the end of the path, and the red steps are only slightly displaced.
Discretizing a circle into 2000 linear segments is no problem for today's computers, but presenting this as the mathematical core of the simulation seems underwhelming. This would mean that the accuracy of the simulation is step-size dependent, and while this may be tolerable for a single trailer, if there are multiple trailers in a problem, each moving along non-straight paths, the inaccuracies will add up and possibly render the whole scenario in an unphysical manner. Therefore we search for a bit more inspiration to extend the above straight-line towing solution to the case of towing along any circular arc.
We expect the curves we seek to be related to the straight-line solution, because a straight line is the limit of a circle at infinite radius. We may change the problem from moving the vehicle and trailer on a path in the 2D plane, to moving the plane under a fixed driving vehicle and a trailer that is free to turn about the hitch point where it connects to the driving vehicle. Since the point at the center of the turning circle and the hitch point define a line of symmetry, we would not lose generality by centering the turning circle on (0,0)
and placing the hitch point at (R,0)
where R
is the turning radius as measured at the hitch point; the angle traveled along the turn circle is given by phi
. With this change, we redefine the sense of θ
, as above θ_t=0
meant the trailer was on the same line as the driving vehicle's direction of travel, while now θ=0
means the trailer is at a right angle to the driving vehicle and closest to the point about which the driving vehicle is turning (that is, inside the turning circle). We also redefine x
in terms of the hitch point motion (which above was x_d
). This allows us to apply a symmetry condition as the vehicle moving forward with θ
is equivalent to the vehicle moving backward with -θ
. The model is that of a phonograph turntable, where the hitch point of the driving vehicle is represented by the fixed end of the tone arm, and the back axle of the trailer is represented by the stylus riding on the vinyl disc, while the disc represents the road surface as the driving vehicle makes a turn about a point at the rotation axis of the turntable; θ=0
corresponds to the stylus being closest to the turntable center.
A trailer {red rectangle} with hitch {filled circle} towed along a circular arc {dotted circle outline} of radius R
. The clockwise angle θ
from the radius line to the trailer forward vector is to be defined in terms of the distance x
{curved arrow} traveled along the circular arc.
The coordinates of the trailer back axle center are then (t_x,t_y)=(R-L*cos(θ),-L*sin(θ))
, while the forward vector of the trailer is (L*cos(θ),L*sin(θ))
. The effective radius of the trailer is P=sqrt(t_x^2+t_y^2)=sqrt(R^2+L^2-2*R*L*cos(θ))
. Since the trailer can only move along its forward vector instantaneously, we take the dot product (R-L*cos(θ))*(L*cos(θ))+(-L*sin(θ))*(L*sin(θ))=R*L*cos(θ)-L^2
, and divide by L*P
to obtain (R*cos(θ)-L)/sqrt(R^2+L^2-2*R*L*cos(θ))=dθ/dv
where dv=dφ*P
is the motion of the surface under the trailer. At the hitch point dx=dφ*R
, so then dθ/dx=cos(θ)-(L/R)
, a surprisingly elegant result. In the limit of L/R=0
which is the case of straight-line travel, we have θ=2*arctan(tanh(x/2))
which is a negated and π/2
-shifted version of θ_t=arctan(sqrt(1-tanh(x_d)^2)/tanh(x_d))
, as expected from the new definition of θ
. Therefore we have agreement with the earlier derivation; the simpler form of the equation in θ
suggests that the new choice is more natural. Now we can go further and determine the limiting angle that the trailer will reach after a long distance traveled along a constant radius turning circle, that is dθ/dx=0
at θ_lim=+-arccos(L/R)
, which agrees with the direct geometric solution. When L≤R
there are two limiting cases (+-)
, one for forward and one for reverse travel of the driving vehicle, while at L>R
there are no stable positions for the trailer as it oscillates about the turning center.
Then define A=L/R
and solve the differential equation for θ(x)
, where x
is normalized to be represented in multiples of L
. The solution takes different forms for different ranges of A
:
0≤A<1
θ_lim=+-arccos(A)+2*π*N
(where N
is an integer). The trailer will always remain in the same region as it started. At A=0
(straight line travel or infinite turning radius) the regions are of equal size. Region 1 is inside the turning circle (θ
close to 0), and there θ=2*arctan((1-A)/sqrt(1-A^2)*tanh(sqrt(1-A^2)/2*x))
. Region 2 is outside the turning circle (θ
close to π), and there θ=π-2*arctan((1+A)/sqrt(1-A^2)*tanh(sqrt(1-A^2)/2*x))
. As A
approaches 1, region 1 shrinks to just θ=0
, while region 2 expands to cover 0<θ<2*π
and the function smoothly transitions into the subsequent case.A=1
θ=2*arccot(x)
which when applied to a moving-vehicle (rather than moving-ground) frame describes a tractrix spiral. The trailer moves towards but never quite reaches the turning center, in the limit of either positive or negative increasing x
. As A
increases beyond 1, the function discontinuously changes (which can be made continuous at a point in space for purposes of the simulation) to an unstable oscillation.A>1
θ=2*arctan(sqrt((1-A)/(-1-A))*tan(x*(1-A)/2*sqrt((-1-A)/(1-A))))
. There is no limiting value for θ
as it periodically traverses the whole range of angles. Since R<L
, the trailer arm is repeatedly swung outside the turning circle and pulled back in. We can now find conditions for which the trailer path will oscillate and loop back on itself, of which we encountered two cases above by accident. This occurs when N=A/sqrt(A^2-1)
is a rational number, or when A=N/sqrt(N^2-1)
as the function is its own inverse; both A
and N
happen to be rational for A=5/3
and A=5/4
.A<0
-A
when the result is negated and shifted by a factor of π
.Then, to simulate trailer motion given a known hitch point trajectory of turning radius R
and distance Δx
, we pick the applicable equation from above, invert it to solve for x(θ)
using the known starting angle of the trailer, then solve back again for θ(x+Δx)
at the end of the trajectory.
Five revolutions of the driving vehicle with R_d=(3/5)*L
{left} and R_d=(4/5)*L
{right}. Red dots are calculated on a path divided into 500 segments, while blue dots are calculated on a path divided into 50 segments. Unlike the previous approach using linear segments, the newly developed approach uses curved segments, so the solution remains precise independent of step size for circular paths.
As fun as the above derivation was, and having thus an exact solution for a vehicle with one trailer, we cannot extend the result without a general method to obtain the (R,Δx)
values. For a vehicle moving on a circular trajectory these values can be found with a bit of geometry, but we would like to extend this to vehicles not moving on a circular trajectory, so that in the simulation we can have a trailer pulling another trailer. A trailer will move along its own version of the "trailer curve", and we need to represent a segment along that curve in terms of (R,Δx)
. Furthermore, this representation should be stable for the case of straight line travel, where R
would tend to infinity. Thus instead of the turning radius R
we use the curvature k=1/R
.
Two points which have defined forward vectors {green arrows} may be connected by an arc whose radius and length are computed from the linear distance D
and the forward rotation Δθ
.
Given two 2D points X1
and X2
, and rotation of the mechanical frame θ1
and θ2
at those points, where the trailer hitch moves from the first point to the second, we need to find the best arc connecting these points, and the arc curvature is k
while arc length (normalized to L
) is Δx
. Since the situation is symmetric, the arc center must be along the line which is the perpendicular bisector of the line between X1
and X2
, and we know the arc angle is Δθ=θ2-θ1
. With D
as the linear distance between X1
and X2
, we can then draw a right triangle with hypotenuse R=(D/2)/sin(Δθ/2)
, so k=sin(Δθ/2)/(D/2)
. The arc length is Δx=R*Δθ=(D/2)*Δθ/sin(Δθ/2)
. In the simulation, Δθ
may approach 0, for which the previous equation is not defined, however it has a nice limit represented with a Taylor series expansion Δx=2+Δθ^2/12+7*Δθ^4/2880+...
which is accurate to more than 9 digits with Δθ<0.1
or using just the second order term with Δθ<0.01
.
This seems like all the ingredients, yet a simulation made with the above formulas would work for only half of the turning circle, in another half giving reversed results. This was a bit of a headache to figure out due to the different rotating and moving reference frames (the driving vehicle, the trailer, and the level), so I'm not sure if the solution I found is the most mathematically elegant. The challenge is that in the above paragraph we defined D
as a distance which always has a positive sign, so the resulting (k,Δx)
does not differentiate well between the 4 quadrants made by combining left-right and forward-backward. We resolve this by defining the turning radius as positive for left turns and negative for right turns, and then Δx
is always positive while k
may be positive or negative. The trailer angle is then referenced to the vector from X1
to X2
rather than to the forward travel vector of the towing vehicle. This makes the solved value of x
discontinuous between forward and backward motion (since a backward turn is treated as a forward turn), however the result is still correct, and since we expect to solve for x
in each step of the simulation anyway due to the general motion profile, this should not pose a limitation on the solution.
Finally we consider how to implement the driving vehicle's path along a circle of a known but large radius with a known arc length, for a front wheel drive. The goal is to avoid numerical instability as the path approaches a straight line.
A driving vehicle {green rectangle} bicycle model with known steering angle θs
and wheel base H
travels forward by Δx
with the equivalent front wheel, from which the displacement of the equivalent rear wheel (ΔX,ΔY)
may be calculated.
We define a steering angle θs
which is the angle the front equivalent steered tire makes to the vehicle's forward travel vector. With wheelbase (distance between front and back equivalent axles) H
the turn radius at the back axle is W=H/tan(θs)
, and at the front axle R=H/sin(θs)
. With an arc length Δx
traveled by the front wheels, the angle traveled is Δθ=Δx/R=Δx*sin(θs)/H
. An equivalent back wheel located at (W,0)
will travel to (W*cos(Δθ),W*sin(Δθ))
which as a displacement is (ΔX,ΔY)=(W*(cos(Δθ)-1),W*sin(Δθ))
. At small θs
, Δθ
goes to zero and W
goes to infinity meanwhile the displacement has a nice limit, so we can use Taylor series expansions for sin(x)=x-x^3/6+x^5/120...; cos(x)=1-x^2/x+x^4/24-x^6/720...; tan(x)=x+x^3/3+2*x^5/15...
. Then we find (ΔX,ΔY)=(-(Δx^2*cos(θs)*sin(θs))/(2*H) + (Δx^4*cos(θs)*sin(θs)^3)/(24*H^3) - (Δx^6*cos(θs)*sin(θs)^5)/(720*H^5)..., Δx*cos(θs) - (Δx^3*cos(θs)*sin(θs)^2)/(6*H^2) + (Δx^5*cos(θs)*sin(θs)^4)/(120*H^4)...)
. The above is accurate to more than 9 digits using 2 terms for (Δx<H,abs(θs)<0.01)
and 6 digits using 1 term for (Δx<0.1*H,abs(θs)<0.01)
.
By finding the displacement and rotation of the vehicle's reference frame, we can apply a transformation to any other point on the vehicle to find where it is relocated. Then this point may be used as the hitch point for a trailer, and the trailer motion solved for in a similar manner. The motion of the trailer's trailer (and so on) may be found by applying the above equations for the respective reference frames. The mathematical basis of the simulation is therefore ready.
The simulator is written in C# using the Windows Presentation Foundation (WPF). This may not be a first choice for writing games, however it implements a visual layout system which allows rendering transforms (such as scale, offset, and rotation) to be applied to different elements, and the necessary updating of pixels takes place automatically, which minimizes the graphics-rendering code I need to write. Additionally, C# with Visual Studio provides a serialization library which can import XML files and generate classes with defined properties, which makes the ability to load custom level files almost effortless, as long as the classes are defined reasonably with regard to the intended XML output. Thus using WPF allows me to concentrate on the simulation physics while still generating a pleasant UI. The choice of classes and how they interact is then guided by the calculation and rendering requirements as well as by the desired XML structure. Although programming in this manner is a recent skill for me, I have come to enjoy it as it eliminates the mental load and dullness of copying from one custom format to another (such as making a parser to read text lines and instantiate classes from that) and keeping everything updated (such as copying from an internal position variable to an external screen location variable), rather the informational content is defined only once (in the class definition itself) and everything else is implicitly derived from there.
There is a MainWindow
, which loads a Level
from a serialized XML file and provides all common UI elements. The Level
contains XShape
geometry defining the static visual features of the level, and one DrivingVehicle
which is controlled by the player. The DrivingVehicle
contains its own XShape
features (which translate and rotate with the vehicle as it moves in the level plane) and SteeringWheels
which rotate to indicate the steering angle (this is a purely visual effect, the angle of these shapes is not used for the path calculation). The DrivingVehicle
optionally contains a Trailer
, which has XShape
features (which translate and rotate with the trailer as it is moved by the driving vehicle) but no SteeringWheels
. The Trailer
optionally contains another Trailer
, and the train may be extended as desired by defining more trailers.
The above class structure is directly reflected in the XML files that define a level. Attributes in each class are used for the mathematical structure of the level. The most important ones are the hitch and link points, where the hitch point of a driving vehicle (or trailer) connects to the link point of its trailer, each defined in local coordinates. To avoid too many degrees of freedom, each vehicle must be defined such that the center of its fixed axle is at (0,0)
and its link point is at (x>0,0)
in its local coordinates (a link point at y≠0
breaks the assumptions of the above derivation and cannot be simulated); a hitch point may be defined anywhere in the plane. For a driving vehicle, it is not linked to anything else, so the link point defines the center of its equivalent steering wheel. To clarify the coordinate frames, the attributes involving the vehicle frame are prefixed with a "v" such as vx_link
for the link point, while the attributes involving the level frame are prefixed with a "l" such as (lx_initial,ly_initial)
for the initial location of the driving vehicle in the level frame (which maps to the origin point in the driving vehicle frame). The following is an overview of a level definition:
<title></title>
Level title<description></description>
Level description<pixel_scale></pixel_scale>
Scale to map level coordinates to pixels. A larger number makes the level appear bigger. The level is presented such that the nominal width and height is 1000 pixels.<decorations></decorations>
Level static geometry
<XShape></XShape>
Shape definition
filltype=""
Describes geometry type. -1
for dashed open line, 0
for solid open line, 1
for closed polygon, 2
for closed and filled polygon.thickness=""
Geometry outline thickness in level coordinates ie it will be scaled by pixel_scale
.hitgroup=""
Defines what other shapes may collide with this shape to display a crash error (not implemented).note=""
An optional text description of what the geometry represents.xoffset=""
, yoffset=""
Shifts the origin of the defined points
to this point in the parent frame.aoffset=""
Rotates the defined points
by this angle about the shape origin. This is defined in counter-clockwise degrees and applies prior to x and y offset translation.<points></points>
Comma-separated points in level coordinates, written as X1,Y1,X2,Y2,X3,Y3...
. For a closed figure type, a line will be drawn from the last point to the first point (there is no need to manually close the figure).XShape
s...<drivingVehicle></drivingVehicle>
Driving vehicle. In the vehicle frame, the origin (0,0) is the location of the equivalent fixed wheel, with its direction of travel fixed along the x-axis.
lx_initial=""
, ly_initial=""
, la_initial=""
Describes the initial offset and rotation of the driving vehicle in the level frame. The offset refers to the origin point (fixed axle center) of the vehicle frame. The rotation is defined in counter-clockwise degrees.va_steering_limit=""
The limit of angle by which the equivalent steering wheel may be turned from its forward direction. This is defined in positive degrees and is symmetric about zero. This is defined by the mechanics of the steering wheel and is independent of vehicle length, so a typical value of 30 degrees applies to many cases. This value must be defined otherwise steering will not work.vx_visual_center=""
, vy_visual_center=""
Describes the point in the vehicle frame which will be centered on the screen. The level will be translated so that this point remains centered. Typically this is the point where the driver seat would be located in the vehicle.va_visual_right=""
The angular direction which should be displayed as pointing to the right when drawing the level. Defined in counter-clockwise degrees, a value of -90
will render the vehicle forward direction facing upwards on the screen.vx_hitch=""
, vy_hitch=""
, va_hitch_limit=""
Describes the point in the vehicle frame which will be used to connect a trailer. Only needs to be defined if a trailer is attached. The angle limit will generate an angle-exceeded error when the trailer is turned at a tight angle; the limit is defined in positive degrees and is symmetric about zero.vx_link=""
Must always be defined as a positive value. This is the location of the equivalent steering wheel along the x-axis and is used for trajectory calculations. The y-component is always 0.<description></description>
Vehicle description<shapes></shapes>
Vehicle static geometry in vehicle frame
<XShape></XShape>
Shape definition, identical to earlier.XShape
s...<steeringWheels></steeringWheels>
Driving vehicle steering wheels. These shapes turn when the steering angle changes, corresponding to Ackermann geometry derived from vx_link
. The elements here are purely visual and do not affect trajectory computation.
<SteeringWheel></SteeringWheel>
Shape definition, identical to XShape
with two extra parameters:
xpivot=""
, ypivot=""
When steering, the steering wheel pivots about this point (in shape coordinates) in accordance with Ackermann geometry.XShape
SteeringWheel
s...<trailer></trailer>
Trailer definition, shares many of the features of driving vehicle definition. The origin (0,0) is the location of the equivalent fixed wheel, with its direction of travel fixed along the x-axis.
la_initial=""
Describes the initial rotation of the trailer in the level frame, defined in counter-clockwise degrees. The initial x and y coordinates for the trailer will be calculated based on the driving vehicle it is attached to.vx_hitch=""
, vy_hitch=""
, va_hitch_limit=""
Describes the point in the trailer frame which will be used to connect a trailer, identical to earlier.vx_link=""
Must always be defined as a positive value. This is the location in trailer coordinates where the trailer attaches to its towing vehicle's hitch point. The y-component is always 0.<description></description>
Trailer description<shapes></shapes>
Trailer static geometry in trailer frame, identical to earlier<trailer></trailer>
More trailers may be added as necessary.Making the levels was somewhat challenging because I needed to find realistic vehicle dimensions and set up visual elements that would allow the vehicle to be maneuvered around them. Using mechanical drawings I could find online and road design guideline figures from NCHRP Report 505 Appendix C "Turning Performance Analysis of Specific Design Vehicles", I compiled a list of reasonably accurate vehicle shapes and wheel bases for 16 vehicles ranging from a passenger car to a tractor trailer. The airplane, truck, schoolbus, and passenger vehicle levels contain more detailed visuals based on tracing satellite view maps. The forklift, articulating bus, passenger bus, and airport luggage levels have only a few simple squares to use for practicing parking or turning near them. It should be an easy matter to add more decorations and obstacles if someone cares to do so, with the already completed vehicle definitions providing a starting point. The 16 included levels may be divided into categories based on the number of articulation points:
The passenger vehicle level is set in a parking lot allowing to practice forward, reverse, diagonal, and parallel parking at various locations.
The small and large schoolbus levels are set in a bus maintenance facility.
The small and large delivery truck levels are set near an industrial building with two delivery docks at the back.
The truck levels (tractor trailer, small and large A-train double, single unit A-train, B-train double) are set by a package handling facility with many spaces where parking maneuvers could be practiced.
The airplane pushback levels (A380 and B737) are at an airport with dashed lines indicating boundaries and travel routes.
A question may arise whether it is even possible to reverse-park some of the more complicated configurations. Mathematically, the scenario is fully deterministic and reversible, so if it is possible to drive forward out of a parking spot, it is also possible to reverse into the same spot; however driving forward is stable in terms of steering angle, while driving in reverse is unstable, so keeping the vehicle under control requires a lot more care in accurately setting up small angular alignments. There are videos demonstrating this for 0 to 3 articulation points, and it appears that 3 and 4 seem to be too difficult to be used in practice, though there must be tales of drivers being able to reverse these as well.
The remainder of the software is minimal and set up to handle basic interactions: a button to load a level file, checkboxes to fix the camera location and rotation on the driving vehicle, and a zoom slider. The driving vehicle is controlled using the keyboard arrows, with left and right turning the steering wheel, and up and down moving the driving vehicle forward and backward (the distance increment associated with each key press is calculated based on the smallest pivot arm of the vehicle and trailers). This input method can become a bit frustrating, but I think that could be considered a "feature" for a parking simulator. It is also possible to press R to reset the level back to its original state. Presently there is no hit testing implemented, so it is possible to drive over boundaries or exceed safe angles for trailer hitches, and we rely on the "honor code" that players would complete a level in a reasonable manner. The C# code files may be downloaded here. The executable (for .NET 7.0) and level files may be downloaded here.
This program successfully loads and simulates different vehicles with trailers for parking scenarios. Mathematically the simulator is sound, accurately solving vehicle trajectories with any angle between trailers. Sensitivity to small angles is also well represented, with the history of the trailer's motion stored as slight angular deviations from a straight path even after multiple vehicle lengths of travel, which is useful in generating an unstable scenario when reversing multiple trailers, as may be expected in the real world. Generating levels has proven to require a lot of manual effort, and this task should be simplified (such as by using existing images or by making another program with a GUI for generating levels) if the simulator is to be used on a frequent basis. However for the levels that I was able to implement, driving the vehicles and attempting to park them has allowed me to better understand the principles of maneuvering loads with multiple articulation points. The simulator does not replace driving experience, as in the simulator I get a top view and perfect forward and backward repeatability, but practicing with the simulator will make it much easier for me to learn in a real setting. I would consider this project a success.