Skip to content

Commit

Permalink
added ray tracing utils
Browse files Browse the repository at this point in the history
  • Loading branch information
FraCpl committed Jun 11, 2024
1 parent ad3b04e commit a005716
Show file tree
Hide file tree
Showing 3 changed files with 229 additions and 0 deletions.
48 changes: 48 additions & 0 deletions examples/testRt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using LinearAlgebra
using JTools
using Quaternions
using SpacecraftBuilder
using GLMakie

function mainSc()

cb = SpacecraftElement(
ID="CB",
mass=6900.0,
posEG_E=[25/1000, 3/1000, 1556/1000],
geometry=Cuboid(2.5, 2.5, 1556*2/1000),
inertiaG_E=[4285.0 -77 -311; -77 5070.0 102; -311 102 1795.0]
)

# Solar arrays
θ = 90π/180
mass = 212.0
geom = Cuboid(6.648, 14.64, 0.015)
inertiaG_E = [4730 -4.33 -0.026; -4.33 728 28; -0.026 28 5460]
posEG_E = [0.0; 9.95; 0.02]

sa1 = SpacecraftElement(
ID="SA (+Y)",
mass=mass,
geometry=geom,
inertiaG_E=inertiaG_E,
posEG_E=posEG_E,
posOE_O=[0.0; 1.25; 1],
R_OE=dcm_fromAxisAngle(2, θ),
)

sa2 = SpacecraftElement(
ID="SA (-Y)",
mass=mass,
geometry=geom,
inertiaG_E=inertiaG_E,
posEG_E=posEG_E,
posOE_O=[0.0; -1.25; 1],
R_OE=dcm_fromAxisAngle(3, π)*dcm_fromAxisAngle(2, -θ),
)

sc, model = build([cb; sa1; sa2]; plotModel=true)

return rayTracingSrp(model, [-1.0; 0.0; 0.0]; Nrays=100_000)
end
mainSc()
3 changes: 3 additions & 0 deletions src/SpacecraftBuilder.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ include("scElements.jl")
export build, getLTI, getMDK
include("scBuild.jl")

export rayTracingDrag, rayTracingSrp, rayTracingSurface
include("rayTracingUtils.jl")

end
178 changes: 178 additions & 0 deletions src/rayTracingUtils.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
mutable struct Ray
origin::Vector
dir::Vector
t::Real
idxFace::Int
end

Ray(origin, dir) = Ray(origin, normalize(dir), Inf, 0)

const EPS_PARALLEL = 1e-8
const ZERO_WITH_TOL = -1e-8
const ONE_WITH_TOL = 1.0 + 1e-8
const EPS_MIN_DIST = 1e-4
const RAY_SHIFT = 1e-2
const DEFAULT_NRAYS = 1_000_000

@views function intersect!(ray::Ray, tri, idx::Int)
E12 = tri[2] - tri[1]
E13 = tri[3] - tri[1]
P = ray.dir × E13
detM = dot(P, E12)

if abs(detM) EPS_PARALLEL; return; end

T = ray.origin - tri[1]
u = dot(P, T)/detM
if u < ZERO_WITH_TOL || u > ONE_WITH_TOL; return; end

Q = T × E12
v = dot(Q, ray.dir)/detM
if v < ZERO_WITH_TOL || u + v > ONE_WITH_TOL; return; end

t = dot(E13, Q)/detM
if t > EPS_MIN_DIST && t < ray.t
ray.t = t
ray.idxFace = idx
end
end

@views function intersect!(ray::Ray, bboxMin, bboxMax)
t1 = (bboxMin - ray.origin)./ray.dir
t2 = (bboxMax - ray.origin)./ray.dir
tmin = min(t1[1], t2[1])
tmax = max(t1[1], t2[1])

tmin = max(tmin, min(t1[2], t2[2]))
tmax = min(tmax, max(t1[2], t2[2]))

tmin = max(0.0, max(tmin, min(t1[3], t2[3])))
tmax = min(tmax, max(t1[3], t2[3]))
return tmax tmin
end

# Qdyn = 1/2ρV^2
function rayTracingDrag(model::GeometryBasics.Mesh, dirVel::Vector{Float64}, Qdyn=1.0, Cx=1.0; Nrays::Int=DEFAULT_NRAYS)
S, posCoP = rayTracingSrp(model, dirVel; Nrays=Nrays, Nrec=1, mode=:drag)
forceDrag = -Qdyn*Cx*S*normalize(dirVel)
torqueDrag = posCoP × forceDrag
return forceDrag, torqueDrag
end

function rayTracingSurface(model::GeometryBasics.Mesh, dirObs::Vector{Float64}; Nrays::Int=DEFAULT_NRAYS)
return rayTracingSrp(model, dirObs; Nrays=Nrays, Nrec=1, mode=:surf)[1]
end

function rayTracingSrp(model::GeometryBasics.Mesh, dirSun::Vector{Float64}, Psrp=1.0; Nrays::Int=DEFAULT_NRAYS, Nrec=3, mode=:srp)

anyIntersection = mode != :srp
α = 0.7; rd = 0.1; rs = 0.2

# Model box
bboxMin = [minimum(getindex.(model.position, i)) for i in 1:3]
bboxMax = [maximum(getindex.(model.position, i)) for i in 1:3]
X0 = (bboxMin + bboxMax)/2
R = maximum(bboxMax - X0)

# Creates rays matrix
coords = 1.1*R*range(-1, 1, round(Int, Nrays))
dirRay = -normalize(dirSun)
R_IS = genOrthogonalAxes(dirSun)
Ap = (coords[2] - coords[1])^2

rays = Ray[]
for x in coords, y in coords
push!(rays, Ray(X0 + R_IS*[x; y; 3R], dirRay))
end

# Intersect model
surf = 0.0; posCoP = zeros(3)
forceSrp = zeros(3); torqueSrp = zeros(3)
for ray in rays
# Check if the ray intersects the object's bounding box
if intersect!(ray, bboxMin, bboxMax)
psrp = Psrp
# Initialize ray recursion
for n in 1:Nrec
# Intersect ray with entire model (closest intersection)
for k in eachindex(model)
intersect!(ray, model[k], k)
if anyIntersection && ray.t < Inf; break; end
end

# Check if any intersection has been found
if ray.t == Inf
break
elseif mode == :srp
# Compute SRP
N, cosθ, newDir = rayReflection(model[ray.idxFace], ray)
frc, trq, psrp, posHit = srpFormula(ray, psrp, Ap, N, α, rd, rs, cosθ)
forceSrp += frc
torqueSrp += trq

# Update ray for next reflection
if n < Nrec
ray.t = Inf
ray.dir = newDir
ray.origin = posHit + RAY_SHIFT*newDir
end
else
# Compute surface and center of pressure
surf += Ap
posCoP .+= ray.origin*Ap
end
end
end
end

# Output
if mode == :srp
return forceSrp, torqueSrp
else
return surf, posCoP./surf
end
end

function rayReflection(face, ray)
E1 = face[2] - face[1]
E2 = face[3] - face[2]
N = normalize(E1 × E2)
cosθ = -N'*ray.dir

# Fix normal direction of current face on the basis of ray
# intersection result (the dot product between minus ray direction
# and face normal must be positive)
if cosθ < 0.0
N = -N
cosθ = -cosθ
end

return N, cosθ, ray.dir + 2cosθ*N
end

function srpFormula(ray, Psrp, Ap, N, α, rd, rs, cosθ)

# Compute forces generated by each single ray intersecting the object
forceSrp = -Psrp*Ap*(-+ rd)*ray.dir + 2(rs*cosθ + rd/3)*N)

# Compute total torque wrt the origin of the model
# (i.e., origin of the coordinates of the vertex of the model)
posHit = ray.origin + ray.t*ray.dir
torqueSrp = posHit × forceSrp

# Update SRP flux for next batch of reflected rays
return forceSrp, torqueSrp, Psrp*rs, posHit
end

function genOrthogonalAxes(zB_A)
nu = norm(zB_A)
if nu > 0.0
zB_A = zB_A./nu
VB_A = [zB_A × [i==1; i==2; i==3] for i in 1:3]
vNorm = norm.(VB_A)
iMax = findfirst(vNorm .≥ 0.2)
vB_A = VB_A[iMax]./vNorm[iMax]
return [(vB_A × zB_A) vB_A zB_A]
end
return Matrix(1.0I, 3, 3)
end

0 comments on commit a005716

Please sign in to comment.