Class: Zodiacly::HorizonsClient

Inherits:
Object
  • Object
show all
Includes:
HTTParty
Defined in:
lib/zodiacly/horizons_client.rb

Overview

Minimal wrapper for NASA/JPL Horizons API. Docs: https://ssd-api.jpl.nasa.gov/doc/horizons.html

Constant Summary collapse

DEFAULTS =
{
  "format" => "json",
  "MAKE_EPHEM" => "'YES'",
  "OBJ_DATA" => "'NO'"
}.freeze

Instance Method Summary collapse

Instance Method Details

#fetch(params) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/zodiacly/horizons_client.rb', line 20

def fetch(params)
  res = self.class.get("/horizons.api", query: DEFAULTS.merge(params))
  unless res.success?
    raise Zodiacly::Error, "Horizons HTTP #{res.code}: #{res.body.to_s[0..300]}"
  end

  json = res.parsed_response
  if json.is_a?(Hash) && json["error"]
    raise Zodiacly::Error, "Horizons error: #{json["error"]}"
  end

  json
end

#vectors(command:, center:, time_utc:) ⇒ Object

Fetch vectors (position+velocity) in the ecliptic plane for a single instant.

Returns the full JSON payload; the ephemeris text is inside json.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/zodiacly/horizons_client.rb', line 37

def vectors(command:, center:, time_utc:)
  # Horizons is picky about timestamp formats. Using START/STOP with a short window
  # avoids TLIST parsing issues with ISO8601 "T...Z".
  start_t = ensure_utc_horizons(time_utc)
  stop_t  = ensure_utc_horizons(Time.parse(time_utc.to_s).utc + 60) # +60s

  fetch(
    "COMMAND" => "'#{command}'",
    "CENTER" => "'#{center}'",
    "EPHEM_TYPE" => "'VECTORS'",
    "REF_PLANE" => "'ECLIPTIC'",
    "CSV_FORMAT" => "'YES'",
    "VEC_TABLE" => "'2'",
    "START_TIME" => "'#{start_t}'",
    "STOP_TIME" => "'#{stop_t}'",
    "STEP_SIZE" => "'1 m'"
  )
end