I've been playing with Kerbal Space Program for a while, a game whereby you construct and fly rockets around a simulated solar system, loosely based of our own. The accuracy and breadth of the game is truly incredible. The challenge and feeling of satisfaction of getting your probes, or Kerbals (cute astronauts) to other planets is truly incredible. I found my interest with this game got taken to a new level when I found I could write software to control my rockets. I could pretend to be Elon Musk and try to land my first stage orbital class boosters back on the launch pad. This is truly challenging to do manually, (though it has been done), but I wanted the challenge of doing it via a program. I first used kOS (Kerbal Operating System). kOS uses its own fairly simple programming language and works within KSP. I moved to kRPC when the complexity I've what I was doing far exceeded what kOS provided. kRPC has an APIs for Python, Java, Ruby etc... and uses an RPC mechanism which the full power of the native language including any external modules. As a Python programmer I can now use the full power of Python modules such as numpy, matplotlib and cvxopt. I was trying to land rockets from orbit but the part which really interested me was steering the rocket at low altitude and speed to compute optimum thrust directions for a minimum fuel descent. I came across some research papers and larsblackmore.com, Lars Blackmore seems to be one of the key researchers in this field and currently heads SpaceX's entry, descent and landing of the Falcon 9 rocket. Some of the key papers here www.larsblackmore.com/iee_tcst13.pdf. The main one is this:
The great insight appears to be making the problem convex which makes it solvable by proven inequality solvers in a defined and short period of time (milliseconds) rather than a much more limited and slower techniques. Heres a video of same NASA tests of the G-FOLD algorithm which is the name for the above technique (probably): Now, I work in software engineering and speech recognition. I have basic knowledge of vector, matrixes, linear algebra, equations of motions but the only convex optimisation problem I'd solved was minimum least squared error. Hence followed several weeks of trying to understand this paper and the field of convex optimisation. The problem is neatly described by this picture: So we solve for a given number of thrust directions/throttle or acceleration vectors distributed over the flight time, with the constraint that the final position is (0,0,0) and that the final velocity is (0,0,0) given an initial position and velocity. An important point to realise is that we can largely solve this problem independently for the XYZ axes and that we don't have to compute the full trajectory to solve the problem, since its only really the final position that matters. At landing all the accelerations must sum to cancel out the initial velocity and the accumulated movements caused by these accelerations must move the craft from the initial position to the origin, plus gravity of course. The problem is posed so solve for the minimum fuel for given amount time, T. We really want the time, Tmin, that gives the minimum fuel, so you have to solve for a range of T's, the golden section search algorithm is good one for this problem. We can't quite solve the XYZ axes independently because the magnitude of the acceleration vector must need exceed the maximum thrust of the craft, this ties the axes together makes this a Second Order Cone Program (SOCP). I believe it is the mathematical trick which allows the magnitudes of the acceleration vectors to be translated into new variables enabling minimum and maximum thrust constraints and enables the total thrust over time (or fuel usage) to be minimised that makes the problem convex. How to solve such a problem, well, there is a Python module called CVXOPT which would do this hard work for me. I just needed to set up the correct matrices to define the problem. That was hard. Once I'd setup a basic solver, which took many weeks of evenings, I gradually added new constraints to help avoid various problems:
I'm missing an important point. Now you have a trajectory (a time ordered list of triples of position, velocity and accelerations) you need to fly the rocket along it. Easy I thought, just point the rocket in the right direction and set the thrust. Not so easy, because the rocket might not behave quite as you planned due to:
Steering to the trajectory The trajectory is shown on the videos as a white line, with desired thrust vectors shown as red lines, there is also an associated desired velocity (length of each line segment) for each point in the trajectory. The trajectory is computed not by solving the solution itself but by applied the equations of motions for short time steps from the initial state using the desired thrust vector for each point in time. The trajectory positions are shown as the white line. The desired thrust vectors are shown as red lines, with the length denoted the amount of thrust. The green line is the current thrust vector, which differs from the red line if off trajectory. I spent a long time getting the trajectory following to work. The problem is that once the craft is off trajectory how to we regain it? Simply fire rockets to the nearest point? No, we'd get to the nearest point but going in the wrong direction! The best solution I found was to calculate the nearest point in the trajectory using a weighted sum of position AND velocity error. This helps choose the correct point in the trajectory when it crosses near itself, and helps the craft aim for a trajectory where both position and velocity are close, which may be ahead or behind. Some issues were problematic. What about reaching the end of the trajectory at the precise moment of landing. The trajectory says apply full thrust with velocity zero, trying to do this for a moment too long will result in going upwards again! Once you have the closest point how to adjust the thrust direction and throttle to steer back to the trajectory. I found that adjusting the desired thrust vector by a combination of the position error and velocity error each multiplied by some gain worked well. I use 6 very similar PID controllers with only P set, I and D are zero. I've got this method to work with a range of craft, but heres one which worked very well, and the very similar Zombie shown in the videos. Grasshopper 2A Here's a basic rocket I used for experimentation as it is highly maneoveable.
Running the code Firstly you need to install kRPC, which runs in version 1.3.1 of Kerbal Space Program. Then you need to unpack the Python code for G-FOLD and the trajectory following. Find this code here. The code consists of several modules:
plot_pid.py - plots for XYZ position and XYZ velocity PID controller actual, set point and output signals across time.
This simulation has gone very well with little error between the actual and predicted values. Heres a video with some captions telling you whats happening, the craft lands somewhere surprising, perhaps? Heres a collection of the successes, using some different craft and landing locations. I finish with a larger craft testing drone ship landings - these need some improvement, the landing is rather sedate - I'd like to get a bit more speed, thats my current project... Here's some occasions where it went wrong.
1 Comment
|
AuthorI like the challenge of writing control software for rockets (in simulation!) ArchivesCategories |