def test_orbit_creation_using_frame_obj(attractor, frame, obstime): vel = [0, 2, 0] * u.km / u.s cartdiff = CartesianDifferential(*vel) pos = [30000, 0, 0] * u.km cartrep = CartesianRepresentation(*pos, differentials=cartdiff) coord = frame(cartrep, obstime=obstime) o = Orbit.from_coords(attractor, coord) inertial_frame_at_body_centre = get_frame(attractor, Planes.EARTH_EQUATOR, obstime=coord.obstime) coord_transformed_to_irf = coord.transform_to( inertial_frame_at_body_centre) pos_transformed_to_irf = coord_transformed_to_irf.cartesian.xyz vel_transformed_to_irf = coord_transformed_to_irf.cartesian.differentials[ "s"].d_xyz assert_quantity_allclose(o.r, pos_transformed_to_irf, atol=1e-5 * u.km) assert_quantity_allclose(o.v, vel_transformed_to_irf, atol=1e-5 * u.km / u.s)
def frame(self): """Reference frame of the orbit. .. versionadded:: 0.11.0 """ if self._frame is None: self._frame = get_frame(self.attractor, self._plane, self.epoch) return self._frame
def from_coords(cls, attractor, coord, plane=Planes.EARTH_EQUATOR): """Creates an `Orbit` from an attractor and astropy `SkyCoord` or `BaseCoordinateFrame` instance. This method accepts position and velocity in any reference frame unlike `Orbit.from_vector` which can accept inputs in only inertial reference frame centred at attractor. Also note that the frame information is lost after creation of the orbit and only the inertial reference frame at body centre will be used for all purposes. Parameters ---------- attractor: Body Main attractor coord: astropy.coordinates.SkyCoord or BaseCoordinateFrame Position and velocity vectors in any reference frame. Note that coord must have a representation and its differential with respect to time. plane : ~poliastro.frames.Planes, optional Final orbit plane, default to Earth Equator. """ if "s" not in coord.cartesian.differentials: raise ValueError( "Coordinate instance doesn't have a differential with respect to time" ) if coord.size != 1: raise ValueError( "Coordinate instance must represents exactly 1 position, found: %d" % coord.size) # Reshape coordinate to 0 dimension if it is not already dimensionless. coord = coord.reshape(()) # Get an inertial reference frame parallel to ICRS and centered at # attractor inertial_frame_at_body_centre = get_frame(attractor, plane, coord.obstime) if not coord.is_equivalent_frame(inertial_frame_at_body_centre): coord_in_irf = coord.transform_to(inertial_frame_at_body_centre) else: coord_in_irf = coord pos = coord_in_irf.cartesian.xyz vel = coord_in_irf.cartesian.differentials["s"].d_xyz return cls.from_vectors(attractor, pos, vel, epoch=coord.obstime, plane=plane)
def change_attractor(self, new_attractor, force=False): """Changes orbit attractor. Only changes from attractor to parent or the other way around are allowed. Parameters ---------- new_attractor: poliastro.bodies.Body Desired new attractor. force: boolean If `True`, changes attractor even if physically has no-sense. Returns ------- ss: poliastro.twobody.orbit.Orbit Orbit with new attractor """ if self.attractor == new_attractor: return self elif self.attractor == new_attractor.parent: # "Sun -> Earth" r_soi = laplace_radius(new_attractor) distance = norm( self.r - get_body_barycentric(new_attractor.name, self.epoch).xyz) elif self.attractor.parent == new_attractor: # "Earth -> Sun" r_soi = laplace_radius(self.attractor) distance = norm(self.r) else: raise ValueError("Cannot change to unrelated attractor") if distance > r_soi and not force: raise ValueError( "Orbit is out of new attractor's SOI. If required, use 'force=True'." ) elif self.ecc < 1.0 and not force: raise ValueError( "Orbit will never leave the SOI of its current attractor") else: warn("Leaving the SOI of the current attractor", PatchedConicsWarning) new_frame = get_frame(new_attractor, self.plane, obstime=self.epoch) coords = self.frame.realize_frame( self.represent_as(CartesianRepresentation)) ss = Orbit.from_coords(new_attractor, coords.transform_to(new_frame)) return ss
def from_coords(cls, attractor, coord, plane=Planes.EARTH_EQUATOR): """Creates an `Orbit` from an attractor and astropy `SkyCoord` or `BaseCoordinateFrame` instance. This method accepts position and velocity in any reference frame unlike `Orbit.from_vector` which can accept inputs in only inertial reference frame centred at attractor. Also note that the frame information is lost after creation of the orbit and only the inertial reference frame at body centre will be used for all purposes. Parameters ---------- attractor: Body Main attractor coord: astropy.coordinates.SkyCoord or BaseCoordinateFrame Position and velocity vectors in any reference frame. Note that coord must have a representation and its differential with respect to time. plane : ~poliastro.frames.Planes, optional Final orbit plane, default to Earth Equator. """ if "s" not in coord.cartesian.differentials: raise ValueError( "Coordinate instance doesn't have a differential with respect to time" ) if coord.size != 1: raise ValueError( "Coordinate instance must represents exactly 1 position, found: %d" % coord.size ) # Reshape coordinate to 0 dimension if it is not already dimensionless. coord = coord.reshape(()) # Get an inertial reference frame parallel to ICRS and centered at # attractor inertial_frame_at_body_centre = get_frame(attractor, plane, coord.obstime) if not coord.is_equivalent_frame(inertial_frame_at_body_centre): coord_in_irf = coord.transform_to(inertial_frame_at_body_centre) else: coord_in_irf = coord pos = coord_in_irf.cartesian.xyz vel = coord_in_irf.cartesian.differentials["s"].d_xyz return cls.from_vectors(attractor, pos, vel, epoch=coord.obstime, plane=plane)
def test_orbit_creation_using_skycoord(attractor): vel = [0, 2, 0] * u.km / u.s cartdiff = CartesianDifferential(*vel) pos = [30000, 0, 0] * u.km cartrep = CartesianRepresentation(*pos, differentials=cartdiff) coord = SkyCoord(cartrep, frame="icrs") o = Orbit.from_coords(attractor, coord) inertial_frame_at_body_centre = get_frame( attractor, Planes.EARTH_EQUATOR, obstime=coord.obstime ) coord_transformed_to_irf = coord.transform_to(inertial_frame_at_body_centre) pos_transformed_to_irf = coord_transformed_to_irf.cartesian.xyz vel_transformed_to_irf = coord_transformed_to_irf.cartesian.differentials["s"].d_xyz assert (o.r == pos_transformed_to_irf).all() assert (o.v == vel_transformed_to_irf).all()
def test_orbit_creation_using_frame_obj(attractor, frame, obstime): vel = [0, 2, 0] * u.km / u.s cartdiff = CartesianDifferential(*vel) pos = [30000, 0, 0] * u.km cartrep = CartesianRepresentation(*pos, differentials=cartdiff) coord = frame(cartrep, obstime=obstime) o = Orbit.from_coords(attractor, coord) inertial_frame_at_body_centre = get_frame( attractor, Planes.EARTH_EQUATOR, obstime=coord.obstime ) coord_transformed_to_irf = coord.transform_to(inertial_frame_at_body_centre) pos_transformed_to_irf = coord_transformed_to_irf.cartesian.xyz vel_transformed_to_irf = coord_transformed_to_irf.cartesian.differentials["s"].d_xyz assert_quantity_allclose(o.r, pos_transformed_to_irf, atol=1e-5 * u.km) assert_quantity_allclose(o.v, vel_transformed_to_irf, atol=1e-5 * u.km / u.s)