def test_compute_missing_body_laplace_radius_raises_error(missing_body): with pytest.raises(RuntimeError) as excinfo: laplace_radius(missing_body) assert ( "To compute the semimajor axis for Moon and Pluto use the JPL ephemeris" in excinfo.exconly() )
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 : bool 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) barycentric_position = get_body_barycentric(new_attractor.name, self.epoch) # Transforming new_attractor's frame into frame of attractor new_attractor_r = ( ICRS(barycentric_position) .transform_to(self.get_frame()) .represent_as(CartesianRepresentation) .xyz ) distance = norm(self.r - new_attractor_r) 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, stacklevel=2, ) new_frame = get_frame(new_attractor, self.plane, obstime=self.epoch) coords = self.get_frame().realize_frame( self.represent_as(CartesianRepresentation, CartesianDifferential) ) ss = Orbit.from_coords(new_attractor, coords.transform_to(new_frame)) return ss
def test_laplace_radius(body, expected_r_SOI): if expected_r_SOI is not None: expected_r_SOI = expected_r_SOI * u.m r_SOI = laplace_radius(body) assert_quantity_allclose(r_SOI, expected_r_SOI, rtol=1e-1)
def change_attractor(self, new_attractor): """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. 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: raise ValueError("Orbit is out of new attractor's SOI") elif self.ecc < 1.0: 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 _calculate_system_laplace_radii(self): body_soi = {} for body in self.body_list: if body.name == "Sun": pass else: try: soi_rad = laplace_radius(body) body_soi[body.name] = soi_rad except KeyError: pass # a = get_mean_elements(body).a <- semimajor axis # r_SOI = a * (body.k / body.parent.k) ** (2 / 5) # todo: calculate laplace radius from mass ratio and semimajor axis # for bodies where get_mean_elements fails return body_soi
def test_laplace_radius_given_a(): parent = Body(None, 1 * u.km**3 / u.s**2, "Parent") body = Body(parent, 1 * u.km**3 / u.s**2, "Body") r_SOI = laplace_radius(body, 1 * u.km) assert r_SOI == 1 * u.km
def test_laplace_radius(body, expected_r_SOI): r_SOI = laplace_radius(body) assert_quantity_allclose(r_SOI, expected_r_SOI, rtol=1e-1)
def test_laplace_radius_given_a(): parent = Body(None, 1 * u.km ** 3 / u.s ** 2, "Parent") body = Body(parent, 1 * u.km ** 3 / u.s ** 2, "Body") r_SOI = laplace_radius(body, 1 * u.km) assert r_SOI == 1 * u.km