KSP-KOS / KSLib

The standard library and examples for the Kerboscript language
MIT License
120 stars 40 forks source link

roll_for() returns incorrect values #89

Closed Gaiiden closed 9 years ago

Gaiiden commented 9 years ago

using this code pasted straight in from the lib:

@lazyglobal off.

function east_for {
  parameter ves.

  return vcrs(ves:up:vector, ves:north:vector).
}

function compass_for {
  parameter ves.

  local pointing is ves:facing:forevector.
  local east is east_for(ves).

  local trig_x is vdot(ves:north:vector, pointing).
  local trig_y is vdot(east, pointing).

  local result is arctan2(trig_y, trig_x).

  if result < 0 {
    return 360 + result.
  } else {
    return result.
  }
}

function pitch_for {
  parameter ves.

  return 90 - vang(ves:up:vector, ves:facing:forevector).
}

function roll_for {
  parameter ves.

  local raw is vang(ves:up:vector, ves:facing:starvector).
  if vang(ves:up:vector, ves:facing:topvector) > 90 {
    if raw > 90 {
      return 270 - raw.
    } else {
      return -90 - raw.
    }
  } else {
    return raw - 90.
  }
}.

clearscreen.

print "Testing lib_navball.".
print " ".
print " +--------------------+".
print " | Compass =          |".
print " +--------------------+".
print " ".
print " +--------------------+".
print " |   Pitch =          |".
print " +--------------------+".
print " ".
print " +--------------------+".
print " |    Roll =          |".
print " +--------------------+".
print " ".

// slight modification to quit method
brakes off.
until brakes {
  print round(compass_for(ship), 1) + "    " at (13,3).
  print round(pitch_for(ship), 1)   + "    " at (13,7).
  print round(roll_for(ship), 1)    + "    " at (13,11).
  wait 0.
}.

Here are the results:

good initially: fg1

gets thrown off quick though: fg2

discrepancy increases quickly: fg3

sudden jump at around -26deg to triple digits: fg4

gradually goes back to correct on the other side: fg5

Craft used was an AIES Nova core hooked onto IR rotatotron and hinge in order to roll and pitch. Solar panels and batteries for power

TDW89 commented 9 years ago

Ok looks like the roll_for() function is using the angle between the up vector and the vessel starboard vector without taking into account the pitch. For a quick fix replace the line

local raw is vang(ves:up:vector, ves:facing:starvector).

with

local raw is vang(vxcl(ship:facing:vector,ship:up:vector, ves:facing:starvector).

It will give slightly odd results when the facing and up vectors are aligned but i will try and find a way round that in the main code. If i can i may use the existing pitch_for() function to exclude some of the result, if not it will just be a small dead zone.

edit: to see the issue / change add the below code to the main loop:

  local old_vec is vecdrawargs(
   v(0,0,0),
   ship:up:vector,
   red,
   "before change",
   2,
   true
  ).
  local star_vec is vecdrawargs(
   v(0,0,0),
   ship:facing:starvector,
   blue,
   "ves star",
   2,
   true
  ).
  local new_vec is vecdrawargs(
   v(0,0,0),
   vxcl(ship:facing:vector,ship:up:vector):normalized,
   green,
   "after change",
   2,
   true
  ).
Dunbaratu commented 9 years ago

It will give slightly odd results when the facing and up vectors are aligned but i will try and find a way round that in the main code.

That's correct behavior. It's true gimbal lock. Imagine if you have an airplane going straight up. There is not enough information to know your heading and roll at the same time, because one alters the other. i.e. pitch 90, compass 90, roll 0 gives the identical orientation as pitch 90, compass 45, roll -45 or pitch 90, compass 0, roll -90, etc. It's all of the above at once: pure information loss.

Gaiiden commented 9 years ago

quick fix - thx TDW! Thanks also for the clarification Dunbaratu