コード例 #1
0
def rotate_vector(vector, quat_array):
    '''Given an array of quaternions, rotate every vector in vector.

    Parameters
    ----------
    vector : array_like
        Nx3 array 
    quat_array : array of quaternions as defined by np.quaternion 

    Returns
    -------
    vector : array_like

    TODO
    ----------
    Replace this by v' = v + 2 * r x (s * v + r x v) / m
    where x represents the cross product, s and r are the scalar and
    vector parts of the quaternion, respectively, and m is the sum of
    the squares of the components of the quaternion. Implemented with numba.
   '''
    if type(quat_array[0]) != quaternion.quaternion:
        quat_array = quaternion.from_float_array(quat_array)
    N = vector.shape[0]
    V = quaternion.from_float_array(np.hstack((np.zeros((N, 1)), vector)))
    return quaternion.as_float_array(
        quat_array * V * np.invert(quat_array)
    )[:, 1:]  # norm is the square of the II-norm in np.quaternion
コード例 #2
0
    def compute_quat(self, predictions, targets, reduce_fn="mean"):
        """
        Compute the chosen metrics. Predictions and targets are assumed to be quaternions.
        Args:
            predictions: An np array of shape (n, seq_length, n_joints*4)
            targets: An np array of the same shape as `predictions`
            reduce_fn: Which reduce function to apply to the joint dimension, if applicable. Choices are [mean, sum].

        Returns:
            A dictionary {metric_name -> values} where the values are given per batch entry and frame as an np array
            of shape (n, seq_length). `reduce_fn` is only applied to metrics where it makes sense, i.e. not to PCK
            and euler angle differences.
        """
        assert predictions.shape[-1] % 4 == 0, "predictions are not quaternions"
        assert targets.shape[-1] % 4 == 0, "targets are not quaternions"
        assert reduce_fn in ["mean", "sum"]
        assert not self._should_call_reset, "you should reset the state of this class after calling `finalize`"
        dof = 4
        batch_size = predictions.shape[0]
        seq_length = predictions.shape[1]

        # for simplicity we just convert quaternions to rotation matrices
        pred_q = quaternion.from_float_array(np.reshape(predictions, [batch_size, seq_length, -1, dof]))
        targ_q = quaternion.from_float_array(np.reshape(targets, [batch_size, seq_length, -1, dof]))
        pred_rots = quaternion.as_rotation_matrix(pred_q)
        targ_rots = quaternion.as_rotation_matrix(targ_q)

        preds = np.reshape(pred_rots, [batch_size, seq_length, -1])
        targs = np.reshape(targ_rots, [batch_size, seq_length, -1])
        return self.compute_rotmat(preds, targs, reduce_fn)
コード例 #3
0
def angular_velocity(R, t):
    from scipy.interpolate import CubicSpline
    R = quaternion.as_float_array(R)
    Rdot = CubicSpline(t, R).derivative()(t)
    R = quaternion.from_float_array(R)
    Rdot = quaternion.from_float_array(Rdot)
    return quaternion.as_float_array(2*Rdot/R)[:, 1:]
コード例 #4
0
def angular_velocity(R, t):
    from scipy.interpolate import InterpolatedUnivariateSpline as spline
    R = quaternion.as_float_array(R)
    Rdot = np.empty_like(R)
    for i in range(4):
        Rdot[:, i] = spline(t, R[:, i]).derivative()(t)
    R = quaternion.from_float_array(R)
    Rdot = quaternion.from_float_array(Rdot)
    return np.array([omega.vec for omega in (2*Rdot/R)])
コード例 #5
0
def angular_velocity(R, t):
    from scipy.interpolate import InterpolatedUnivariateSpline as spline
    R = quaternion.as_float_array(R)
    Rdot = np.empty_like(R)
    for i in range(4):
        Rdot[:, i] = spline(t, R[:, i]).derivative()(t)
    R = quaternion.from_float_array(R)
    Rdot = quaternion.from_float_array(Rdot)
    return quaternion.as_float_array(2*Rdot/R)[:, 1:]
コード例 #6
0
def load_dataset_6d_rvec(imu_data_filename, gt_data_filename, window_size=200, stride=10):

    #imu_data = np.genfromtxt(imu_data_filename, delimiter=',')
    #gt_data = np.genfromtxt(gt_data_filename, delimiter=',')
    
    imu_data = pd.read_csv(imu_data_filename).values
    gt_data = pd.read_csv(gt_data_filename).values

    #imu_data = imu_data[1200:-300]
    #gt_data = gt_data[1200:-300]
    
    gyro_acc_data = np.concatenate([imu_data[:, 4:7], imu_data[:, 10:13]], axis=1)
    
    pos_data = gt_data[:, 2:5]
    ori_data = np.concatenate([gt_data[:, 8:9], gt_data[:, 5:8]], axis=1)

    init_q = quaternion.from_float_array(ori_data[window_size//2 - stride//2, :])
    
    init_rvec = np.empty((3, 1))
    cv2.Rodrigues(quaternion.as_rotation_matrix(init_q), init_rvec)

    init_tvec = pos_data[window_size//2 - stride//2, :]

    x = []
    y_delta_rvec = []
    y_delta_tvec = []

    for idx in range(0, gyro_acc_data.shape[0] - window_size - 1, stride):
        x.append(gyro_acc_data[idx + 1 : idx + 1 + window_size, :])

        tvec_a = pos_data[idx + window_size//2 - stride//2, :]
        tvec_b = pos_data[idx + window_size//2 + stride//2, :]

        q_a = quaternion.from_float_array(ori_data[idx + window_size//2 - stride//2, :])
        q_b = quaternion.from_float_array(ori_data[idx + window_size//2 + stride//2, :])

        rmat_a = quaternion.as_rotation_matrix(q_a)
        rmat_b = quaternion.as_rotation_matrix(q_b)

        delta_rmat = np.matmul(rmat_b, rmat_a.T)

        delta_rvec = np.empty((3, 1))
        cv2.Rodrigues(delta_rmat, delta_rvec)

        delta_tvec = tvec_b - np.matmul(delta_rmat, tvec_a.T).T

        y_delta_rvec.append(delta_rvec)
        y_delta_tvec.append(delta_tvec)


    x = np.reshape(x, (len(x), x[0].shape[0], x[0].shape[1]))
    y_delta_rvec = np.reshape(y_delta_rvec, (len(y_delta_rvec), y_delta_rvec[0].shape[0]))
    y_delta_tvec = np.reshape(y_delta_tvec, (len(y_delta_tvec), y_delta_tvec[0].shape[0]))

    return x, [y_delta_rvec, y_delta_tvec], init_rvec, init_tvec
コード例 #7
0
def quatUnion(q_parent, q_child):

    q_parent_conj = np.array([q_parent[0], -q_parent[1], -q_parent[2], -q_parent[3]])

    q_parent = quaternion.from_float_array(q_parent)
    q_child = quaternion.from_float_array(q_child)

    q_parent_conj = quaternion.from_float_array(q_parent_conj)

    qU = q_parent_conj * q_child
    return quaternion.as_float_array(qU).astype(np.float32)
コード例 #8
0
    def load(self, data_path):
        if data_path[-1] == '/':
            data_path = data_path[:-1]
        with open(osp.join(data_path, 'info.json')) as f:
            self.info = json.load(f)

        # {'tango_reference_time': 3697949488366.0, 'date': '01/21/19', 'imu_init_gyro_bias': [0.005569000000000001, 0.009201, -0.00018299999999999914], 'imu_acce_scale': [0.9987918889533104, 0.997062129866083, 0.9932574091553678], 'grv_ori_error': 8.353779492444412, 'align_tango_to_body': [-0.4841758535176575, -0.4938374978693588, -0.5424326634072199, 0.47693298715598254], 'start_frame': 5896, 'imu_end_gyro_bias': [0.005432, 0.008774, -4.6e-05], 'type': 'annotated', 'imu_reference_time': 3610942440968.0, 'start_calibration': [0.0, 0.99995545, 0.009439, 0.0], 'ekf_ori_error': 3.6239102945197676, 'imu_acce_bias': [-0.15661902624553775, -0.026333329541761968, 0.05681364453654479], 'gyro_integration_error': 8.481689436777705, 'device': 'asus4', 'length': 323.7550000070669, 'imu_time_offset': -0.07619643889847794, 'end_calibration': [0.0, 0.99998599, 0.0052938, 0.0]}

        self.info['path'] = osp.split(data_path)[-1]

        self.info['ori_source'], ori, self.info['source_ori_error'] = select_orientation_source( # ori is hdf5.synced.game_rv i. e. Android Sensor.TYPE_GAME_ROTATION_VECTOR
            data_path, self.max_ori_error, self.grv_only)
        #('game_rv', array([[ 0.02301384, -0.734161  ,  0.00956859,  0.67851714], [ 0.02296023, -0.73417201,  0.00956628,  0.67850771], ..., [ 0.05427992,  0.70881762,  0.07637797, -0.6991363 ]]]), 8.353779492444412)

        with h5py.File(osp.join(data_path, 'data.hdf5')) as f:
            gyro_uncalib = f['synced/gyro_uncalib']                                                                # <HDF5 dataset "gyro_uncalib": shape (64752, 3), type "<f8">
            acce_uncalib = f['synced/acce']                                                                        # <HDF5 dataset "acce": shape (64752, 3), type "<f8">
            gyro = gyro_uncalib - np.array(self.info['imu_init_gyro_bias'])                                        # array([[-0.02230625,  0.01376489,  0.01876768], [-0.01673078,  0.00785385,  0.01808999], ..., [ 0.00657855, -0.02807542,  0.00804713]])
            acce = np.array(self.info['imu_acce_scale']) * (acce_uncalib - np.array(self.info['imu_acce_bias']))   # array([[-9.76895341, -0.19332236, -0.85234999], [-9.76140265, -0.2099069 , -0.81018915], ..., [-9.82066284, -0.32593967, -0.28265888]])
            ts = np.copy(f['synced/time'])                                                                         # array([3641.39639807, 3641.40139807, 3641.40639807, ..., 3965.14139807, 3965.14639807, 3965.15139807])
            tango_pos = np.copy(f['pose/tango_pos'])                                                               # array([[ 0.00747055,  0.0794231 ,  0.04721916], [ 0.00743938,  0.07954534,  0.04721213], ..., [ 0.04869788, -0.01891041, -0.03532039]])
            init_tango_ori = quaternion.quaternion(*f['pose/tango_ori'][0])                                        # quaternion(0.500218919180744, 0.498520940104168, 0.458115146317795, -0.539803994906776)

        # Compute the IMU orientation in the Tango coordinate frame.
        ori_q = quaternion.from_float_array(ori)                                   # array([quaternion(0.0230138445473811, -0.734161004581412, 0.00956858773770847, 0.678517142961637), quaternion(0.0229602307881793, -0.734172007659053, 0.00956628356173319, 0.678507709011024), ..., quaternion(0.0542799190079345, 0.708817623072373, 0.0763779734707989, -0.6991362963311)], dtype=quaternion)
        # hdf5.synced.game_rv i. e. Android Sensor.TYPE_GAME_ROTATION_VECTOR

        rot_imu_to_tango = quaternion.quaternion(*self.info['start_calibration'])  # quaternion(0, 0.99995545, 0.009439, 0)
        init_rotor = init_tango_ori * rot_imu_to_tango * ori_q[0].conj()           # quaternion(-0.695289552060529, 0.00118374652078425, 0.00248606386725569, 0.718723783950829)
        ori_q = init_rotor * ori_q                                                 # array([quaternion(-0.5028224217168, 0.50529138394065, -0.535057892743795, -0.453388785030156), quaternion(-0.502778345472314, 0.505300603413145, -0.535064320967734, -0.453420734559951), ..., quaternion(0.463716682908265, -0.54940199756135, 0.457301820727505, 0.523442677366401)], dtype=quaternion)
        # ori_q = f['pose/tango_ori'][0] * self.info['start_calibration'] * conj(f['synced/game_rv'][0]) * f['synced/game_rv']

        dt = (ts[self.w:] - ts[:-self.w])[:, None]                                 # array([[1.], [1.], [1.], ..., [1.],[1.], [1.]])

        glob_v = (tango_pos[self.w:] - tango_pos[:-self.w]) / dt                   # array([[-0.00533056,  0.01667982, -0.00509732], [-0.00531125,  0.016594  , -0.00511179], ..., [-0.0023489 ,  0.00633583, -0.00057166]])

        # these two below are position vector arrays
        gyro_q = quaternion.from_float_array(np.concatenate([np.zeros([gyro.shape[0], 1]), gyro], axis=1))  # array([quaternion(0, -0.0223062507369463, 0.0137648946088728, 0.0187676819234896), quaternion(0, -0.0167307794589504, 0.00785385399152264, 0.018089989505323), ..., quaternion(0, 0.00657855020053501, -0.0280754170707831, 0.0080471337151681)], dtype=quaternion)
        acce_q = quaternion.from_float_array(np.concatenate([np.zeros([acce.shape[0], 1]), acce], axis=1))  # array([quaternion(0, -9.76895340810378, -0.193322357928738, -0.852349993053583), quaternion(0, -9.76140265037272, -0.209906902110648, -0.810189151712629), ..., quaternion(0, -9.8206628384554, -0.325939671417927, -0.282658875290474)], dtype=quaternion)

        # each element vector rotated by the corresponding ori_q rotation quaternion
        # At test time, we use the coordinate frame defined by system device orientations from Android or iOS, whose Z axis is aligned with gravity.
        # The whole is transformed into the global (Tango) coordinate frame.
        glob_gyro = quaternion.as_float_array(ori_q * gyro_q * ori_q.conj())[:, 1:]  # array([[-0.01258328,  0.02161022,  0.02034508], [-0.00665554,  0.02000185,  0.0149826 ], ..., [ 0.02674353,  0.01209917, -0.0058859 ]])
        glob_acce = quaternion.as_float_array(ori_q * acce_q * ori_q.conj())[:, 1:]  # array([[-3.46650073e-02, -3.36474233e-02,  9.80783499e+00], [-1.38849800e-02,  6.54256497e-03,  9.79719413e+00], ..., [ 3.31727211e-02, -6.26925428e-02,  9.82980926e+00]])

        start_frame = self.info.get('start_frame', 0)                                # 5896
        self.ts = ts[start_frame:]                                                   # array([3670.87639807, 3670.88139807, 3670.88639807, ..., 3965.14139807, 3965.14639807, 3965.15139807])
        self.features = np.concatenate([glob_gyro, glob_acce], axis=1)[start_frame:] # array([[-5.94662071e-03, -9.38751552e-03, -5.15188486e-03, -3.08588928e-02,  6.39869105e-02,  9.86019268e+00], [-5.27530580e-03, -7.75847573e-03, -1.59778536e-02, -3.54599110e-02,  5.16253587e-02,  9.82394159e+00], ..., [ 2.67435308e-02,  1.20991655e-02, -5.88589595e-03, 3.31727211e-02, -6.26925428e-02,  9.82980926e+00]])
        self.targets = glob_v[start_frame:, :2]                                      # array([[-0.02427537,  0.02117807], [-0.02406481,  0.02145767], ..., [-0.0023489 ,  0.00633583]]) targets are averaged for the window w
        self.orientations = quaternion.as_float_array(ori_q)[start_frame:]           # array([[-0.51946022,  0.24279321, -0.60182678,  0.55589147], [-0.51947897,  0.24272502, -0.6018242 ,  0.55590699], ..., [ 0.46371668, -0.549402  ,  0.45730182,  0.52344268]])
        self.gt_pos = tango_pos[start_frame:]                                        # array([[ 0.17387274, -0.14344794, -0.0743621 ], [ 0.17362087, -0.14350179, -0.07425673], ..., [ 0.04869788, -0.01891041, -0.03532039]])
コード例 #9
0
def initPosTransfer(bodypose, q):


    q_conj = np.array([q[0], -q[1], -q[2], -q[3]])
    q = quaternion.from_float_array(q)
    q_conj = quaternion.from_float_array(q_conj)
    for i in range(len(bodypose)):
        v = np.array([0, bodypose[i][0],bodypose[i][1], bodypose[i][2]])
        v = quaternion.from_float_array(v)

        v_new = q_conj*v*q
        bodypose[i] = np.array([v_new.x, v_new.y, v_new.z])
    return bodypose
コード例 #10
0
ファイル: util.py プロジェクト: xxyu/6-DOF-Inertial-Odometry
def generate_trajectory_6d_quat(init_p, init_q, y_delta_p, y_delta_q):
    cur_p = np.array(init_p)
    cur_q = quaternion.from_float_array(init_q)
    pred_p = []
    pred_p.append(np.array(cur_p))

    for [delta_p, delta_q] in zip(y_delta_p, y_delta_q):
        cur_p = cur_p + np.matmul(quaternion.as_rotation_matrix(cur_q),
                                  delta_p.T).T
        cur_q = cur_q * quaternion.from_float_array(delta_q).normalized()
        pred_p.append(np.array(cur_p))

    return np.reshape(pred_p, (len(pred_p), 3))
コード例 #11
0
	def load(self, data_path):
		if data_path[-1] == '/':
			data_path = data_path[:-1]
		with open(osp.join(data_path, 'info.json')) as f:
			self.info = json.load(f)

		self.info['path'] = osp.split(data_path)[-1]

		if self.with_orientation:
			self.info['ori_source'], ori, self.info['source_ori_error'] = select_orientation_source(
				data_path, self.max_ori_error, self.grv_only)

		with h5py.File(osp.join(data_path, 'data.hdf5')) as f:
			gyro_uncalib = f['synced/gyro_uncalib']
			acce_uncalib = f['synced/acce']
			gyro = gyro_uncalib - np.array(self.info['imu_init_gyro_bias'])
			# acce = np.array(self.info['imu_acce_scale']) * (acce_uncalib - np.array(self.info['imu_acce_bias']))
			acce = acce_uncalib
			ts = np.copy(f['synced/time'])

			# tango_pos = np.copy(f['pose/tango_pos'])
			# init_tango_ori = quaternion.quaternion(*f['pose/tango_ori'][0])

			if self.with_orientation:
				gyro = np.copy(gyro)
				acce = np.copy(acce)
			else:
				glob_gyro = np.copy(gyro)
				glob_acce = np.copy(acce)


		# Compute the IMU orientation in the Tango coordinate frame.
		if self.with_orientation:
			ori_q = quaternion.from_float_array(ori)
			# rot_imu_to_tango = quaternion.quaternion(*self.info['start_calibration'])
			# init_rotor = init_tango_ori * rot_imu_to_tango * ori_q[0].conj()
			# ori_q = init_rotor * ori_q

			gyro_q = quaternion.from_float_array(np.concatenate([np.zeros([gyro.shape[0], 1]), gyro], axis=1))
			acce_q = quaternion.from_float_array(np.concatenate([np.zeros([acce.shape[0], 1]), acce], axis=1))

			glob_gyro = quaternion.as_float_array(ori_q * gyro_q * ori_q.conj())[:, 1:]
			glob_acce = quaternion.as_float_array(ori_q * acce_q * ori_q.conj())[:, 1:]

		# dt = (ts[self.w:] - ts[:-self.w])[:, None]
		# glob_v = (tango_pos[self.w:] - tango_pos[:-self.w]) / dt


		start_frame = self.info.get('start_frame', 0)
		self.ts = ts[start_frame:]
		self.features = np.concatenate([glob_gyro, glob_acce], axis=1)[start_frame:]
コード例 #12
0
    def pow(self, exponent):
        """self^exponent
        :param exponent: single float
        """
        exponent = float(exponent)

        q_r_float = quaternion.as_float_array(self.q_r)
        q_d_float = quaternion.as_float_array(self.q_d)

        if len(self)==1:
            q_r_w, q_r_vec = self.q_r.w, self.q_r.vec
            q_d_w, q_d_vec = self.q_d.w, self.q_d.vec

            q_r_w, q_r_vec = np.array([q_r_w])[:,None], np.array([q_r_vec])[:,None]
            q_d_w, q_d_vec = np.array([q_d_w])[:, None], np.array([q_d_vec])[:, None]


        else:
            q_r_float = quaternion.as_float_array(self.q_r)
            q_d_float = quaternion.as_float_array(self.q_d)
            q_r_w = q_r_float[:,0]
            q_r_vec = q_r_float[:,1:]
            q_d_w = q_d_float[:, 0]
            q_d_vec = q_d_float[:,1:]

        theta = 2 * np.arccos(q_r_w)



        if np.all(np.isclose(theta, 0)):
            return DualQuaternion.from_translation_vector(exponent * np.array(self.translation()))
        else:

            s0 = q_r_vec / np.sin(theta[:,None] / 2)
            d = -2. * q_d_w / np.sin(theta / 2)
            se = (q_d_vec - s0 * d[:,None] / 2 * np.cos(theta[:,None] / 2)) / np.sin(theta[:,None] / 2)

        q_r_float = np.zeros((len(self),4))
        q_r_float[:,0] = np.cos(exponent * theta / 2)
        q_r_float[:,1:] = np.sin(exponent * theta[:,None] / 2) * s0
        q_r = quaternion.from_float_array(q_r_float)

        q_d_float = np.zeros((len(self), 4))
        q_d_float[:,0] = -exponent * d / 2 * np.sin(exponent * theta / 2)
        #q_d_float[:,1:] = exponent * d / 2 * np.cos(exponent * theta / 2) * s0 + np.sin(exponent * theta / 2) * se
        p3 = (exponent * d /2 *np.cos(exponent * theta / 2))[:,None] * s0 + np.sin(exponent * theta[:,None] / 2) * se

        q_d_float[:,1:] = p3
        q_d = quaternion.from_float_array(q_d_float)
        return DualQuaternion(q_r, q_d)
コード例 #13
0
def world_coordinates_from_rot_trans(init_t, init_q, relative_t, relative_q):
    t = np.array(init_t)
    q = quaternion.from_float_array(init_q)
    pred_t = []
    pred_t.append(t)

    for [delta_t, delta_q] in zip(relative_t, relative_q):
        t = t + np.matmul(quaternion.as_rotation_matrix(q), delta_t.T).T
        q = q * quaternion.from_float_array(delta_q).normalized()
        pred_t.append(np.array(t))
    coord = np.reshape(pred_t, (len(pred_t), 3))
    x = coord[:, 0]
    y = coord[:, 1]
    z = coord[:, 2]
    return (x, y, z)
コード例 #14
0
def calibrateRawIMU(ori):
    import quaternion
    import itertools
    import myUtil
    ######### **********the order of IMUs are: [left_lower_wrist, right_lower_wrist, left_lower_leg, right_loewr_leg, head, back]
    SMPL_SENSOR = [
        'L_Shoulder', 'R_Shoulder', 'L_Knee', 'R_Knee', 'Head', 'Pelvis'
    ]

    ############### calculation in Rotation Matrix #########################
    seq_len = len(ori)
    # head sensor for the first frame
    head_quat = quaternion.from_float_array(ori[100, 4, :])
    Q = np.quaternion(0.5, 0.5, 0.5, 0.5)
    # calib: R(T_I) which is constant over the frames
    calib = np.linalg.inv(quaternion.as_rotation_matrix(np.dot(head_quat, Q)))

    # bone2sensor: R(B_S) calculated once for each sensor and remain constant over the frames as used further
    bone2sensor = {}
    for i in range(len(SMPL_SENSOR)):
        sensorid = SMPL_SENSOR[i]
        qbone = quaternion.as_rotation_matrix(
            quaternion.from_rotation_vector(myUtil.getGlobalBoneOri(sensorid)))
        qsensor = np.dot(
            calib,
            quaternion.as_rotation_matrix(
                quaternion.from_float_array(ori[100, i, :])))
        boneQuat = np.dot(np.linalg.inv(qsensor), qbone)
        bone2sensor[i] = boneQuat

    # calibrated_ori: R(T_B) calculated as calib * sensor data(changes every frame) * bone2sensor(corresponding sensor)
    calibrated_ori = np.asarray([
        np.linalg.multi_dot([
            calib,
            quaternion.as_rotation_matrix(
                quaternion.from_float_array(ori[k, j, :])), bone2sensor[j]
        ]) for k, j in itertools.product(range(seq_len), range(6))
    ])
    calibrated_ori = calibrated_ori.reshape(-1, 6, 3, 3)
    root_inv = np.linalg.inv(calibrated_ori[:, 5, :, :])
    # root_inv = np.transpose(calibrated_ori[:, 5], [0, 2, 1])
    norm_ori = np.asarray([
        np.matmul(root_inv[k], calibrated_ori[k, j, :, :])
        for k, j in itertools.product(range(seq_len), range(6))
    ])
    norm_ori = norm_ori.reshape(-1, 6, 3, 3)

    return norm_ori[:, 0:5, :, :]
コード例 #15
0
def createSequence(keyframes, dt=0.1):
    timestamps = [frame.timestamp for frame in keyframes]
    rotations = quaternion.as_quat_array([[frame.frame.orientation.x, frame.frame.orientation.y, frame.frame.orientation.z, frame.frame.orientation.w] for frame in keyframes])

    # Coordinate frame conversion
    multiplier_quat = quaternion.from_float_array([np.sqrt(2) / 2, -np.sqrt(2) / 2, 0, 0])
    rotations = [rot * multiplier_quat for rot in rotations]

    positions = np.array([[frame.frame.position.x, frame.frame.position.y, frame.frame.position.z] for frame in keyframes])

    time_interps = list(np.arange(timestamps[0], timestamps[-1], dt)) + [timestamps[-1]]
    lerp = interp1d(timestamps, positions, axis=0) 
    lin_interps = lerp(time_interps)

    rot_interps = []
    for i in range(len(keyframes) - 1):
        rot_interps.extend(quaternion.as_float_array(quaternion.slerp(rotations[i], rotations[i + 1], timestamps[i], timestamps[i + 1], np.arange(timestamps[i], timestamps[i + 1], dt))))
    rot_interps.append(quaternion.as_float_array(rotations[-1]))

    sequence = []
    for pos, ori in zip(lin_interps, rot_interps):
        pose = Pose()
        pose.position.x, pose.position.y, pose.position.z = pos
        pose.orientation.w, pose.orientation.x, pose.orientation.y, pose.orientation.z = ori
        pose_stamped = PoseStamped()
        pose_stamped.pose = pose
        sequence.append(pose_stamped)


    g_poses[0] = sequence[-1].pose
    g_poses[1] = sequence[-1].pose

    return time_interps, sequence 
コード例 #16
0
 def test_avg(self):
     # distribute a bunch of rotation around I,
     # such that the average should be I:
     # at random axis but constant angle,
     nb_rotations = 1000
     angles = np.linspace(0.0, np.deg2rad(45), 100)
     averages_q = []
     np.random.seed(1)
     for angle in angles:
         rotation_axis = np.random.uniform(-1., 1., size=(nb_rotations, 3))
         rotation_axis /= np.linalg.norm(rotation_axis,
                                         axis=1,
                                         keepdims=True)
         rotation_axis *= angle
         rotation_qs = quaternion.from_rotation_vector(rotation_axis)
         rotation_qs = quaternion.as_float_array(rotation_qs)
         # print(rotation_qs)
         r = average_quaternion(rotation_qs)
         averages_q.append(r.tolist())
     averages_q = np.array(averages_q)
     # normalizes rotation (resolve the opposite ambiguity)
     averages_q *= np.sign(averages_q[:, 0]).reshape((-1, 1))
     # convert quaternions to angle-axis representation
     averages_q = quaternion.from_float_array(averages_q)
     averages_v = quaternion.as_rotation_vector(averages_q)
     # retrieve angle amplitudes.
     errors_rad = np.linalg.norm(averages_v, axis=1)
     # # plot for debug
     # import matplotlib.pyplot as plt
     # plt.plot(np.rad2deg(errors_rad), 'x', label='Errors (in deg.) as a function of angle amplitude (in deg.)')
     # plt.show()
     maximum_error_deg = np.rad2deg(np.max(errors_rad))
     self.assertLess(maximum_error_deg, 3.6)
コード例 #17
0
    def __init__(self, tcp_pos=None, tcp_quat=None):
        self.d_bs = 0.36
        self.d_se = 0.42
        self.d_ew = 0.4
        self.d_wf = 0.151

        # DH_paramters a_i, alpha_i, d_i
        self.dh_a = np.array([0., 0., 0., 0., 0., 0., 0.])
        self.dh_alpha = np.array([-np.pi / 2, np.pi / 2, np.pi / 2, -np.pi / 2, -np.pi / 2, np.pi / 2, 0.])
        self.dh_d = np.array([self.d_bs, 0., self.d_se, 0., self.d_ew, 0., self.d_wf])

        self.joint_limits = np.vstack([IIWA_JOINT_MIN_LIMITS, IIWA_JOINT_MAX_LIMITS]).T

        self.joint_vel_limits = np.array([[-85., 85.],
                                          [-85., 85.],
                                          [-100., 100.],
                                          [-75., 75.],
                                          [-130., 130.],
                                          [-135., 135.],
                                          [-135., 135.]]) / 180. * np.pi

        self.singularity_eps = 0.1

        self.T_ee = np.eye(4)
        if tcp_pos is not None:
            self.T_ee[:3, 3] = tcp_pos
        if tcp_quat is not None:
            self.T_ee[:3, :3] = quaternion.as_rotation_matrix(quaternion.from_float_array(tcp_quat))
コード例 #18
0
 def from_quat(self, joint_angles):
     """
     Get joint positions from quaternion representations in shape (N, H36M_NR_JOINTS*4)
     """
     qs = quaternion.from_float_array(np.reshape(joint_angles, [-1, H36M_NR_JOINTS, 4]))
     aa = quaternion.as_rotation_matrix(qs)
     return self.fk(np.reshape(aa, [-1, H36M_NR_JOINTS * 3]))
コード例 #19
0
    def update_orientation(self, timestep, ext_forces):
        """
    Update the orientation of the rigid body according to the ellapsed time and external forces.
   
    Parameters
    ----------
    timestep : scalar
      The ellapsed time.
    ext_forces : dict
      The external forces applied to the rigid body.

    Returns
    -------
    quaternion
      A copy of the rigid body's orientation.
    """
        cm_torque = sum([
            force.torque(self.orientation) for force in ext_forces.values()
        ])  # M
        non_inertial_term = np.cross(self.ang_velocity,
                                     self.inertia.dot(
                                         self.ang_velocity))  # w x (I.w)
        ang_acceleration = np.linalg.inv(self.inertia).dot(
            cm_torque - non_inertial_term
        )  #+ from Euler's equations I.w_dot + w x (I.w) = M
        self.ang_velocity += ang_acceleration * timestep  # dw = w_dot*dt
        omega_matrix = self.quaternion_omega_matrix()
        d_orientation = omega_matrix.dot(q.as_float_array(
            self.orientation)) * 0.5 * timestep
        self.orientation += q.from_float_array(
            d_orientation)  # q_dot=0.5*Omega*q
        return np.copy(self.orientation)
コード例 #20
0
def orientation_to_angles(ori):
    """
    Covert an array of quaternions to an array of Euler angles. Calculations are from Android source code:

    https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/hardware/SensorManager.java
    Function "getOrientation(float[] R, float[] values)"

    Note that this function DOES NOT consider singular configurations, such as Gimbal Lock.

    Args:
        ori: an array of N quaternions.

    Returns:
        A Nx3 array. With Android's game rotation vector or rotation vector, each group of three values
        correspond to: azimuth(yaw), pitch and roll, respectively.
    """
    if ori.dtype != quaternion.quaternion:
        ori = quaternion.from_float_array(ori)

    rm = quaternion.as_rotation_matrix(ori)
    angles = np.zeros([ori.shape[0], 3])
    angles[:, 0] = adjust_angle_array(np.arctan2(rm[:, 0, 1], rm[:, 1, 1]))
    angles[:, 1] = adjust_angle_array(np.arcsin(-rm[:, 2, 1]))
    angles[:, 2] = adjust_angle_array(np.arctan2(-rm[:, 2, 0], rm[:, 2, 2]))

    return angles
コード例 #21
0
    def load(self, data_path):
        super().load(data_path)
        self.velocities = self.targets[:, :2]
        with open(osp.join(data_path, 'info.json')) as f:
            info = json.load(f)
            rot_tango_to_body = info['align_tango_to_body']
            start_frame = info.get('start_frame', 0)

        with h5py.File(osp.join(data_path, 'data.hdf5')) as f:
            tango_ori = f['pose/tango_ori']
            body_ori_q = quaternion.from_float_array(
                tango_ori) * quaternion.from_float_array(
                    rot_tango_to_body).conj()
            body_heading = orientation_to_angles(body_ori_q)[start_frame:, 0]
        self.targets = np.stack(
            [np.sin(body_heading), np.cos(body_heading)], axis=-1)
コード例 #22
0
def align_3dvector_with_gravity_legacy(data,
                                       gravity,
                                       local_g_direction=np.array([0, 1, 0])):
    """
    Eliminate pitch and roll from a 3D vector by aligning gravity vector to local_g_direction.

    @:param data: N x 3 array
    @:param gravity: real gravity direction
    @:param local_g_direction: z direction before alignment
    @:return
    """
    assert data.ndim == 2, 'Expect 2 dimensional array input'
    assert data.shape[1] == 3, 'Expect Nx3 array input'
    assert data.shape[0] == gravity.shape[0], '{}, {}'.format(
        data.shape[0], gravity.shape[0])
    epsilon = 1e-03
    gravity_normalized = gravity / np.linalg.norm(gravity, axis=1)[:, None]
    output = np.copy(data)
    for i in range(data.shape[0]):
        # Be careful about two singular conditions where gravity[i] and local_g_direction are parallel.
        gd = np.dot(gravity_normalized[i], local_g_direction)
        if gd > 1. - epsilon:
            continue
        if gd < -1. + epsilon:
            output[i, [1, 2]] *= -1
            continue
        q = quaternion.from_float_array(
            quaternion_from_two_vectors(gravity[i], local_g_direction))
        output[i] = (q * quaternion.quaternion(1.0, *data[i]) * q.conj()).vec
    return output
コード例 #23
0
ファイル: util.py プロジェクト: frostburn/quaternion-julia
def generate_mesh_slices(width, height, depth, center_w, center_x, center_y, center_z, zoom, rotation_theta, rotation_phi, rotation_gamma, rotation_beta, offset_x, offset_y, depth_dither=1):
    ct, st = np.cos(rotation_theta), np.sin(rotation_theta)
    cp, sp = np.cos(rotation_phi), np.sin(rotation_phi)
    cg, sg = np.cos(rotation_gamma), np.sin(rotation_gamma)
    cb, sb = np.cos(rotation_beta), np.sin(rotation_beta)
    zoom = 2**-zoom

    x = np.arange(width, dtype='float64') + offset_x
    y = np.arange(height, dtype='float64') + offset_y
    z = np.arange(depth, dtype='float64')

    x, y = np.meshgrid(x, y)

    x = (2 * x - width) * zoom / height
    y = (2 * y - height) * zoom / height

    for z_ in z:
        z_ += np.random.rand(*x.shape) * depth_dither - 0.5*depth_dither
        z_ = (2 * z_ - depth) * zoom / depth

        # The screen coordinates have x as the real axis, so 'w' is a misnomer here.
        y_ = cb*y
        w_ = -sb*y
        x_, z_ = x*ct + z_*st, z_*ct - x*st
        x_, y_ = x_*cp + y*sp, y*cp - x_*sp
        y_, z_ = y_*cg + z_*sg, z_*cg - y_*sg

        # See above for the misnaming compared to the quaternion library.
        x_ += center_w
        y_ += center_x
        z_ += center_y
        w_ += center_z

        yield quaternion.from_float_array(np.stack((x_, y_, z_, w_), axis=-1))
コード例 #24
0
def quatdiff_in_euler(quat_curr, quat_des):
    """
        Compute difference between quaternions and return 
        Euler angles as difference
    """
    curr_mat = quaternion.as_rotation_matrix(
        quaternion.from_float_array(quat_curr))
    des_mat = quaternion.as_rotation_matrix(
        quaternion.from_float_array(quat_des))
    rel_mat = des_mat.T.dot(curr_mat)
    rel_quat = quaternion.from_rotation_matrix(rel_mat)
    vec = quaternion.as_float_array(rel_quat)[1:]
    if rel_quat.w < 0.0:
        vec = -vec

    return -des_mat.dot(vec)
コード例 #25
0
def load_gt_poses(gt_filename):
    indices = []
    Ts = []

    # Camera to world
    # Dirty left 2 right coordinate transform
    # https://github.com/theNded/MeshHashing/blob/master/src/io/config_manager.cc#L88
    T_l2r = np.eye(4)
    T_l2r[1, 1] = -1

    with open(gt_filename) as f:
        content = f.readlines()
        for line in content:
            data = np.array(list(map(float, line.strip().split(' '))))
            indices.append(int(data[0]))

            data = data[1:]

            q = data[3:][[3, 0, 1, 2]]
            q = quaternion.from_float_array(q)
            R = quaternion.as_rotation_matrix(q)

            t = data[:3]
            T = np.eye(4)

            T[0:3, 0:3] = R
            T[0:3, 3] = t

            Ts.append(T_l2r @ T @ np.linalg.inv(T_l2r))

    return indices, Ts
コード例 #26
0
ファイル: util.py プロジェクト: frostburn/quaternion-julia
def generate_imaginary_mesh_slices(width, height, depth, center_w, center_x, center_y, center_z, zoom, rotation_theta, rotation_phi, rotation_gamma, offset_x, offset_y, depth_dither=1):
    ct, st = np.cos(rotation_theta), np.sin(rotation_theta)
    cp, sp = np.cos(rotation_phi), np.sin(rotation_phi)
    cg, sg = np.cos(rotation_gamma), np.sin(rotation_gamma)
    zoom = 2**-zoom

    x = np.arange(width, dtype='float64') + offset_x
    y = np.arange(height, dtype='float64') + offset_y
    z = np.arange(depth, dtype='float64')

    x, y = np.meshgrid(x, y)

    x = (2 * x - width) * zoom / height
    y = (2 * y - height) * zoom / height
    w = 0*x + center_w

    for z_ in z:
        z_ += np.random.rand(*x.shape) * depth_dither - 0.5*depth_dither
        z_ = (2 * z_ - depth) * zoom / depth

        x_, z_ = x*ct + z_*st, z_*ct - x*st
        x_, y_ = x_*cp + y*sp, y*cp - x_*sp
        y_, z_ = y_*cg + z_*sg, z_*cg - y_*sg

        x_ += center_x
        y_ += center_y
        z_ += center_z

        yield quaternion.from_float_array(np.stack((w, x_, y_, z_), axis=-1))
コード例 #27
0
def solve_kinematic_motion_equation(
        time_span: Tuple[int, int],
        state: KinematicState,
        acceleration: np.ndarray,
        gravity_acceleration: np.ndarray,
        angular_velocity: np.ndarray) -> KinematicState:
    """
    Solve kinematic differential equation of motion.
    Describe motion in phase space that represent spatial position and angular position of body.
    'Body' is a rigid body (physical model).
    Phase space is:
        - position vector (cartesian coordinates),
        - velocity vector (cartesian coordinates),
        - quaternion that represent angular position according to inertial frame.
    NB: All vectors related to uniform acceleration motion must be in the same measurements units, e.g. x is [km, km/sec],
         acceleration and gravity_acceleration are [km/sec^2] .
    NB: angular_velocity must be in [rad, sec].
    :param time_span: time span.
    :param state: value of state space vector of body in phase space.
    :param acceleration: acceleration of body that caused by all non-gravitational forces in body frame.
    :param gravity_acceleration: acceleration of body that caused by gravitational force.
    :param angular_velocity: angular velocity of rotation of body frame respect to inertial frame, [rad, sec].
    :return: State  space vector at current time, i.e.
        - position vector (cartesian coordinates),
        - velocity vector (cartesian coordinates),
        - quaternion that represent angular position according to inertial frame.
    """
    acc = npq.rotate_vectors(state.quaternion, acceleration) + gravity_acceleration
    x0 = np.hstack((state.position, state.velocity))
    x_new = solve_ivp(lambda t, x: uniform_acceleration_motion_equation(x, acc), time_span, x0, method="RK45")
    q_new = solve_ivp(lambda t, q: uniform_angular_motion_equation(q, angular_velocity), time_span, state.quaternion.components, method="RK45")

    return KinematicState(x_new.y[:3, -1], x_new.y[3:, -1], npq.from_float_array(q_new.y[:, -1]).normalized())
コード例 #28
0
def MakeRotationQuaternion(angle, vec):
    a = np.cos(angle/2)
    b = np.sin(angle/2)
    axis = vec*b
    axis = np.append(a, axis)
    quat = quaternion.from_float_array(axis)
    return quat
コード例 #29
0
    def _system_equations(self, state, forces, moments):
        """Euler flat earth equations: linear momentum equations, angular momentum
        equations, angular kinematic equations, linear kinematic
        equations.

        Parameters
        ----------
        velocity, omega, attitude, forces, moments : all nd arrays of size (m,12)

        Returns
        -------
        dstate_dt : array_like, shape(9)
            Derivative with respect to time of the state vector.
            Current value of absolute acceleration and angular acceleration,
            both expressed in body axes, Euler angles derivatives and velocity
            with respect to Earth Axis.
            (du_dt, dv_dt, dw_dt, dp_dt, dq_dt, dr_dt, dphi_dt, dtheta_dt,
            dpsi_dt, dx_dt, dy_dt, dz_dt)
            (m/s² , m/s², m/s², rad/s², rad/s², rad/s², rad/s, rad/s, rad/s,
            m/s, m/s, m/s).

        References
        ----------
        .. [1] B. Etkin, Dynamics of flight, stability and control
        """

        state_dot = self.make_state_obj(N=state.N)

        # get inertia parameters
        mass = self.aircraft.mass
        I = self.aircraft.inertia
        invI = self.aircraft.inertia_inverse

        # get state values
        u, v, w = state.velocity.T
        p, q, r = state.omega.T
        # phi, theta, psi = attitude.T

        # Linear momentum equations
        Fx, Fy, Fz = forces.T
        state_dot.u = Fx / mass + r * v - q * w
        state_dot.v = Fy / mass - r * u + p * w
        state_dot.w = Fz / mass + q * u - p * v

        # Angular momentum equations
        state_dot.p, state_dot.q, state_dot.r = (
            invI @ (moments - np.cross(state.omega, (I @ state.omega.T).T)).T)

        # Angular Kinematic equations
        Qomega = npquat.from_float_array(
            np.hstack((np.zeros((state.N, 1)), state.omega)))
        state_dot.quaternion = 1 / 2 * state.quaternion * Qomega + 1 / 2 * (
            1 - np.norm(state.quaternion)) * state.quaternion / .1

        # Linear kinematic equations : rotate body velocity back to earth frame
        state_dot.position = change_basis(state.velocity,
                                          state.quaternion.conjugate())

        self.aircraft.state_dot = state_dot
        return state_dot.vec
コード例 #30
0
 def respawn_agent(self, position, rotation):
     """Respawns the agent at the position and rotation specified"""
     sim = self._robot.base.sim
     agent = sim.get_agent(0)
     new_agent_state = habitat_sim.AgentState()
     new_agent_state.position = position
     new_agent_state.rotation = quaternion.from_float_array(rotation)
     agent.set_state(new_agent_state)
コード例 #31
0
 def compute_attitude_splines(self):
     s_w = self.attitude_splines[0]
     s_x = self.attitude_splines[1]
     s_y = self.attitude_splines[2]
     s_z = self.attitude_splines[3]
     splines_coeffs = np.array([s_w, s_x, s_y, s_z]).T
     self.discretized_attitude = quaternion.from_float_array(splines_coeffs)
     return self.discretized_attitude
コード例 #32
0
def minimal_rotation(R, t, iterations=2):
    """Adjust frame so that there is no rotation about z' axis

    The output of this function is a frame that rotates the z axis onto the same z' axis as the
    input frame, but with minimal rotation about that axis.  This is done by pre-composing the input
    rotation with a rotation about the z axis through an angle gamma, where

        dgamma/dt = 2*(dR/dt * z * R.conjugate()).w

    This ensures that the angular velocity has no component along the z' axis.

    Note that this condition becomes easier to impose the closer the input rotation is to a
    minimally rotating frame, which means that repeated application of this function improves its
    accuracy.  By default, this function is iterated twice, though a few more iterations may be
    called for.

    Parameters
    ==========
    R: quaternion array
        Time series describing rotation
    t: float array
        Corresponding times at which R is measured
    iterations: int [defaults to 2]
        Repeat the minimization to refine the result

    """
    from scipy.interpolate import InterpolatedUnivariateSpline as spline
    if iterations == 0:
        return R
    R = quaternion.as_float_array(R)
    Rdot = np.empty_like(R)
    for i in range(4):
        Rdot[:, i] = spline(t, R[:, i]).derivative()(t)
    R = quaternion.from_float_array(R)
    Rdot = quaternion.from_float_array(Rdot)
    halfgammadot = quaternion.as_float_array(Rdot * quaternion.z * R.conjugate())[:, 0]
    halfgamma = spline(t, halfgammadot).antiderivative()(t)
    Rgamma = np.exp(quaternion.z * halfgamma)
    return minimal_rotation(R * Rgamma, t, iterations=iterations-1)
コード例 #33
0
def integrate_angular_velocity(Omega, t0, t1, R0=None, tolerance=1e-12):
    """Compute frame with given angular velocity

    Parameters
    ==========
    Omega: tuple or callable
        Angular velocity from which to compute frame.  Can be
          1) a 2-tuple of float arrays (t, v) giving the angular velocity vector at a series of times,
          2) a function of time that returns the 3-vector angular velocity, or
          3) a function of time and orientation (t, R) that returns the 3-vector angular velocity
        In case 1, the angular velocity will be interpolated to the required times.  Note that accuracy
        is poor in case 1.
    t0: float
        Initial time
    t1: float
        Final time
    R0: quaternion, optional
        Initial frame orientation.  Defaults to 1 (the identity orientation).
    tolerance: float, optional
        Absolute tolerance used in integration.  Defaults to 1e-12.

    Returns
    =======
    t: float array
    R: quaternion array

    """
    import warnings
    from scipy.integrate import ode

    if R0 is None:
        R0 = quaternion.one

    input_is_tabulated = False

    try:
        t_Omega, v = Omega
        from scipy.interpolate import InterpolatedUnivariateSpline
        Omega_x = InterpolatedUnivariateSpline(t_Omega, v[:, 0])
        Omega_y = InterpolatedUnivariateSpline(t_Omega, v[:, 1])
        Omega_z = InterpolatedUnivariateSpline(t_Omega, v[:, 2])
        def Omega_func(t, R):
            return [Omega_x(t), Omega_y(t), Omega_z(t)]
        Omega_func(t0, R0)
        input_is_tabulated = True
    except (TypeError, ValueError):
        def Omega_func(t, R):
            return Omega(t, R)
        try:
            Omega_func(t0, R0)
        except TypeError:
            def Omega_func(t, R):
                return Omega(t)
            Omega_func(t0, R0)

    def RHS(t, y):
        R = quaternion.quaternion(*y)
        return (0.5 * quaternion.quaternion(0.0, *Omega_func(t, R)) * R).components

    y0 = R0.components

    if input_is_tabulated:
        from scipy.integrate import solve_ivp
        t = t_Omega
        t_span = [t_Omega[0], t_Omega[-1]]
        solution = solve_ivp(RHS, t_span, y0, t_eval=t_Omega, atol=tolerance, rtol=100*np.finfo(float).eps)
        R = quaternion.from_float_array(solution.y.T)
    else:
        solver = ode(RHS)
        solver.set_initial_value(y0, t0)
        solver.set_integrator('dop853', nsteps=1, atol=tolerance, rtol=0.0)
        solver._integrator.iwork[2] = -1  # suppress Fortran-printed warning
        t = appending_array((int(t1-t0),))
        t.append(solver.t)
        R = appending_array((int(t1-t0), 4))
        R.append(solver.y)
        warnings.filterwarnings("ignore", category=UserWarning)
        t_last = solver.t
        while solver.t < t1:
            solver.integrate(t1, step=True)
            if solver.t > t_last:
                t.append(solver.t)
                R.append(solver.y)
                t_last = solver.t
        warnings.resetwarnings()
        t = t.a
        R = quaternion.as_quat_array(R.a)

    return t, R