autorope / donkeycar

Open source hardware and software platform to build a small scale self driving car.
http://www.donkeycar.com
MIT License
3.05k stars 1.28k forks source link

Implement a global path optimizer for path follow template #1129

Open Ezward opened 1 year ago

Ezward commented 1 year ago

The current path follow template records a set of way-points and then follows them. It will also record throttle values with each way-point. However, when the way-points are gathered it is usually better the drive slowly and accurately to get way-points that are accurate and close together. The resulting path will definitely not have race-quality throttle values or possibly an optimal racing path.

It is a common practice in autonomous racing to map the track then calculate an optimal path around it that includes way-points with velocity. The Indy Autonomous Racing team from the Technical University of Munich (TUM) have open sourced their global race trajectory optimizer which is written in Python. This is a very sophisticated algorithm that can calculate a trajectory at the limits of traction/stability. TUM also has simpler optimizers; one for optimizing for minimum curvature and one for optimizing for shortest path. There are other algorithms that use reinforcement learning to calculate a trajectory, for instance https://github.com/byronbenharris/reinforcement-learning-trajectory-optimization.

In this process we need to think about:

In all of this we want to anticipate what the workflow for the human will be. This needs to be easy enough for a Donkeycar user to accomplish at a new track on the day of racing. What follows is a description of 4 command line applications that can be used in a pipeline to calculate an optimal race trajectory for a given car and race course.

1. Measure Vehicle Parameters

At a minimum we need to know the maximum speed/throttle we would want to apply (the value we would apply on a long straight) and the minimum speed/throttle we would want to apply (around the tightest turn on the track). These can be determined by driving the course manually and recording the way-points. Since Donkeycar records throttle rather than velocity we can estimate the velocity using the way-point position and time values between in the recorded path.

The current path follow template does not use velocities; each way-point is tagged with the throttle value that was being applied at the time it was recorded. Throttle may be fine for our purposes. We simply use throttle as a proxy for velocity. However, if we want to include velocity in our calculations, we will need to update the path recording code to include millisecond timestamps on each way-point in the path so we can calculate velocities. The following sections reference throttle/velocity, with the hope that we will be adding optional timestamps to the recorded path.

The human driver may be hesitant to drive the car to it's limits, so we should allow them to 'tweak' the minimum and maximum values using scaling factors.

NOTE: Throttle values are recorded as a range of -1 to 1, where -1 is maximum reverse throttle, zero is no throttle, and 1 is maximum forward throttle. Those values are used to calculate a PWM value that is use to control the motors (see actuators), so there is some interaction with how the PWM values set when the car is calibrated. It is common for a user to choose a PWM value for the maximum throttle that is considerable less than what the motor can actually do. I do this myself so that I know that when I am driving manually I can go full on the joystick and still be able to control the car. With our autopilot and optimized trajectory I hope we can do better than a timid human driver like myself, so it's possible we could end up maximum throttle values > 1.

These outputs will be needed we calculate the target throttle/velocity for way-points in the optimized path. Ideally the command-line application will write these out to a file that can be used as configuration input to subsequent steps.

2. Calculate the Drive-able Area

The path follow algorithm outputs path consisting of way-points and an optional throttle value. We need to have a 'map' of the drive-able race area in order to calculate an optimized trajectory. A simple way to define the drive-able area is to have a human drive in the middle of the track while recording a path (or even just hold the car and walk down the middle of the track). Then a width can be given to the path using each way-point as the center of the path. So for each way-point, calculate a tangent using the way point and the one before it and the one after it. The calculate a perpendicular to that tangent and apply the track width to get the left and right boundary at that point.

3. Trajectory Optimization Algorithm

The simplest algorithm that offers the most stability would be to optimize for minimum curvature. The TUM solver for minimum curvature does not calculate velocities, just the path. So we need to add code to calculate velocities at each way-point (see section 4).

The TUMFTF code can take in a lot of parameters to use in this calculation. For our purposes we should make sensible defaults for most parameters and then make it easy to change these defaults.

4. Calculating Target Way-point Throttle/Velocities

As simple way to handle velocity is to apply a scaling factor based on curvature (or inverse curvature) at each way-point; calculate curvature range and use this to map between the minimum and maximum target velocities that were measured/configured in a previous step. The most simplistic approach would be to apply the throttle/velocity for the target way-point. This is not great when using our simplistic line follow algorithm based on cross-track error. It can be improved by taking a second pass that looks ahead in the waypoint list based on the first pass target velocity for the way-point and fixes up the target velocity based on the maximum curvature it would encounter at the look ahead point, so when we are going fast we look ahead for curves and start to slow down before we get there.

The output is a new path where each way-point has an (x,y) position and a target throttle based on the optimal path and the velocity calculation. This is the path that the Donkeycar path follow autopilot will use.

Summary

So we 4 parts to this pipeline:

  1. Determine the car's minimum and maximum target throttle/velocity values around the track.
  2. Use a path recorded in the path follow template that is assumed to be the center of the race track and convert this to drive-able area suitable for input into the TUM solver for minimum curvature.
  3. Integrate the TUM solver for minimum curvature to produce an optimized race line.
  4. Add target throttle/velocity values to each way point on the optimized race line. Output the optimized race line with throttle in the path follow template format so it can be used directly in DonkeyCar.
Ezward commented 5 months ago

TUM also has open sources some useful Python functions to help with the race line optimization task https://github.com/TUMFTM/trajectory_planning_helpers