1
$\begingroup$

I'm trying to work with quaternion math in Blender 2.82a and Python I need to normalize a quaternion number in Blender 2.82a using Python before I do calculations on it but I'm getting an error.

TypeError: unsupported operand type(s) for /: 'Quaternion' and 'float' for the line
quat1_norm = quat1 / math.sqrt(ww**2 + ii**2 + jj**2 + kk**2)

The code below is:

import math
import mathutils
import numpy as np

new_angle_rad = np.deg2rad(10)
ww = np.cos(new_angle_rad/2)
ii = np.sin(new_angle_rad/2)*0
jj = np.sin(new_angle_rad/2)*1
kk = np.sin(new_angle_rad/2)*0

quat1 = mathutils.Quaternion((ww, ii, jj, kk))

#Normalize quaternion to length 1 (unit quaternion). 
quat1_norm = quat1 / math.sqrt(ww**2 + ii**2 + jj**2 + kk**2) 

print(ww,ii,jj,kk)
print(quat1)

I'm trying to convert Octave code to work in Python and Blender https://octave.sourceforge.io/quaternion/function/@quaternion/unit.html

Here's the Octave math code I'm trying to convert.

Function File: qn = unit (q)

    Normalize quaternion to length 1 (unit quaternion).

              q = w + x*i + y*j + z*k
              unit (q) = q ./ sqrt (w.^2 + x.^2 + y.^2 + z.^2)

Package: quaternion

I did try:

quat1_norm=mathutils.Quaternion.normalize(mathutils.Quaternion((1, 2, 3, 4)))
print(quat1_norm)

it comes back with None.

When a similar command is done in Octave I get this

unit(quaternion(1,2,3,4))
ans = 0.1826 + 0.3651i + 0.5477j + 0.7303k
$\endgroup$

1 Answer 1

1
$\begingroup$

This can be done making and using the function below:

Original:

def normalize(v, tolerance=0.00001):
    mag2 = sum(n * n for n in v)
    if abs(mag2 - 1.0) > tolerance:
        mag = math.sqrt(mag2)
        v = tuple(n / mag for n in v)
    return np.array(v)

Updated Version using batFINGER suggestion: April 26 2020

def normalize(v, tolerance=0.00001):
    mag2 = sum(n * n for n in v)
    if mag2 > tolerance:
        mag = math.sqrt(mag2)
        v = tuple(n / mag for n in v)
    return np.array(v)

Or using the built in Function

import mathutils
quat1 = mathutils.Quaternion((1, 2, 3, 4))
quat1_norm = quat1.normalized()
print(quat1_norm)
$\endgroup$
2
  • $\begingroup$ Would edit to if mag2 > tolerance: only zero length vectors are an issue. $\endgroup$
    – batFINGER
    Apr 26, 2020 at 10:07
  • $\begingroup$ Trying methods above on Quaternion((0, 0, 0, 0)) deliver a zero division error, (0, 0, 0, 0) and (0, 1, 0, 0). Not sure why the zero quat result normalizes to x=1 whereas default (Quaternion()) is w=1. If using numpy no need to loop normalized_v = v / np.sqrt(np.sum(v ** 2)) and check for all zeros. $\endgroup$
    – batFINGER
    Apr 26, 2020 at 14:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .