--[[
; Example for a script-driven vessel class definition.
; For implementation code, see Orbitersdk/samples/ScriptVessel
; This file contains both the configuration and script parts.
; The config part is terminated by 'END_PARSE' to prevent the
; Orbiter parser from reading the script, and enclosed in Lua
; comment brackets to make it a comment for the script interpreter.

; A. Configuration section
; -------------------------------------------
ClassName = ScriptPB
Module = ScriptVessel
Script = ScriptPB.cfg
END_PARSE




; B. Script section
; -------------------------------------------
--]]

-- Vessel parameters

vprm = {                         -- general Parameters
  emass = 500,                     -- empty mass [kg]
  fuelmass = 750,                  -- propellant mass [kg]
  size = 3.5,                      -- mean radius [m]
  pmi = {x=2.28,y=2.31,z=0.79},    -- principal moments of inertia [m^2]
  cs = {x=10.5,y=15.0,z=5.8},      -- cross sections [m^2]
  rd = {x=0.1,y=0.1,z=0.05},       -- rotation drag coefficients
  co = {x=0,y=0.8,z=0},            -- cockpit camera offset
  td1 = {x=0,y=-1.5,z=2},          -- touchdown point: front
  td2 = {x=-1,y=-1.5,z=-1.5},      -- touchdown point: left
  td3 = {x=1,y=-1.5,z=-1.5}        -- touchdown point: right
}

afv = {                          -- parameters for vertical airfoil
  cl = {-0.1,-0.5,-0.4,-0.1,0,0,0,0,0,0,0,0,0,0,-0.2,-0.6,-0.6,-0.4,0.2,0.5,0.9,0.8,0.2,0,0,0,0,0,0,0,0,0,0.1,0.4,0.5,0.3,-0.1,-0.5},
  aoa_step = 10*RAD,                      -- step size for lift coeff samples
  dp = 0.03,                              -- profile drag parameters
  di = {A=2.5,e=0.5},                     -- induced drag parameters
  dw = {M1=0.75,M2=1.0,M3=1.1,cmax=0.04}  -- wave drag parameters
}

afh = {                          -- parameters for horizontal airfoil
  cl = {0,0.4,0,-0.4,0,0.4,0,-0.4,0,0.4}, -- lift coeffs in 45deg steps from -pi
  aoa_step = 45*RAD,                      -- step size for lift coeff samples
  dp = 0.03,                              -- profile drag parameters
  di = {A=1.5,e=0.6},                     -- induced drag parameters
  dw = {M1=0.75,M2=1.0,M3=1.1,cmax=0.04}  -- wave drag parameters
}

thmain_prm = {                   -- main thruster parameters
  pos = {x=0,y=0,z=-4.35},         -- thrust attack point [m]
  dir = {x=0,y=0,z=1},             -- thrust direction
  maxth0 = 2e4,                    -- max. vacuum thrust [N]
  isp0 = 5e4                       -- vacuum ISP value [m/s]
}
thhovr_prm = {                   -- hover thruster parameters
  pos = {x=0,y=-1.5,z=0},          -- thrust attack point [m]
  dir = {x=0,y=1,z=0},             -- thrust direction
  maxth0 = 1.5e4,                  -- max. vacuum thrust [N]
  isp0 = 5e4                       -- vacuum ISP value [m/s]
}
thrcs_prm = {                    -- RCS thruster parameters
  maxth0 = 2e2,                    -- max. vaccum thrust [N]
  isp0 = 5e4                       -- vacuum ISP value [m/s]
}

dprm = {                         -- docking port parameters
  pos = {x=0,y=1.3,z=-1},          -- position
  dir = {x=0,y=1,z=0},             -- approach direction
  rot = {x=0,y=0,z=-1}             -- longitudinal alignment
}

trans_Laileron = {               -- transformation for left aileron animation
  type = 'rotation',                -- transformation type
  mesh = 0,                         -- mesh index
  grp = 2,                          -- group indices
  ref = {x=-1.3,y=-0.725,z=-1.5},   -- reference point
  axis = {x=-0.9619,y=-0.2735,z=0}, -- rotation axis
  angle = 20*RAD                    -- rotation angle
}
trans_Raileron = {               -- transformation for right aileron animation
  type = 'rotation',                -- transformation type
  mesh = 0,                         -- mesh index
  grp = 3,                          -- group indices
  ref = {x=1.3,y=-0.725,z=-1.5},    -- reference point
  axis = {x=0.9619,y=-0.2735,z=0},  -- rotation axis
  angle = 20*RAD                    -- rotation angle
}
trans_Lelevator = {              -- transformation for left elevator animation
  type = 'rotation',                -- transformation type
  mesh = 0,                         -- mesh index
  grp = 2,                          -- group indices
  ref = {x=-1.3,y=-0.725,z=-1.5},   -- reference point
  axis = {x=-0.9619,y=-0.2735,z=0}, -- rotation axis
  angle = -30*RAD                   -- rotation angle
}
trans_Relevator = {              -- transformation for right elevator animation
  type = 'rotation',                -- transformation type
  mesh = 0,                         -- mesh index
  grp = 3,                          -- group indices
  ref = {x=1.3,y=-0.725,z=-1.5},    -- reference point
  axis = {x=0.9619,y=-0.2735,z=0},  -- rotation axis
  angle =  30*RAD                   -- rotation angle
}

-- SetClassCaps implementation

function clbk_setclasscaps(cfg)

  -- physical vessel parameters
  vi:set_size(vprm.size)
  vi:set_emptymass(vprm.emass)
  vi:set_pmi(vprm.pmi)
  vi:set_crosssections(vprm.cs)
  vi:set_rotdrag(vprm.rd)
  vi:set_touchdownpoints(vprm.td1,vprm.td2,vprm.td3)
  
  -- docking port definitions
  hDock = vi:set_dockparams(dprm.pos,dprm.dir,dprm.rot)
  
  -- airfoil definitions
  vi:create_airfoil(LIFT.VERTICAL,{x=0,y=0,z=-0.1},'vlift',2,2,2.5)
  vi:create_airfoil(LIFT.HORIZONTAL,{x=0,y=0,z=-0.1},'hlift',2,1.5,2)
  
  -- control surface animations
  animcomp_Laileron = oapi.create_animationcomponent(trans_Laileron)
  animcomp_Raileron = oapi.create_animationcomponent(trans_Raileron)
  animcomp_Lelevator = oapi.create_animationcomponent(trans_Lelevator)
  animcomp_Relevator = oapi.create_animationcomponent(trans_Relevator)
  anim_Laileron = vi:create_animation(0.5)
  anim_Raileron = vi:create_animation(0.5)
  anim_elevator = vi:create_animation(0.5)
  vi:add_animationcomponent(anim_Laileron,0,1,animcomp_Laileron)
  vi:add_animationcomponent(anim_Raileron,0,1,animcomp_Raileron)
  vi:add_animationcomponent(anim_elevator,0,1,animcomp_Lelevator)
  vi:add_animationcomponent(anim_elevator,0,1,animcomp_Relevator)
  
  -- aerodynamic control surface definitions
  vi:create_controlsurface(AIRCTRL.ELEVATOR, 1.5, 0.5, {x=0,y=0,z=-2.5}, AIRCTRL_AXIS.XPOS, 1.0, anim_elevator);
  vi:create_controlsurface(AIRCTRL.AILERON, 1.5, 0.25, {x=1,y=0,z=-2.5}, AIRCTRL_AXIS.XPOS, 1.0, anim_Laileron);
  vi:create_controlsurface(AIRCTRL.AILERON, 1.5, 0.25, {x=-1,y=0,z=-2.5}, AIRCTRL_AXIS.XNEG, 1.0, anim_Raileron);
  
  -- propellant resources
  hProp = vi:create_propellantresource(vprm.fuelmass)
  
  -- main engine
  thmain_prm.hprop = hProp
  thmain = vi:create_thruster(thmain_prm)
  thgmain = vi:create_thrustergroup({thmain},THGROUP.MAIN)
  
  -- hover engine
  thhovr_prm.hprop = hProp
  thhovr = vi:create_thruster(thhovr_prm)
  thghovr = vi:create_thrustergroup({thhovr},THGROUP.HOVER)
  
  -- RCS engines
  th = thrcs_prm.maxth0
  isp = thrcs_prm.isp0
  thrcs0  = vi:create_thruster({pos={x=1,y=0,z=3},dir={x=0,y=1,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs1  = vi:create_thruster({pos={x=1,y=0,z=3},dir={x=0,y=-1,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs2  = vi:create_thruster({pos={x=-1,y=0,z=3},dir={x=0,y=1,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs3  = vi:create_thruster({pos={x=-1,y=0,z=3},dir={x=0,y=-1,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs4  = vi:create_thruster({pos={x=1,y=0,z=-3},dir={x=0,y=1,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs5  = vi:create_thruster({pos={x=1,y=0,z=-3},dir={x=0,y=-1,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs6  = vi:create_thruster({pos={x=-1,y=0,z=-3},dir={x=0,y=1,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs7  = vi:create_thruster({pos={x=-1,y=0,z=-3},dir={x=0,y=-1,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs8  = vi:create_thruster({pos={x=1,y=0,z=3},dir={x=-1,y=0,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs9  = vi:create_thruster({pos={x=-1,y=0,z=3},dir={x=1,y=0,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs10 = vi:create_thruster({pos={x=1,y=0,z=-3},dir={x=-1,y=0,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs11 = vi:create_thruster({pos={x=-1,y=0,z=-3},dir={x=1,y=0,z=0},maxth0=th,isp0=isp,hprop=hProp})
  thrcs12 = vi:create_thruster({pos={x=0,y=0,z=-3},dir={x=0,y=0,z=1},maxth0=th,isp0=isp,hprop=hProp})
  thrcs13 = vi:create_thruster({pos={x=0,y=0,z=3},dir={x=0,y=0,z=-1},maxth0=th,isp0=isp,hprop=hProp})
  vi:create_thrustergroup({thrcs0,thrcs2,thrcs5,thrcs7},THGROUP.ATT_PITCHUP)
  vi:create_thrustergroup({thrcs1,thrcs3,thrcs4,thrcs6},THGROUP.ATT_PITCHDOWN)
  vi:create_thrustergroup({thrcs0,thrcs4,thrcs3,thrcs7},THGROUP.ATT_BANKLEFT)
  vi:create_thrustergroup({thrcs1,thrcs5,thrcs2,thrcs6},THGROUP.ATT_BANKRIGHT)
  vi:create_thrustergroup({thrcs0,thrcs4,thrcs2,thrcs6},THGROUP.ATT_UP)
  vi:create_thrustergroup({thrcs1,thrcs5,thrcs3,thrcs7},THGROUP.ATT_DOWN)
  vi:create_thrustergroup({thrcs8,thrcs11},THGROUP.ATT_YAWLEFT)
  vi:create_thrustergroup({thrcs9,thrcs10},THGROUP.ATT_YAWRIGHT)
  vi:create_thrustergroup({thrcs8,thrcs10},THGROUP.ATT_LEFT)
  vi:create_thrustergroup({thrcs9,thrcs11},THGROUP.ATT_RIGHT)
  vi:create_thrustergroup({thrcs12},THGROUP.ATT_FORWARD)
  vi:create_thrustergroup({thrcs13},THGROUP.ATT_BACK)

  -- engine exhaust definitions
  vi:add_exhaust(thmain,8,1,{x=0,y=0.3,z=-4.35},{x=0,y=0,z=-1})
  vi:add_exhaust(thhovr,8,1,{x=0,y=-1.5,z=1},{x=0,y=-1,z=0})
  vi:add_exhaust(thhovr,8,1,{x=0,y=-1.5,z=-1},{x=0,y=-1,z=0})
  
  -- exhaust particle stream definitions
  contrail_main = {
    srcsize = 5.0,
    srcrate = 16,
    v0 = 200,
    srcspread = 0.15,
    lifetime = 1.0,
    growthrate = 5,
    atmslowdown = 3.0,
    ltype = PARTICLE.DIFFUSE,
    levelmap = PARTICLE.LVL_PSQRT,
    lmin = 0,
    lmax = 2,
    atmsmap = PARTICLE.ATM_PLOG,
    amin = 1e-4,
    amax = 1
  }
  exhaust_main = {
    srcsize = 2.0,
    srcrate = 20,
    v0 = 200,
    srcspread = 0.05,
    lifetime = 0.1,
    growthrate = 8,
    atmslowdown = 1.0,
    ltype = PARTICLE.EMISSIVE,
    levelmap = PARTICLE.LVL_SQRT,
    atmsmap = PARTICLE.ATM_PLOG,
    amin = 1e-5,
    amax = 0.1
  }
  vi:add_exhauststream(thmain,{x=0,y=0.3,z=-10},contrail_main)  
  vi:add_exhauststream(thmain,{x=0,y=0.3,z=-5},exhaust_main)
  
  contrail_hovr = {
    srcsize = 5.0,
    srcrate = 8,
    v0 = 200,
    srcspread = 0.15,
    lifetime = 1.0,
    growthrate = 5,
    atmslowdown = 3.0,
    ltype = PARTICLE.DIFFUSE,
    levelmap = PARTICLE.LVL_PSQRT,
    lmin = 0,
    lmax = 2,
    atmsmap = PARTICLE.ATM_PLOG,
    amin = 1e-4,
    amax = 1
  }
  exhaust_hovr = {
    srcsize = 2.0,
    srcrate = 10,
    v0 = 200,
    srcspread = 0.05,
    lifetime = 0.05,
    growthrate = 8,
    atmslowdown = 1.0,
    ltype = PARTICLE.EMISSIVE,
    levelmap = PARTICLE.LVL_SQRT,
    atmsmap = PARTICLE.ATM_PLOG,
    amin = 1e-5,
    amax = 0.1
  }
  vi:add_exhauststream(thhovr,{x=0,y=-3,z=1},contrail_hovr)
  vi:add_exhauststream(thhovr,{x=0,y=-3,z=-1},contrail_hovr)
  vi:add_exhauststream(thhovr,{x=0,y=-2,z=1},exhaust_hovr)
  vi:add_exhauststream(thhovr,{x=0,y=-2,z=-1},exhaust_hovr)

  -- camera parameters
  vi:set_cameraoffset(vprm.co)
  
  -- associate a mesh for the visual
  vi:add_mesh('ShuttlePB')
end


-- vertical airfoil definition

function vlift(hVessel,aoa,M,Re)
  idx = math.floor((aoa+PI)/afv.aoa_step)
  a = (aoa+PI-idx*afv.aoa_step)/afv.aoa_step
  cl = afv.cl[idx+1]*(1-a) + afv.cl[idx+2]*a  -- lift coefficient (linear interpolation)
  -- cl = cl*0.5
  cm = -0.03*math.sin(aoa-0.1)         -- moment coefficient
  saoa = math.sin(aoa)
  cdp = afv.dp + 0.4*saoa*saoa             -- profile drag
  cdi = oapi.get_induceddrag(cl,afv.di.A,afv.di.e)   -- induced drag
  cdw = oapi.get_wavedrag(M,afv.dw.M1,afv.dw.M2,afv.dw.M3,afv.dw.cmax)
                                         -- wave drag
  cd = cdp + cdi + cdw                   -- drag coefficient
  return cl,cm,cd
end


-- horizontal airfoil definition

function hlift(hVessel,aoa,M,Re)
  idx = math.floor((aoa+PI)/afh.aoa_step)
  a = (aoa+PI-idx*afh.aoa_step)/afh.aoa_step
  cl = afh.cl[idx+1]*(1-a) + afh.cl[idx+2]*a
  cdp = afh.dp
  cdi = oapi.get_induceddrag(cl,afh.di.A,afh.di.e)
  cdw = oapi.get_wavedrag(M,afh.dw.M1,afh.dw.M2,afh.dw.M3,afh.dw.cmax)
  cd = cdp + cdi + cdw;
  return cl,0,cd
end
