Spaceship controls -> autopilot

Started by
17 comments, last by scippie 4 years, 10 months ago

I am creating a simple spaceship sim with 6DOF flying.

For the ships' angle, I use a quaternion and with the keyboard, I can change yaw, pitch and roll separately which result in three quaternions which are multiplied into the current rotation. The rotation force is limited by a value [-1.0 ... 1.0] and is built up gradually, not only to simulate joystick controls on the keyboard, but also because it feels realistic that the thrusters must build up their power.

Then, I also have a throttle [0.0 ... 1.0] which makes the ship move in the direction of the rotation.

Now, I am trying to create an autopilot and the first thing I need is auto-aim. When I am looking at a planet in front of me and I want the autopilot to move to the planet behind me, I need it to handle the rotation and the thruster to get there.

Simply doing quaternion interpolation (slerp) is not acceptable as this does not allow me to limit the thrust-force (or in other words, I would not be able to know how much my thrusters would be burning). Also, this would not take the building up of the power for the thrusters.

I have tried just coding it as it feels, taking the polar directions of where I am looking at and the polar direction of where I am going to and just adjust yaw and pitch thrusters to rotate there, but as you know, rotation with quaternions isn't as linear as I would hope and the result is constantly reviewed which not only makes it look unnatural but also makes it do spirally smaller getting circles around the target because of the thruster-forces which I don't really know how to calculate accurately because of the same reason.

Can anyone give me some tips and/or point me to a solution?

The math currently is like this:

yaw_thruster, pitch_thruster, roll_thruster are values between [-1 ... 1] and are added with a factor in function of passed time.

rot_x_axis, rot_y_axis, rot_z_axis are axis-angle quaternions with the thruster values * passed time as angle.

They are all multiplied with the ship rotation on every frame and I normalize the ship rotation from time to time to handle precision errors.

I calculate polar direction vectors by calculating the (normalized) z-axis from the rotation and then: theta = atan2(z.x, -z.z), phi = acos(z.y).

These things all seem to work perfectly.

Advertisement

I don't have an answer (at this point at least), but maybe asking some questions would help. Here:

Quote

I have tried just coding it as it feels, taking the polar directions of where I am looking at and the polar direction of where I am going to and just adjust yaw and pitch thrusters to rotate there, but as you know, rotation with quaternions isn't as linear as I would hope and the result is constantly reviewed which not only makes it look unnatural but also makes it do spirally smaller getting circles around the target because of the thruster-forces which I don't really know how to calculate accurately because of the same reason.

I'm wondering what you mean by rotation with quaternions not being as linear as you'd hope. Managing rotations with quaternions isn't qualitatively different than doing so with, say, matrices (the differences have more to do with things like efficiency, convenience, elegance, etc.), so it might help to clarify what you mean by 'linear', and what you think quaternions are contributing to the problem specifically.

I'm also wondering about your use of spherical coordinates. If your spherical coordinates are in world space (which it seems like they might be), then I'll offer that it's not immediately obvious to me how world-space spherical coordinates would be effectively leveraged in a 6DOF context. So that might be something else worth looking at.

I think (but am not sure) that I've seen autopilot-like problems discussed here before, specifically with respect to managing thrust appropriately in order to reach (approximately at least) a goal orientation, but unfortunately I can't direct you to anything specific. Maybe someone else can though.

Meanwhile, I'll just say that my intuition is that the primary information of interest would be the target position expressed in the local space of the ship. It seems that given this information you could compute a relative yaw and pitch that would align the ship with the target (spherical coordinates would come into play here, but they'd be in local space rather than world space). Of course that does still leave you with the problem of how to manage thrust appropriately (which, again, I feel like I've seen discussed here before).

Edit: Here are some links:

https://www.gamedev.net/forums/topic/699302-calculate-the-amount-of-torque-impulse-needed-to-get-to-a-certain-orientation/?tab=comments

https://www.gamedev.net/articles/programming/math-and-physics/pid-control-of-physics-bodies-r3885/

https://en.wikipedia.org/wiki/PID_controller

The term I was trying to think of was 'PID' ('Proportional-Integral-Derivative'). Maybe those links and/or searching for that term will help (assuming I'm correct that it's relevant to your problem).

Recent similar topic is one page back:

It's in 2D, but you might be able to get some inspiration from it.

15 hours ago, Zakwayda said:

I'm wondering what you mean by rotation with quaternions not being as linear as you'd hope... so it might help to clarify what you mean by 'linear', and what you think quaternions are contributing to the problem specifically.

What I mean is that quaternions don't work in the yaw/pitch/roll sense. I know you can construct a quaternion from them, but then you could as well be using matrices and have gimbal lock problems.

What I mean is that if it were, I wouldn't be asking this question as I would just make sure the yaw and the pitch would linearly move to the target. But if you do this with quaternions, you are automatically influencing the other parts of the rotation. If you pitch, your yaw-axis is already changed and no longer has a reference to the original 3D axis.

15 hours ago, Zakwayda said:

I think (but am not sure) that I've seen autopilot-like problems discussed here before

...

Edit: Here are some links:

...

The term I was trying to think of was 'PID' ('Proportional-Integral-Derivative'). Maybe those links and/or searching for that term will help (assuming I'm correct that it's relevant to your problem).

I had already searched this forum (and others) extensively and had already found these discussions. I had found the PID approach and it was new to me and I know how they work and I might end up using it, but it is an inaccurate system which can easily lead to unforseen/untested bugs where your ship starts spinning because of its 'just try and then correct'-approach. Maybe I should have mentioned that in my OP.

Edit: also, the PID uses a fixed time-step between frames. I prefer to find a solution that works on fluctuating time steps.

I would really think that there should be a more mathematical, more robust solution.

12 hours ago, Alberth said:

Recent similar topic is one page back:

It's in 2D, but you might be able to get some inspiration from it.

Thank you, but it is so much easier in 2D. You just take a rotation and thrust to it (and I have done that one before). The problem is that by using quaternions, you no longer simply change one rotation, you automatically change them all, making the difference between your current state and the target change more than just in one angle. In 2D, you don't have that problem.

4 minutes ago, scippie said:

Thank you, but it is so much easier in 2D. You just take a rotation and thrust to it

Aren't you solving just 2 2D problems at the same time? Put the destination at the origin, and the ship is at some x,y,z point. Then at two orthogonal planes through the origin (say XY and XZ, but any two planes will do), you need to create trajectories such that both trajectories end up at (0, 0, 0) at the same time.

Once you have trajectories, you can find a way to make the ship follow that.

 

A completely different approach is to see the auto-pilot as a user. That is, it "presses" keyboard buttons just like a normal user would. If you're flying in the wrong direction you break and turn until you're pointing to the target, then apply thrust and break again to arrive at stand-still at the destination. It's not optimal, but maybe that is not a problem, it means a real user can outsmart the auto-pilot, so there is a good reason to steer the space-ship yourself.

 

17 minutes ago, Alberth said:

Aren't you solving just 2 2D problems at the same time? Put the destination at the origin, and the ship is at some x,y,z point. Then at two orthogonal planes through the origin (say XY and XZ, but any two planes will do), you need to create trajectories such that both trajectories end up at (0, 0, 0) at the same time.

Once you have trajectories, you can find a way to make the ship follow that.

Well, that's exactly what I was doing now and that is exactly my problem: calculating the thrust so that all trajectories end up at (0, 0, 0) at the same time. By changing the pitch of the ship, the yaw is already no longer valid as it will make your ship roll because of the normalized way quaternions work. Your XY/XZ plane as you put it, constantly changes.

Edit: and as you need to calculate all thrusting forces at a time before you apply them to the calculations that actually changes the ship rotation, they are immediately badly chosen.

17 minutes ago, Alberth said:

A completely different approach is to see the auto-pilot as a user. That is, it "presses" keyboard buttons just like a normal user would. If you're flying in the wrong direction you break and turn until you're pointing to the target, then apply thrust and break again to arrive at stand-still at the destination. It's not optimal, but maybe that is not a problem, it means a real user can outsmart the auto-pilot, so there is a good reason to steer the space-ship yourself.

This is not a completely different approach. I did it based on what you said above: looking at what my angles are now and where they need to be and just 'virtually pressing keys' until I get there. But calculating exactly when and how much to apply is what I am unable to do and the result is that the ship oversteers, so starts applying counter forces, oversteers again in the other direction, starts applying counter forces, etc... It will come to the end point most of the time after shaking back and fro several times but sometimes, the oversteering is so much that it starts rotating in circles and never gets there.

Steering too little will look silly, steering too much will make it go past the target. Calculating that exact number is what I am actually trying to ask. The suggested PID controller does this by trial and error, which is fine, but there also, it is a fine tuning of constant values which might be good in most situations but can generate untested situations where the ship will start spinning and never find its target, because... in the end, it comes to: well... we need to go there, let's just give some thrust and see what happens... while a human being will 'feel' where to go and will already start thrusting more aimed.

You don't compute when to reverse steering? Draw a line between the target and the center of the ship. create two orthogonal planes on that line, you're rotating in each plane towards the line. When the ship aligns with the line rotational velocity in the plane must be 0. As you know how fast you can decrease rotational speed, you can compute the angle in the plane at which point you have to reverse thrust to stop the rotation.

3 minutes ago, Alberth said:

You don't compute when to reverse steering? Draw a line between the target and the center of the ship. create two orthogonal planes on that line, you're rotating in each plane towards the line. When the ship aligns with the line rotational velocity in the plane must be 0. As you know how fast you can decrease rotational speed, you can compute the angle in the plane at which point you have to reverse thrust to stop the rotation.

I was going to explain why I don't agree (because of the way the planes already change when you adjust one thruster even before you have calculated the new rotation), but you are making me think now... let me think about this ?

Funny. I solved this yesterday.

 

First, you need a target rotation as quadernion. Then you can calculate the diff quaternion between your current rotation and target rotation. Finally you can decompose that diff into a axis+angle. Which you can use for pitch/yaw/roll

On my phone right now, can post some code later. Pm me if i forget.

39 minutes ago, Daid said:

Funny. I solved this yesterday.

 

First, you need a target rotation as quadernion. Then you can calculate the diff quaternion between your current rotation and target rotation. Finally you can decompose that diff into a axis+angle. Which you can use for pitch/yaw/roll

On my phone right now, can post some code later. Pm me if i forget.

Cool! Yes please, share your code! ?

This topic is closed to new replies.

Advertisement