Nivekk / KOS

Fully programmable autopilot mod for KSP.
Other
80 stars 30 forks source link

future feature: RCS translation controls? #46

Open Dunbaratu opened 10 years ago

Dunbaratu commented 10 years ago

It would be nice if there was a way to access what the IJKLHN keys normally do in flight. (sideways movement.) Docking is nearly impossible without it. It doesn't even have to be too fancy- just mimic what the controls do, which I think is boolean thrusting so it's simpler than the THROTTLE interface (no need to set a number between 0.0 and 1.0 just a boolean toggle for the 6 directions:

Any one of these would be fine: suggestion 1 - direct control of the 6 thrust directions:

rcsleft on. // or off.
rcsright on.  // or off.
rcstup on.  // or off.
rcsdown on.  // or off.
rcsahead on.  // or off.
rcsback on.  // or off.

suggestion 2 - Same thing but use positive and negative numbers so there's only 3 thrust settings not 6:

lock rcsside to 1. // pushing  to ship's relative right
lock rcsside to 0. // drift.
lock rcsside to -1. // pushing to ship's relative left.

lock rcsvertical to 1. // pushing to ship's relative up.
lock rcsvertical to 0. // drift.
lock rcsvertical to -1. // pushing to ship's relative down.

lock rcsahead to 1. // pushing to ship's relative front.
lock rcsahead to 0. // drift.
lock rcsahead to -1. // pushing to ship's relative rear.

suggestion 3 - thrust in a direction, let kOS work the combination of the 6 thrust directions to do it:

lock rcsDirection to ( up + R(45,0,0) ). // push diagonally.
rcsThrust on.
rcsThrust off.

I actually prefer 1 or 2 over 3. Sort of the whole reason I'm using kOS instead of mechjeb is that I want to write my own piloting routines instead of having someone else do it for me.

Nivekk commented 10 years ago

I'll have to think about this one, one of the reasons I didn't just let users write their own steering algorithm is because it would be so difficult (it's hard enough in c#!) the vast majority of people would give up.

Writing a program that aligns your docking port with a target, while controlling only 1 of 6 axes per line, without overshooting would be quite the tall order

Dunbaratu commented 10 years ago

Well, don't make it TOO easy. KOS fills a role partway between manual filght and mechjeb flight. If KOS starts becoming too easy it will feel like just telling mechjeb to fly the ship for you while you watch. The difference between what KOS provides and what mechjeb provides is that I didn't have to do anything to make mechjeb work. It was already working fully out of the box without any help from me, and that's why I don't care for using it.

baloan commented 10 years ago

+1. I prefer option 3. Option 1 has a problem with turning on multiple directions.

rcsleft on. 
rcsright on.
// what now?

A slightly simpler and IMHO more intuitive approach for option 3:

lock rcs to facing. // burn forward
unlock rcs.           //  stop, control back to keyboard
lock rcs to -facing. // burn backward
lock rcs to facing + R(90,0,0). // burn sideways
unlock rcs.           //  stop, control back to keyboard
bshepherdson commented 10 years ago

I'm not thrilled with any of these APIs. I propose just letting the user set a vector whose components range over -1..1, with intuitive interpretations of the axes. +x is to the right (when looking from behind your ship towards the target), -x is left, +y is up, -y is down, +z is forward and -z is backward.

lock rcs to (0,0,1).

Then you can get your speed relative to your target, and check its components, and control your linear RCS accordingly. It's worth noting that this is far from making things too easy, since you're controlling acceleration here and not speed. It'll be easy to overshoot, especially if you have to choose {-1,0,1} and not real numbers in the interval [-1,1]. (I don't know if KSP allows for fractional RCS thrust, or if it's all-or-nothing.)

Dunbaratu commented 10 years ago

You say you don't like any of the proposed APIs, but what you suggested is in fact almost identical to my original option 2.

rcsside, rcsvertical, and rcsahead are the three axes you refer to in your vector method.

The only difference is that I talked about them being boolean because I THINK that's how the actual game is. I don't think the game lets you push "halfway down" on the "L" key for example, to thrust 0.5 in the rightward direction.

I don't mind your method - I'm just not sure its a thing the controls support. The main throttle lets you adjust the thrust up and down with SHIFT and CONTROL. so it makes sense for KOS to let you express that as a floating point coefficient ranging continuously over the range from 0 to 1. But RCS translations aren't like that in the user interface Either you're pressing the key or you're not, and if you want to go gently, you have to do it by tapping the thruster on and off.

At any rate, I'm not sure I like the idea of expressing it as a vector that uses different frame of reference axes than the other vectors in the game. When you obtain your velocity:orbit as a vector, for example, that's in the XYZ grid of the main game, which is not aligned with your ship facing.

So if you make it a vector, it's a vector people can't really combine with the other vectors in the game if you express it relative to your ship facing, and THAT will be confusing. This for example, wouldn't work:

To show you why I fear doing it that way, how would you interpret this statement in the way you're proposing:

lock rcstrans to velocity:orbit + V(40,20,0).

Is that a V() in the same coordinate frame of reference as velocity:orbit, or in the same frame of reference as the ship facing?

If you use the native rotation system everything else uses, you can derive a facing-based system like this:

lock transdir to facing * V(0,0,1). lock trans on. // start thrusting that way

(I've found that this works well in general in other places too so it would be consistent with the rest of the langauge that way. Multiplying a vector by a rotation seems to have the effect of behaving as if that vector was expressed in a different frame of reference- one in which it was aligned with that rotation. I use this method in my lander script, where I prefer to think in terms of east,north, and up, and I can steer that way by doing this:

lock steering to up * V(0 - eastward, northward, upward ).

(The reason for "0 - eastward" is just that I'm thinking in a right-handed coordinate system and the game is thinking in a left handed one so I had to fliip one of the axes.).

bshepherdson commented 10 years ago

I'm perfectly content with lock rcsTrans to facing * V(0,0,1). The main point I'm pushing for is having everything be set in one line, not 3 or 6, using a familiar vector syntax. I'm not attached to using any particular frame of reference; I just looked at it in isolation and thought "How would I want to control my linear RCS?" I agree that consistency with elsewhere in the code is important, and multiplying facing by a vector or rotation works well.

fibonatic commented 10 years ago

I also would prefer the ability to thrust RCS in a direction determined by a vector. However I do not know for sure what would be a good way to control the "throttle". There is no real UI RCS-throttle in KSP, but you can have variable RCS thrust, for example when using fine controls or when the SAS tries to keep a certain heading. You could use the magnitude of the vector as the throttle, since otherwise you would have to input both a vector and a throttle value when controlling RCS.

baloan commented 10 years ago

+1 to shepheb's proposal. Like it better than mine. It more intuitively represents what you can do with the keys.

lock rcs to (0,0,1).    // start burn
lock rcs to (0,0,5).    // start burn as well, anything > 0 is thrust on
unlock rcs.               // stop burn

The only argument is about which axis is forward. Funnily KSP defines y as perpendicular to the symmetry axis. To be consistent we should have (not sure about x and z):

x  -1: left, +1: right 
z  +1: up, -1: down
y  +1: forward, -1: aft
Dunbaratu commented 10 years ago

I prefer this sort of API:

lock rcsTransDir to facing*V(horizontal,forward,vertical). // sets direction but does not thrust.
trans on.  // start thrusting that way.
trans off.  // stop thrusting that way 
          // (but of course you still drift.  You need to thrust the
          // opposite way to stop.
          // Please don't auto-stop motion as that makes it too easy)..

// Or if it's possible to RCS thrust in lesser amounts (I don't know if it is), then
// instead of trans on and trans off you could:
lock trans to 0.5.
// instead.

The reason I prefer this is that I think it dovetails best with how the rest of how the KOS mod works. It gets the best of shepheb's suggestion without having to break the XYZ system of KSP to do it, since it would mean rcsTransDir is being expressed in the same way as steering and all the other directions are and it's only the multiplication by FACING that's making it behave like it was lined up with the ship. If it hadn't been multiplied by FACING then it would be in the native XYZ direction like all other vectors. In this proposed API, the actual code behind the scenes that's running the RCS thrusters would not actually care that the Direction you gave it is lined up with FACING. It wouldn't be seeing that vector, but rather it would be seeing a direction that results from FACING * V(a,b,c). You could just as easily lock rcsTransDir to UP. for example and the code would accept that just as happily if this is how the API worked. All it cares is that you gave it a direction of SOME sort.. The fact that using FACING times a vector happens to be the sanest way for the user to specify it is a thing the code itself would treat as irrelevant.

While I agree that the extra step of picking a direction first and THEN turning thrust on and off is a bit more clunky than doing the two together, the reason I"m suggesting it this way is because of how an expression of DIrection * Vector ends up evaluating in KOS.

When you multiply a Direction by a Vector, the result is NOT a vector. I's a Direction.

Up * V(west,north,up) For example returns a direction that has "forgotten" what the magnitude of the vector was. Therefore Up + V( 100,100,100) results in the same exact thing as Up + V(500,500,500). The vectors were the same direction, so the resulting Direction is the same. The magnitude gets forgotten.

And it's because the magnitude gets forgotten that this proposal needs that extra step of picking direction and then magnitude separately.

While this may seem clunky, remember, the advantage is that the work is being already done for us by the code that's already there. The abiliy to get a Direction out of FACING*V(a,b,c)``` is already how it works now.