How to broadcast a Vector of an Array


#1

I try to convert a 2-dimensional array of floats to a 1-dimensional array of Quaternions. I want to use broadcasting for this. The following code fails. How can it be fixed?

using Rotations, StaticArrays


function Quat(vec::SVector{4,Float64})
    return Quat(vec[1], vec[2], vec[3], vec[4])
end

q1 = [0.287819, -0.0776879, 0.208938, 0.931381]

q2 = [0.287819, -0.0776879, 0.208938, 0.931381]

quat = [q1 q2]'

new_quat = Quat.(quat)

The error message is:

ERROR: LoadError: MethodError: no method matching Quat(::Float64)
Closest candidates are:
  Quat(::StaticArrays.SArray{Tuple{4},Float64,1,4}) at /home/shekhar/uavtalk/scripts/test_quat.jl:5
Stacktrace:
 [1] broadcast_t(::Function, ::Type{Any}, ::Tuple{Base.OneTo{Int64},Base.OneTo{Int64}}, ::CartesianRange{CartesianIndex{2}}, ::Array{Float64,2}) at ./broadcast.jl:258
 [2] broadcast_c at ./broadcast.jl:321 [inlined]
 [3] broadcast(::Function, ::Array{Float64,2}) at ./broadcast.jl:455
 [4] include_from_node1(::String) at ./loading.jl:576
 [5] include(::String) at ./sysimg.jl:14
while loading /home/shekhar/uavtalk/scripts/test_quat.jl, in expression starting on line 14


#2

Broadcasting works completely elementwise. What you’re after is a function that operates on whole columns of your matrix at a time. Mapping across slices: mapslices.

You can also use reinterpret here if you want to share memory.


#3

Your Quat function expects an SVector{4,Float64}, so to broadcast with it you’ll need some container like a vector that contains SVector{4,Float64}'s. In your code q1 and q2 aren’t SVector’s. They’re just normal vectors. The way you are making quat concatenates q1 and q2 into a single 2 dimensional array. You would probably want to make a vector of SVector’s instead.

q1 = SVector{4,Float64}(0.287819, -0.0776879, 0.208938, 0.931381)
q2 = SVector{4,Float64}(0.287819, -0.0776879, 0.208938, 0.931381)
quat = [q1, q2]
new_quat = Quat.(quat)