def paperclip_shape_rotate_midsegment(h, params): """ This move rotates the midsegment of h, keeping the other segments fixed. Because we constrain midsegment to be aligned with the x axis, this rotation is implemented by rotating the other segments. Crucially, we want it to look like only the midsegment is rotated; so we rotate the viewpoint to do that. """ hp = h.copy() # if the object has only a midsegment if hp.joint_count == 2: return hp, 1.0, 1.0 # get random rotation axis and angle theta = np.random.rand() * 360.0 - 180.0 phi = np.random.rand() * 180.0 rotation_axis = geom_3d.spherical_to_cartesian((1.0, theta, phi)) kappa = 1 / (params['ROTATE_MIDSEGMENT_VARIANCE'] * np.pi**2 / 180**2) rotation_angle = np.random.vonmises(0.0, kappa) * 180.0 / np.pi # rotate midsegment try: # we might not be able to rotate midsegment by rotation_angle around rotation_axis hp.rotate_midsegment(rotation_axis, rotation_angle) except ValueError: return hp, 1.0, 1.0 # rotate each viewpoint to correct for the rotation of the joints (we want only the midsegment to change how it # looks) for i in range(len(hp.viewpoint)): vp_cartesian = geom_3d.spherical_to_cartesian(hp.viewpoint[i]) new_vp_cartesian = geom_3d.rotate_axis_angle(vp_cartesian, rotation_axis, -rotation_angle) hp.viewpoint[i] = geom_3d.cartesian_to_spherical(new_vp_cartesian) return hp, 1.0, 1.0
def test_change_viewpoint(self): vp1 = np.array((1.0, 0.0, 0.0)) vp2 = np.array((2.0, 150.0, 0.0)) h = hyp.I3DHypothesis(forward_model=None, viewpoint=[vp1, vp2], params=None) for i in range(1000): hp, p0, p1 = change_viewpoint( h, {'CHANGE_VIEWPOINT_VARIANCE': np.square(5.0 / 180.0 * np.pi)}) self.assertAlmostEqual(p0, 1.0) self.assertAlmostEqual(p1, 1.0) vp = hp.viewpoint[0] self.assertAlmostEqual(vp[0], 1.0) # because the variance is 1.0, we would expect the angle between vectors to be small self.assertTrue( geom_3d.angle_between_vectors( geom_3d.spherical_to_cartesian(vp), geom_3d.spherical_to_cartesian(vp1)) < 20.0) vp = hp.viewpoint[1] self.assertAlmostEqual(vp[0], 2.0) self.assertTrue( geom_3d.angle_between_vectors( geom_3d.spherical_to_cartesian(vp), geom_3d.spherical_to_cartesian(vp2)) < 20.0)
def test_change_viewpoint(self): vp1 = np.array((1.0, 0.0, 0.0)) vp2 = np.array((2.0, 150.0, 0.0)) h = hyp.I3DHypothesis(forward_model=None, viewpoint=[vp1, vp2], params=None) for i in range(1000): hp, p0, p1 = change_viewpoint(h, {'CHANGE_VIEWPOINT_VARIANCE': np.square(5.0 / 180.0 * np.pi)}) self.assertAlmostEqual(p0, 1.0) self.assertAlmostEqual(p1, 1.0) vp = hp.viewpoint[0] self.assertAlmostEqual(vp[0], 1.0) # because the variance is 1.0, we would expect the angle between vectors to be small self.assertTrue(geom_3d.angle_between_vectors(geom_3d.spherical_to_cartesian(vp), geom_3d.spherical_to_cartesian(vp1)) < 20.0) vp = hp.viewpoint[1] self.assertAlmostEqual(vp[0], 2.0) self.assertTrue(geom_3d.angle_between_vectors(geom_3d.spherical_to_cartesian(vp), geom_3d.spherical_to_cartesian(vp2)) < 20.0)
def _get_random_vector_along(z_vector, min_angle=30.0, max_angle=180.0): """ Get a random vector that makes more than min_angles and less than max_angles degrees with the `z_vector`. This method is used by ``paperclip_shape_add_remove_joint`` move. Note that the angle between the returned vector and the -z_vector (NEGATIVE z_vector, not the z_vector) will be in (min_angle, max_angle). If we add such a vector to z_vector, the angle between z_vector and the new vector will be in (min_angle, max_angle). """ if max_angle < min_angle: raise ValueError("Maximum angle cannot be smaller than minimum angle.") max_phi = 180.0 - min_angle min_phi = 180.0 - max_angle phi = min_phi + (np.random.rand() * (max_phi - min_phi)) theta = np.random.rand() * 360.0 coords = geom_3d.spherical_to_cartesian((1.0, theta, phi)) v = geom_3d.rotate_vector_by_vector(coords, old_z=np.array([0., 0., 1.]), new_z=z_vector) return v