I have a problem converting Heading, Pitch and Roll to an Orientation Matrix
How would I go about improving this to ensure Y and Z and are correctly calculated.
--[[
get_orientation - Returns the orientation matrix of an object based on its heading, pitch, and roll in degrees.
@param heading number - The heading of the object in degrees.
@param pitch number - The pitch of the object in degrees.
@param roll number - The roll of the object in degrees.
@returns orientation table - The orientation matrix of the object, represented as a table with three unit vectors: x, y, and z.
]]
local function get_orientation(heading, pitch, roll)
local orientation = {}
-- Convert the heading, pitch, and roll from degrees to radians using math.rad
heading = math.rad(heading)
pitch = math.rad(pitch)
roll = math.rad(roll)
-- Calculate the x unit vector
-- x is the Vec3 unit vector that points in the direction of the object's front
orientation.x = {}
orientation.x.x = math.cos(heading) * math.cos(pitch)
orientation.x.y = math.sin(pitch)
orientation.x.z = math.sin(heading) * math.cos(pitch)
-- Calculate the y unit vector
-- y is the Vec3 unit vector that points in the direction of the object's top
orientation.y = {}
orientation.y.x = -math.cos(heading) * math.sin(pitch)
orientation.y.y = math.cos(pitch)
orientation.y.z = -math.sin(heading) * math.sin(pitch)
-- Calculate the z unit vector
-- z is the Vec3 unit vector that points in the direction of the object's right side
orientation.z = {}
orientation.z.x = -math.sin(heading)
orientation.z.z = -math.cos(heading) * math.cos(roll)
orientation.z.y = math.sin(roll)
-- Return the orientation matrix of the object
return orientation
end
---------------------------------------------------
---------------------------------------------------
local lat = 41.610278
local lon = 41.599444
local heading = 90
local pitch = 25
local roll = 0
local alt = 100
local x, y = terrain.convertLatLonToMeters(lat, lon)
local orientation = get_orientation(heading, pitch, roll)
local position = {
x=orientation.x,
y=orientation.y,
z=orientation.z,
p={x=x,y=alt,z=y}
}
Export.LoSetCameraPosition(position)
local actual = Export.LoGetCameraPosition()
return {position=position, actual=actual}
There is a little more information about the Orientation here https://www.digitalcombatsimulator.com/en/support/faq/1256/#:~:text=level 10 m-,Orientation,-Object orientation is
I am attempting to build a function that takes lat, lon, alt, heading, pitch and roll and produce the Position matrix.
I have the example function so far, which does work but everything goes funky after -81 pitch and the roll does not work as intended.
CodePudding user response:
Formulas for 3D rotation are not simple, but they can be simply deduced from three consecutive 2D rotations.
local function apply_rotation(a, b, angle)
local ax, ay, az, bx, by, bz = a.x, a.y, a.z, b.x, b.y, b.z
a.x = math.cos(angle) * ax math.sin(angle) * bx
a.y = math.cos(angle) * ay math.sin(angle) * by
a.z = math.cos(angle) * az math.sin(angle) * bz
b.x = math.cos(angle) * bx - math.sin(angle) * ax
b.y = math.cos(angle) * by - math.sin(angle) * ay
b.z = math.cos(angle) * bz - math.sin(angle) * az
end
local function get_orientation(heading, pitch, roll)
-- Convert the heading, pitch, and roll from degrees to radians using math.rad
heading = math.rad(heading)
pitch = math.rad(pitch)
roll = math.rad(roll)
-- x is the Vec3 unit vector that points in the direction of the object's front
-- y is the Vec3 unit vector that points in the direction of the object's top
-- z is the Vec3 unit vector that points in the direction of the object's right side
local o = {
x = { x=1, y=0, z=0 },
y = { x=0, y=1, z=0 },
z = { x=0, y=0, z=1 },
}
apply_rotation(o.x, o.z, heading)
apply_rotation(o.x, o.y, pitch)
apply_rotation(o.z, o.y, roll)
-- Return the orientation matrix of the object
return o
end