local maf	= require 'maf'
local vec3	= maf.vector
local quat	= maf.rotation


-- Порог для поднятия тангажа, используется для корректировки тангажа
local pitchUpThreshold   = -15 -- значение в градусах, извлечено из MonoBehaviour с fileID: 3737572916587997159

-- Угол для тонкой корректировки рулевого управления,
-- определяет, когда следует выполнять корректировки рысканья или крена
local fineSteeringAngle  = 5   -- значение в градусах, извлечено из MonoBehaviour с fileID: 3737572916587997159

-- Фактор для корректировки рысканья, множитель для настройки управления по рысканию
local yawFactor          = 1   -- множитель, используется для масштабирования корректировки рысканья, извлечено из MonoBehaviour с fileID: 3737572916587997159

-- Фактор для корректировки крена, множитель для настройки управления по крену
local rollFactor         = 1 -- множитель, используется для масштабирования корректировки крена, извлечено из MonoBehaviour с fileID: 3737572916587997159

-- Скорость рулевого управления, определяет, насколько быстро следует двигаться к целевому вводу
local steeringSpeed      = 5.0 -- единиц в секунду, скорость перемещения к целевым значениям управления, извлечено из MonoBehaviour с fileID: 3737572916587997159

local dir = {
    forward		= vec3(0, 1, 0),	-- вперед
    backward	= vec3(0, -1, 0),	-- назад
    right		= vec3(1, 0, 0),	-- вправо
    left		= vec3(-1, 0, 0),	-- влево
    up			= vec3(0, 0, 1),	-- вверх
    down		= vec3(0, 0, -1)	-- вниз
}

function signedAngle(from, to, axis)
  -- Step 1: Normalize the both vectors
  local fromNormalized = from:clone():normalize()
  local toNormalized = to:clone():normalize()
  
  -- Step 2: Calculate the unsigned angle
  local dotProduct = fromNormalized:dot(toNormalized)
  local angle = math.acos(math.max(-1, math.min(1, dotProduct))) -- Clamp acos input

  -- Step 3: Determine the sign using the cross product and reference axis
  local crossProduct = fromNormalized:cross(toNormalized)
  local sign = crossProduct:dot(axis) < 0 and -1 or 1

  -- Step 4: Return the signed angle
  return angle * sign
end

function CalculateSteeringForPlane(plane ,--[[float]] dt, --[[Vector3]] targetPosition)
	print(targetPosition)
    local planePosition = vec3(getCarCoordinates(plane))
    local planeRotation = quat(getVehicleQuaternion(plane))

    -- Calculate the error (direct difference, verify if we need transformation)
    local error = targetPosition - planePosition

    -- Suppose unary minus acts as conjugation; use it
    local errorLocal = -planeRotation * error

    print("Error (world):", error)
    print("Error (local):", errorLocal)

    -- For stability, recheck that these normalized vectors are close to expected results
    local errorDir = errorLocal:normalize()
    local pitchError = vec3(0, errorLocal.z, errorLocal.y):normalize()
    local rollError = vec3(errorLocal.x, 0, errorLocal.y):normalize()
    local yawError = vec3(errorLocal.x, errorLocal.z, 0):normalize()

    print("PitchError:", pitchError)
    print("RollError:", rollError)
    print("YawError:", yawError)

    local targetInput = vec3()

    local pitch = signedAngle(dir.forward, pitchError, dir.right)
    if (-pitch < pitchUpThreshold) then
        pitch = pitch + 360
    end
    targetInput.x = pitch

    if (vec3.angle(dir.forward, errorDir) < fineSteeringAngle) then
        local yaw = signedAngle(dir.forward, yawError, dir.up)
        targetInput.y = yaw * yawFactor
    else
        local roll = signedAngle(dir.up, rollError, dir.forward)
        targetInput.z = roll * rollFactor
    end

    return targetInput
end


function main()
	while true do
		local plane = storeCarCharIsInNoSave(playerPed)

		-- Получаем позицию машины
		local planePosition = vec3(getCarCoordinates(plane))

		-- Получаем координаты камеры и точку, куда она смотрит
		local cameraPosition = vec3(getActiveCameraCoordinates())
		local cameraPointAt = vec3(getActiveCameraPointAt())

		-- Вычисляем направление камеры
		local cameraDirection = (cameraPointAt - cameraPosition):normalize()

		-- Строим целевой вектор используемый `planePosition` как начальную точку и `cameraDirection` для направления
		local goPos = planePosition + cameraDirection * 1000

		print(CalculateSteeringForPlane(plane, 10, goPos))
		wait(0)
	end
end

почему этот код работает неправильно?

0, 40.121957)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831116, -0.732388, -18.363093)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.792031, -999.830196, -18.342951)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018343, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097233, -0.995262, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589140, 3.044206, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792542, -2016.145840, 40.121957)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831116, -0.732388, -18.363093)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.792011, -999.830185, -18.342977)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018343, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097232, -0.995262, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589140, 3.044207, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792542, -2016.145840, 40.121957)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831116, -0.732388, -18.363093)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791988, -999.830173, -18.342989)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018343, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097230, -0.995262, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589140, 3.044208, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792612, -2016.145840, 40.125771)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831186, -0.732388, -18.359280)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791814, -999.830317, -18.339186)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018339, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097241, -0.995261, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589137, 3.044198, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792612, -2016.145840, 40.125771)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831186, -0.732388, -18.359280)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791891, -999.830229, -18.339187)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018339, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097245, -0.995260, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589137, 3.044194, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792612, -2016.145840, 40.125771)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831186, -0.732388, -18.359280)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791796, -999.830308, -18.339189)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018339, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097240, -0.995261, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589137, 3.044199, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792612, -2016.145840, 40.125771)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831186, -0.732388, -18.359280)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791879, -999.830224, -18.339173)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018339, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097245, -0.995261, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589137, 3.044194, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792612, -2016.145840, 40.125771)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831186, -0.732388, -18.359280)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791794, -999.830308, -18.339151)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018339, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097240, -0.995261, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589137, 3.044199, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792612, -2016.145840, 40.125771)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831186, -0.732388, -18.359280)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791898, -999.830235, -18.339107)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018339, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097246, -0.995260, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589136, 3.044193, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792612, -2016.145840, 40.125771)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831186, -0.732388, -18.359280)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791817, -999.830322, -18.339082)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018339, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097242, -0.995261, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589136, 3.044197, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792542, -2016.145840, 40.121957)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831116, -0.732388, -18.363093)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791982, -999.830173, -18.342862)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018343, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097231, -0.995262, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589140, 3.044208, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792542, -2016.145840, 40.121957)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831116, -0.732388, -18.363093)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791897, -999.830257, -18.342840)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018343, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097226, -0.995262, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589140, 3.044212, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792542, -2016.145840, 40.121957)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831116, -0.732388, -18.363093)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791982, -999.830174, -18.342802)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018343, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097231, -0.995262, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589140, 3.044208, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792542, -2016.145840, 40.121957)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831116, -0.732388, -18.363093)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.791990, -999.830179, -18.342766)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018343, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097232, -0.995262, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589140, 3.044207, 0.000000)
[ML] (script) (^^)tracers.lua: (2275.792542, -2016.145840, 40.121957)
[ML] (script) (^^)tracers.lua: Error (world):   (999.831116, -0.732388, -18.363093)
[ML] (script) (^^)tracers.lua: Error (local):   (-1.792087, -999.830270, -18.342735)
[ML] (script) (^^)tracers.lua: PitchError:   (0.000000, -0.018343, -0.999832)
[ML] (script) (^^)tracers.lua: RollError:   (-0.001792, 0.000000, -0.999998)
[ML] (script) (^^)tracers.lua: YawError:   (-0.097237, -0.995261, 0.000000)
[ML] (script) (^^)tracers.lua: (-1.589140, 3.044202, 0.000000)