def __mul__(left, right): """ multiply quaternion :arg left: left multiplicand :type left: Quaternion, UnitQuaternion :arg right: right multiplicand :type left: Quaternion, UnitQuaternion, 3-vector, float :return: product :rtype: Quaternion, UnitQuaternion :raises: ValueError ============== ============== ============== ================ Multiplicands Product ------------------------------- -------------------------------- left right type result ============== ============== ============== ================ Quaternion Quaternion Quaternion Hamilton product Quaternion UnitQuaternion Quaternion Hamilton product Quaternion scalar Quaternion scalar product UnitQuaternion Quaternion Quaternion Hamilton product UnitQuaternion UnitQuaternion UnitQuaternion Hamilton product UnitQuaternion scalar Quaternion scalar product UnitQuaternion 3-vector 3-vector vector rotation ============== ============== ============== ================ Any other input combinations result in a ValueError. Note that left and right can have a length greater than 1 in which case: ==== ===== ==== ================================ left right len operation ==== ===== ==== ================================ 1 1 1 ``prod = left * right`` 1 N N ``prod[i] = left * right[i]`` N 1 N ``prod[i] = left[i] * right`` N N N ``prod[i] = left[i] * right[i]`` N M - ``ValueError`` ==== ===== ==== ================================ A scalar of length N is a list, tuple or numpy array. A 3-vector of length N is a 3xN numpy array, where each column is a 3-vector. """ if type(left) == type(right): # quaternion * quaternion case (same class) return left.__class__( left._op2(right, lambda x, y: quat.qqmul(x, y) ) ) elif isinstance(other, Quaternion): # quaternion * quaternion case (different class) return Quaternion( left._op2(right, lambda x, y: quat.qqmul(x, y) ) ) elif argcheck.isscalar(right): # quaternion * scalar case print('scalar * quat') return Quaternion([right*q._A for q in left]) elif isinstance(self, UnitQuaternion) and argcheck.isvector(right,3): # scalar * vector case return quat.qvmul(left._A, argcheck.getvector(right,3)) else: raise ValueError('operands to * are of different types') return left._op2(right, lambda x, y: x @ y )
def __mul__(left, right): """ multiply quaternion :arg left: left multiplicand :type left: Quaternion :arg right: right multiplicand :type left: Quaternion, UnitQuaternion, float :return: product :rtype: Quaternion :raises: ValueError ============== ============== ============== ================ Multiplicands Product ------------------------------- -------------------------------- left right type result ============== ============== ============== ================ Quaternion Quaternion Quaternion Hamilton product Quaternion UnitQuaternion Quaternion Hamilton product Quaternion scalar Quaternion scalar product ============== ============== ============== ================ Any other input combinations result in a ValueError. Note that left and right can have a length greater than 1 in which case: ==== ===== ==== ================================ left right len operation ==== ===== ==== ================================ 1 1 1 ``prod = left * right`` 1 N N ``prod[i] = left * right[i]`` N 1 N ``prod[i] = left[i] * right`` N N N ``prod[i] = left[i] * right[i]`` N M - ``ValueError`` ==== ===== ==== ================================ """ if isinstance(right, left.__class__): # quaternion * [unit]quaternion case return Quaternion(left._op2(right, lambda x, y: quat.qqmul(x, y))) elif argcheck.isscalar(right): # quaternion * scalar case #print('scalar * quat') return Quaternion([right * q._A for q in left]) else: raise ValueError('operands to * are of different types') return left._op2(right, lambda x, y: x @ y)
def __truediv__(self, other): assert type(self) == type(other), 'operands to * are of different types' return self._op2(other, lambda x, y: quat.qqmul(x, quat.qconj(y)) )
def __mul__(left, right): """ Multiply unit quaternion :arg left: left multiplicand :type left: UnitQuaternion :arg right: right multiplicand :type left: UnitQuaternion, Quaternion, 3-vector, 3xN array, float :return: product :rtype: Quaternion, UnitQuaternion :raises: ValueError ============== ============== ============== ================ Multiplicands Product ------------------------------- -------------------------------- left right type result ============== ============== ============== ================ UnitQuaternion Quaternion Quaternion Hamilton product UnitQuaternion UnitQuaternion UnitQuaternion Hamilton product UnitQuaternion scalar Quaternion scalar product UnitQuaternion 3-vector 3-vector vector rotation UnitQuaternion 3xN array 3xN array vector rotations ============== ============== ============== ================ Any other input combinations result in a ValueError. Note that left and right can have a length greater than 1 in which case: ==== ===== ==== ================================ left right len operation ==== ===== ==== ================================ 1 1 1 ``prod = left * right`` 1 N N ``prod[i] = left * right[i]`` N 1 N ``prod[i] = left[i] * right`` N N N ``prod[i] = left[i] * right[i]`` N M - ``ValueError`` ==== ===== ==== ================================ A scalar of length N is a list, tuple or numpy array. A 3-vector of length N is a 3xN numpy array, where each column is a 3-vector. :seealso: :func:`~spatialmath.Quaternion.__mul__` """ if isinstance(left, right.__class__): # quaternion * quaternion case (same class) return right.__class__( left._op2(right, lambda x, y: quat.qqmul(x, y))) elif argcheck.isscalar(right): # quaternion * scalar case #print('scalar * quat') return Quaternion([right * q._A for q in left]) elif isinstance(right, (list, tuple, np.ndarray)): #print('*: pose x array') if argcheck.isvector(right, 3): v = argcheck.getvector(right) if len(left) == 1: # pose x vector #print('*: pose x vector') return quat.qvmul(left._A, argcheck.getvector(right, 3)) elif len(left) > 1 and argcheck.isvector(right, 3): # pose array x vector #print('*: pose array x vector') return np.array([tr.qvmul(x, v) for x in left._A]).T elif len(left) == 1 and isinstance( right, np.ndarray) and right.shape[0] == 3: return np.array([tr.qvmul(left._A, x) for x in right.T]).T else: raise ValueError('bad operands') else: raise ValueError( 'UnitQuaternion: operands to * are of different types') return left._op2(right, lambda x, y: x @ y) return right.__mul__(left)