Source code for blenderproc.python.sampler.UniformSO3
from typing import List, Optional, Union
import mathutils
import random
import numpy as np
[docs]def uniformSO3(around_x: bool = True, around_y: bool = True, around_z: bool = True) -> np.ndarray:
""" Uniformly samples rotations from SO(3). Allows to limit the rotation around Blender World coordinate axes.
:param around_x: Whether to rotate around X-axis.
:param around_y: Whether to rotate around Y-axis.
:param around_z: Whether to rotate around Z-axis.
:return: Sampled rotation in euler angles.
"""
# Uniform sampling in full SO3.
if around_x and around_y and around_z:
quat_rand = UniformSO3._random_quaternion()
euler_rand = mathutils.Quaternion(quat_rand).to_euler()
# Uniform sampling of angles around the selected axes.
else:
def random_angle():
return random.uniform(0, 2 * np.pi)
mat_rand = mathutils.Matrix.Identity(3)
if around_x:
mat_rand @= mathutils.Matrix.Rotation(random_angle(), 3, 'X')
if around_y:
mat_rand @= mathutils.Matrix.Rotation(random_angle(), 3, 'Y')
if around_z:
mat_rand @= mathutils.Matrix.Rotation(random_angle(), 3, 'Z')
euler_rand = mat_rand.to_euler()
return np.array(euler_rand)
[docs]class UniformSO3:
[docs] @staticmethod
def _random_quaternion(rand: Optional[Union[List[float], np.ndarray]] = None) -> np.ndarray:
""" Return uniform random unit quaternion.
https://github.com/thodan/bop_toolkit/blob/master/bop_toolkit_lib/transform.py
:param rand: Three independent random variables that are uniformly distributed between 0 and 1.
:return: Unit quaternion.
"""
if rand is None:
rand = np.random.rand(3)
else:
assert len(rand) == 3
r1 = np.sqrt(1.0 - rand[0])
r2 = np.sqrt(rand[0])
pi2 = np.pi * 2.0
t1 = pi2 * rand[1]
t2 = pi2 * rand[2]
return np.array([np.cos(t2) * r2, np.sin(t1) * r1, np.cos(t1) * r1, np.sin(t2) * r2])