open-space-toolkit-astrodynamics 16.0.0__py39-none-manylinux2014_x86_64.whl → 16.2.0__py39-none-manylinux2014_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: open-space-toolkit-astrodynamics
3
- Version: 16.0.0
3
+ Version: 16.2.0
4
4
  Summary: Orbit, attitude, access.
5
5
  Author: Open Space Collective
6
6
  Author-email: contact@open-space-collective.org
@@ -1,7 +1,7 @@
1
1
  ostk/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
2
- ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-39-x86_64-linux-gnu.so,sha256=hYcv26NaK9AHaPkJh3rLogej1VLlxftOHxQ_pnvEXAE,2836704
2
+ ostk/astrodynamics/OpenSpaceToolkitAstrodynamicsPy.cpython-39-x86_64-linux-gnu.so,sha256=u8ODW-L9UeT6TPkLpmmrlGfdt0tcb1m_xcT03TNDswA,2848992
3
3
  ostk/astrodynamics/__init__.py,sha256=3gWyqFIbhAfcdeMhmfBPQPlPQTmaOzm-6flkJe745Zk,251
4
- ostk/astrodynamics/__init__.pyi,sha256=pW_h-XAUd7C6EssxuLWAAj5NAGHrkXE_uZCDatMjdec,32193
4
+ ostk/astrodynamics/__init__.pyi,sha256=1oup4Ap55geh52gLbRxTDrBnHpx4Rbg0PwW-l6xax0k,32193
5
5
  ostk/astrodynamics/access.pyi,sha256=t2CF0TU6_6ow_rkV_I4rVKap7ZIdC4jYKL3WkTDHRXg,25157
6
6
  ostk/astrodynamics/converters.py,sha256=luPh30qMp9bzEkN7hUccmxlLf7zRp_AzqmBe8IUjPhU,3314
7
7
  ostk/astrodynamics/converters.pyi,sha256=HrZFyizkc6Hv_K38ZKZ80fX_bAxd6keA_NFWNQygvbs,1745
@@ -11,23 +11,23 @@ ostk/astrodynamics/dynamics.pyi,sha256=gZ95KoGex4SB-1z6yMrngkZN1Ir9X6bEmrZgdLxq1
11
11
  ostk/astrodynamics/estimator.pyi,sha256=MnahWzp8aACxrNKWlYRsgQr5zpBxogNr-yPm7hJob5k,14000
12
12
  ostk/astrodynamics/event_condition.pyi,sha256=2c_1Sq7tkYKeAA_aRWBi43KDQXXxu6EMSmUpEWz_Fa4,45814
13
13
  ostk/astrodynamics/guidance_law.pyi,sha256=rVmbpV2Y5FsIXejaInxINS67nVHmTIxVEkhaDIn17SA,12171
14
- ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.16,sha256=K8Pnig_cKlxFlypbFxHQAIRtFp1_3pI_9ezyr5jjOR4,122033672
14
+ ostk/astrodynamics/libopen-space-toolkit-astrodynamics.so.16,sha256=z7f9nP2oT2d_F9qbdFBQ4wnH5xBhQirZRBtnxgvkmFg,122110960
15
15
  ostk/astrodynamics/solver.pyi,sha256=sPqyYPXBfFGC24dzzYyFyt01VfMAlWQ5_gh_RpeaBFk,17734
16
16
  ostk/astrodynamics/utilities.py,sha256=y8mr3M46J5z-GhS1oIEnuEJA6otwcyJ9YDhvn_5JxHM,6976
17
- ostk/astrodynamics/viewer.py,sha256=-Q4migLFOB9dNzs6TRPIXHNewyV5udsDSpcSma0kv8A,16376
17
+ ostk/astrodynamics/viewer.py,sha256=PLznIOEArRlx-pfMHpGoszNRf2F8mf2SHe8CGvZrVnw,16740
18
18
  ostk/astrodynamics/conjunction/__init__.pyi,sha256=HFvWl8bCmrq3cBkUh5X5RGIh8webmVGxaZdpsz3WN-E,79
19
19
  ostk/astrodynamics/conjunction/message/__init__.pyi,sha256=5H__sg_QUx7ybf9jtVWvXzrUHeK3ECotfhddAdHjJUc,75
20
20
  ostk/astrodynamics/conjunction/message/ccsds.pyi,sha256=1Peto19hRqlD7KHf1cyLP3CT4OAKzwtemqvO6_4FZ0g,28162
21
21
  ostk/astrodynamics/data/__init__.pyi,sha256=4l_mfVbnU_L7wImwgTCe8fVI81gK_tUmd0z7BY9lLi8,81
22
22
  ostk/astrodynamics/data/provider.pyi,sha256=O4Lg9FBq9itufgATnic5SMg90pn8vJJJMUdNcWP72NI,1492
23
- ostk/astrodynamics/flight/__init__.pyi,sha256=lcObS0XM7GvdJ_Oe-1GGQkSg3y_MYh-n5i5AwH6eREQ,21204
23
+ ostk/astrodynamics/flight/__init__.pyi,sha256=JEMXdq_Fkfc2GGMFZL3pta-Juu5sj9v5t3A_Tdc9SW8,22248
24
24
  ostk/astrodynamics/flight/system.pyi,sha256=WVxy6Oe4q3C81c0AOxSwAmnwUHcpXO7JCEvESjs2g4A,10508
25
25
  ostk/astrodynamics/flight/profile/__init__.pyi,sha256=WBTG17V59UwD-X1r6TOrXT_rA3WjKY-2ML1cWfji_4g,3688
26
26
  ostk/astrodynamics/flight/profile/model.pyi,sha256=g5Uy2ZLxImuETrMP4jqXr5FXl2dGAoKuNgzOH07EdBo,6807
27
27
  ostk/astrodynamics/pytrajectory/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
28
28
  ostk/astrodynamics/pytrajectory/__init__.pyi,sha256=QWrGyQNiICBEI3pKku2wJYdu-SQCBKXjJ_93XTEgkP8,79
29
- ostk/astrodynamics/pytrajectory/pystate.py,sha256=c0wR5OJn070ImwVJtW25XhEW7d2_8jkAd168Fo9u6K8,7959
30
- ostk/astrodynamics/pytrajectory/pystate.pyi,sha256=dbYwAoyZo9ZgLjms8nH9s_OhxlmxMLLILR-wXGqphbw,3320
29
+ ostk/astrodynamics/pytrajectory/pystate.py,sha256=HbWtj1_FXGXTuvSu52ewMaO3ahwLBLStyJ4e5xqL-jw,8415
30
+ ostk/astrodynamics/pytrajectory/pystate.pyi,sha256=ljE5Q9Y56dpWgxY75ji9ibrTWIJTXeO29_foHBPxGs4,3413
31
31
  ostk/astrodynamics/test/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
32
32
  ostk/astrodynamics/test/conftest.py,sha256=stmQOt7UXjBlXKJzNN6RkS2miv1xXSOX-YNpFhaHTqI,2771
33
33
  ostk/astrodynamics/test/test_access.py,sha256=MCBsUPtuVm7NgHZR0z0DpWnPZ_qBu4aRhLI2PnRNUYs,3940
@@ -69,7 +69,7 @@ ostk/astrodynamics/test/event_condition/test_logical_condition.py,sha256=09h5TYW
69
69
  ostk/astrodynamics/test/event_condition/test_real_condition.py,sha256=tle6HVzMFMIIkfRY7CuaA0mPtw3riJBG_JQkc1L0dpk,1374
70
70
  ostk/astrodynamics/test/flight/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
71
71
  ostk/astrodynamics/test/flight/test_maneuver.py,sha256=HonAvD9qtax72lizoDLR6ELI-poC3LWk_umg-WYygYA,5388
72
- ostk/astrodynamics/test/flight/test_profile.py,sha256=V1IekQv7Mju3fMlQZuY4vc1LPNVHsPMtjpT9zI2L_DE,7865
72
+ ostk/astrodynamics/test/flight/test_profile.py,sha256=ialv-BdeGq9WX_G8l9sva-C0TXfenA8ZOXEA_aiVtuA,8051
73
73
  ostk/astrodynamics/test/flight/test_system.py,sha256=5kJCULHdpkwAC7i6xLV7vdJnGfOdrOuhi0G22p_L160,1224
74
74
  ostk/astrodynamics/test/flight/system/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
75
75
  ostk/astrodynamics/test/flight/system/test_propulsion_system.py,sha256=SoxOt-fjHvs_86f6Xb3jAsHDOShJ6Puz7eO5wrqibaM,1835
@@ -89,7 +89,7 @@ ostk/astrodynamics/test/trajectory/test_orbit.py,sha256=vp7gDMtjO7nqERe0yq1OQZ0p
89
89
  ostk/astrodynamics/test/trajectory/test_propagator.py,sha256=ALjMvzndO9r6dVVXllk0iqu61tEoqu2j25MtzEitDIQ,14076
90
90
  ostk/astrodynamics/test/trajectory/test_segment.py,sha256=aXdF5CpNLwN_hKRU5sG3ID3hJR-NZ1_kgtNA-xHMBkM,12223
91
91
  ostk/astrodynamics/test/trajectory/test_sequence.py,sha256=4piYpMZ9C_eCXxaOcdz2We67wZxhsNBnETgKwvq6dl0,15083
92
- ostk/astrodynamics/test/trajectory/test_state.py,sha256=th1BvTIhmgsPPFTbVnpR3URvqYFrf0oyluJyoPP7TPI,17135
92
+ ostk/astrodynamics/test/trajectory/test_state.py,sha256=JO-SnUCRZ6sfVNwB5soT5c1f8c5DXuFN5lHZkiiTcYc,18119
93
93
  ostk/astrodynamics/test/trajectory/test_state_builder.py,sha256=LpCCYdCaLu_D2npm9wgA2sMlcekrtbRqP-afe5IE5L4,4871
94
94
  ostk/astrodynamics/test/trajectory/orbit/__init__.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
95
95
  ostk/astrodynamics/test/trajectory/orbit/test_model.py,sha256=epnVn2PwdQkUDZ1msqBRO5nEZIOUBIq-IfK3IlNPijE,21
@@ -119,7 +119,7 @@ ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_attitude_quatern
119
119
  ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_acceleration.py,sha256=1p37_FYN85d9SrOqO3iCkNecovJJayhnFeZ4QCOw2ao,3528
120
120
  ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_position.py,sha256=XvHdk1KjacTwtkgx2jUAc9I9N3nvjPDv03FAanpv8jQ,2702
121
121
  ostk/astrodynamics/test/trajectory/state/coordinate_subset/test_cartesian_velocity.py,sha256=-kd5TZO5TICihbkqDTew2i_tDpggdpe3Yf23046FATM,3057
122
- ostk/astrodynamics/trajectory/__init__.pyi,sha256=dxNnpdnDid4GRXiBs_Lr6WNn1L7jx42pwu_eq4Nk9Ss,76183
122
+ ostk/astrodynamics/trajectory/__init__.pyi,sha256=uC9WD4s1XZpnJy8GhSTap818vHPMgMNieusLaxlzh4U,76264
123
123
  ostk/astrodynamics/trajectory/orbit/__init__.pyi,sha256=wbuRK7Yp_NYBr3ta5-NpnJYMX4baUl7yIlUWhaRlR4o,12899
124
124
  ostk/astrodynamics/trajectory/orbit/message/__init__.pyi,sha256=-GNBlYPrsjelhKxWorYQYhIWzFsibiIQNZvMXjhRpfM,77
125
125
  ostk/astrodynamics/trajectory/orbit/message/spacex.pyi,sha256=fnUVJGWlSPo8AmLVuu08LubsAuVGo-gFaT86yd4f4CI,10558
@@ -129,8 +129,8 @@ ostk/astrodynamics/trajectory/orbit/model/kepler.pyi,sha256=OZMznHuU7e6m1rfqtOgX
129
129
  ostk/astrodynamics/trajectory/orbit/model/sgp4.pyi,sha256=OhFzoPPQHlYy7m3LiZ8TXF89M4uBTfNk6tGsBEp0sjI,14235
130
130
  ostk/astrodynamics/trajectory/state/__init__.pyi,sha256=bq__Fii35czVrTeNxc9eQVjXdqwbbQxUdNQWK3vLrMo,17649
131
131
  ostk/astrodynamics/trajectory/state/coordinate_subset.pyi,sha256=kYMfMwEjCqO1NepMYFT4QS6kIPBkVL6sGCLeLbogcMw,10176
132
- open_space_toolkit_astrodynamics-16.0.0.dist-info/METADATA,sha256=QZzoZmh6ksKVxnXob_SRtfRykp2hf20s2fLMk70AXtk,1913
133
- open_space_toolkit_astrodynamics-16.0.0.dist-info/WHEEL,sha256=Lf7t-kOlAeOyExg08NFEPC9xn1Q2CLFgwDRGfj0NsM4,109
134
- open_space_toolkit_astrodynamics-16.0.0.dist-info/top_level.txt,sha256=zOR18699uDYnafgarhL8WU_LmTZY_5NVqutv-flp_x4,5
135
- open_space_toolkit_astrodynamics-16.0.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
136
- open_space_toolkit_astrodynamics-16.0.0.dist-info/RECORD,,
132
+ open_space_toolkit_astrodynamics-16.2.0.dist-info/METADATA,sha256=Xna6Sf7jCN-myVL7NvFMecPLgJTxbg5Akf9wfjZyyhI,1913
133
+ open_space_toolkit_astrodynamics-16.2.0.dist-info/WHEEL,sha256=Lf7t-kOlAeOyExg08NFEPC9xn1Q2CLFgwDRGfj0NsM4,109
134
+ open_space_toolkit_astrodynamics-16.2.0.dist-info/top_level.txt,sha256=zOR18699uDYnafgarhL8WU_LmTZY_5NVqutv-flp_x4,5
135
+ open_space_toolkit_astrodynamics-16.2.0.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
136
+ open_space_toolkit_astrodynamics-16.2.0.dist-info/RECORD,,
@@ -14,8 +14,8 @@ from ostk import mathematics as OpenSpaceToolkitMathematicsPy
14
14
  from ostk.mathematics import curve_fitting
15
15
  from ostk.mathematics import geometry
16
16
  from ostk.mathematics import object
17
- import ostk.physics
18
17
  from ostk import physics as OpenSpaceToolkitPhysicsPy
18
+ import ostk.physics
19
19
  from ostk.physics import Environment
20
20
  from ostk.physics import Manager
21
21
  from ostk.physics import Unit
@@ -186,7 +186,7 @@ class Profile:
186
186
  @property
187
187
  def orientation_generator(self) -> typing.Callable[[ostk.astrodynamics.trajectory.State], numpy.ndarray[numpy.float64[3, 1]]]:
188
188
  """
189
- The orientation generator of the target
189
+ The orientation generator of the target.
190
190
  """
191
191
  class OrientationProfileTarget(Profile.Target):
192
192
  """
@@ -207,7 +207,7 @@ class Profile:
207
207
  @property
208
208
  def orientation_profile(self) -> list[tuple[ostk.physics.time.Instant, numpy.ndarray[numpy.float64[3, 1]]]]:
209
209
  """
210
- The orientation profile of the target
210
+ The orientation profile of the target.
211
211
  """
212
212
  class Target:
213
213
  """
@@ -254,6 +254,10 @@ class Profile:
254
254
 
255
255
  Trajectory : Trajectory
256
256
 
257
+ TargetPosition : Target position
258
+
259
+ TargetVelocity : Target velocity
260
+
257
261
  Sun : Sun
258
262
 
259
263
  Moon : Moon
@@ -268,14 +272,16 @@ class Profile:
268
272
  """
269
273
  GeocentricNadir: typing.ClassVar[Profile.TargetType] # value = <TargetType.GeocentricNadir: 0>
270
274
  GeodeticNadir: typing.ClassVar[Profile.TargetType] # value = <TargetType.GeodeticNadir: 1>
271
- Moon: typing.ClassVar[Profile.TargetType] # value = <TargetType.Moon: 4>
272
- OrbitalMomentum: typing.ClassVar[Profile.TargetType] # value = <TargetType.OrbitalMomentum: 7>
273
- OrientationProfile: typing.ClassVar[Profile.TargetType] # value = <TargetType.OrientationProfile: 8>
274
- Sun: typing.ClassVar[Profile.TargetType] # value = <TargetType.Sun: 3>
275
+ Moon: typing.ClassVar[Profile.TargetType] # value = <TargetType.Moon: 6>
276
+ OrbitalMomentum: typing.ClassVar[Profile.TargetType] # value = <TargetType.OrbitalMomentum: 9>
277
+ OrientationProfile: typing.ClassVar[Profile.TargetType] # value = <TargetType.OrientationProfile: 10>
278
+ Sun: typing.ClassVar[Profile.TargetType] # value = <TargetType.Sun: 5>
279
+ TargetPosition: typing.ClassVar[Profile.TargetType] # value = <TargetType.TargetPosition: 3>
280
+ TargetVelocity: typing.ClassVar[Profile.TargetType] # value = <TargetType.TargetVelocity: 4>
275
281
  Trajectory: typing.ClassVar[Profile.TargetType] # value = <TargetType.Trajectory: 2>
276
- VelocityECEF: typing.ClassVar[Profile.TargetType] # value = <TargetType.VelocityECEF: 6>
277
- VelocityECI: typing.ClassVar[Profile.TargetType] # value = <TargetType.VelocityECI: 5>
278
- __members__: typing.ClassVar[dict[str, Profile.TargetType]] # value = {'GeocentricNadir': <TargetType.GeocentricNadir: 0>, 'GeodeticNadir': <TargetType.GeodeticNadir: 1>, 'Trajectory': <TargetType.Trajectory: 2>, 'Sun': <TargetType.Sun: 3>, 'Moon': <TargetType.Moon: 4>, 'VelocityECI': <TargetType.VelocityECI: 5>, 'VelocityECEF': <TargetType.VelocityECEF: 6>, 'OrbitalMomentum': <TargetType.OrbitalMomentum: 7>, 'OrientationProfile': <TargetType.OrientationProfile: 8>}
282
+ VelocityECEF: typing.ClassVar[Profile.TargetType] # value = <TargetType.VelocityECEF: 8>
283
+ VelocityECI: typing.ClassVar[Profile.TargetType] # value = <TargetType.VelocityECI: 7>
284
+ __members__: typing.ClassVar[dict[str, Profile.TargetType]] # value = {'GeocentricNadir': <TargetType.GeocentricNadir: 0>, 'GeodeticNadir': <TargetType.GeodeticNadir: 1>, 'Trajectory': <TargetType.Trajectory: 2>, 'TargetPosition': <TargetType.TargetPosition: 3>, 'TargetVelocity': <TargetType.TargetVelocity: 4>, 'Sun': <TargetType.Sun: 5>, 'Moon': <TargetType.Moon: 6>, 'VelocityECI': <TargetType.VelocityECI: 7>, 'VelocityECEF': <TargetType.VelocityECEF: 8>, 'OrbitalMomentum': <TargetType.OrbitalMomentum: 9>, 'OrientationProfile': <TargetType.OrientationProfile: 10>}
279
285
  def __eq__(self, other: typing.Any) -> bool:
280
286
  ...
281
287
  def __getstate__(self) -> int:
@@ -309,6 +315,16 @@ class Profile:
309
315
 
310
316
 
311
317
  """
318
+ @staticmethod
319
+ def target_position(trajectory: ostk.astrodynamics.Trajectory, axis: Profile.Axis, anti_direction: bool = False) -> Profile.TrajectoryTarget:
320
+ """
321
+ Create a target, which produces a vector pointing from the observer to the target position.
322
+ """
323
+ @staticmethod
324
+ def target_velocity(trajectory: ostk.astrodynamics.Trajectory, axis: Profile.Axis, anti_direction: bool = False) -> Profile.TrajectoryTarget:
325
+ """
326
+ Create a target, which produces a vector pointing along the target velocity.
327
+ """
312
328
  def __init__(self, trajectory: ostk.astrodynamics.Trajectory, axis: Profile.Axis, anti_direction: bool = False) -> None:
313
329
  """
314
330
  Constructor.
@@ -321,7 +337,7 @@ class Profile:
321
337
  @property
322
338
  def trajectory(self) -> ostk.astrodynamics.Trajectory:
323
339
  """
324
- The trajectory of the target. Required only if the target type is `Trajectory`.
340
+ The trajectory of the target. Used to compute the target position or velocity.
325
341
  """
326
342
  @staticmethod
327
343
  def align_and_constrain(alignment_target: Profile.Target, clocking_target: Profile.Target, angular_offset: ostk.physics.unit.Angle = ...) -> typing.Callable[[ostk.astrodynamics.trajectory.State], ostk.mathematics.geometry.d3.transformation.rotation.Quaternion]:
@@ -18,7 +18,7 @@ from ostk.astrodynamics.trajectory.state.coordinate_subset import (
18
18
  AngularVelocity,
19
19
  )
20
20
 
21
- CANONICAL_FORMAT: str = r"(r|v)_(.*?)_(x|y|z)"
21
+ POS_VEL_CANONICAL_FORMAT: str = r"(r|v)_(.*?)_(x|y|z)"
22
22
 
23
23
 
24
24
  def custom_class_generator(frame: Frame, coordinate_subsets: list) -> type:
@@ -68,6 +68,7 @@ def from_dict(data: dict) -> State:
68
68
  - 'drag_coefficient'/'cd': The drag coefficient. Optional.
69
69
  - 'cross_sectional_area'/'surface_area': The cross-sectional area. Optional.
70
70
  - 'mass': The mass. Optional.
71
+ - 'ballistic_coefficient'/'bc': The ballistic coefficient. Optional.
71
72
 
72
73
  Args:
73
74
  data (dict): The dictionary.
@@ -76,7 +77,7 @@ def from_dict(data: dict) -> State:
76
77
  State: The State.
77
78
  """
78
79
 
79
- instant: Instant = coerce_to_instant(data["timestamp"])
80
+ # Position and velocity subsets
80
81
 
81
82
  eci_columns: list[str] = [
82
83
  "rx_eci",
@@ -123,7 +124,7 @@ def from_dict(data: dict) -> State:
123
124
  ]
124
125
 
125
126
  match_groups: list[re.Match] = [
126
- re.match(CANONICAL_FORMAT, column) for column in data.keys()
127
+ re.match(POS_VEL_CANONICAL_FORMAT, column) for column in data.keys()
127
128
  ]
128
129
 
129
130
  if len(matches := [match for match in match_groups if match is not None]) == 6:
@@ -188,6 +189,8 @@ def from_dict(data: dict) -> State:
188
189
  else:
189
190
  raise ValueError("Invalid state data.")
190
191
 
192
+ # Attitude and angular velocity subsets
193
+
191
194
  if all(
192
195
  column in data for column in ["q_B_ECI_x", "q_B_ECI_y", "q_B_ECI_z", "q_B_ECI_s"]
193
196
  ):
@@ -216,6 +219,8 @@ def from_dict(data: dict) -> State:
216
219
  ],
217
220
  )
218
221
 
222
+ # Extra subsets
223
+
219
224
  if (data.get("drag_coefficient") is not None) or (data.get("cd") is not None):
220
225
  coordinate_subsets.append(CoordinateSubset.drag_coefficient())
221
226
  coordinates = np.append(
@@ -239,8 +244,15 @@ def from_dict(data: dict) -> State:
239
244
  data["mass"],
240
245
  )
241
246
 
247
+ if (data.get("ballistic_coefficient") is not None) or (data.get("bc") is not None):
248
+ coordinate_subsets.append(CoordinateSubset.ballistic_coefficient())
249
+ coordinates = np.append(
250
+ coordinates,
251
+ data.get("ballistic_coefficient", data.get("bc")),
252
+ )
253
+
242
254
  return State(
243
- instant=instant,
255
+ instant=coerce_to_instant(data["timestamp"]),
244
256
  coordinates=coordinates,
245
257
  frame=frame,
246
258
  coordinate_subsets=coordinate_subsets,
@@ -13,7 +13,7 @@ import ostk.physics.coordinate
13
13
  from ostk.physics.coordinate import Frame
14
14
  from ostk.physics.time import Instant
15
15
  import re as re
16
- __all__ = ['AngularVelocity', 'AttitudeQuaternion', 'CANONICAL_FORMAT', 'CartesianPosition', 'CartesianVelocity', 'CoordinateSubset', 'Frame', 'Instant', 'State', 'StateBuilder', 'coerce_to_instant', 'custom_class_generator', 'from_dict', 'np', 're']
16
+ __all__ = ['AngularVelocity', 'AttitudeQuaternion', 'CartesianPosition', 'CartesianVelocity', 'CoordinateSubset', 'Frame', 'Instant', 'POS_VEL_CANONICAL_FORMAT', 'State', 'StateBuilder', 'coerce_to_instant', 'custom_class_generator', 'from_dict', 'np', 're']
17
17
  def custom_class_generator(frame: ostk.physics.coordinate.Frame, coordinate_subsets: list) -> type:
18
18
  """
19
19
 
@@ -54,6 +54,7 @@ def from_dict(data: dict) -> ostk.astrodynamics.trajectory.State:
54
54
  - 'drag_coefficient'/'cd': The drag coefficient. Optional.
55
55
  - 'cross_sectional_area'/'surface_area': The cross-sectional area. Optional.
56
56
  - 'mass': The mass. Optional.
57
+ - 'ballistic_coefficient'/'bc': The ballistic coefficient. Optional.
57
58
 
58
59
  Args:
59
60
  data (dict): The dictionary.
@@ -62,4 +63,4 @@ def from_dict(data: dict) -> ostk.astrodynamics.trajectory.State:
62
63
  State: The State.
63
64
 
64
65
  """
65
- CANONICAL_FORMAT: str = '(r|v)_(.*?)_(x|y|z)'
66
+ POS_VEL_CANONICAL_FORMAT: str = '(r|v)_(.*?)_(x|y|z)'
@@ -97,7 +97,11 @@ def profile(request) -> Profile:
97
97
  @pytest.fixture(
98
98
  params=[
99
99
  Profile.Target(Profile.TargetType.GeocentricNadir, Profile.Axis.X),
100
- Profile.TrajectoryTarget(
100
+ Profile.TrajectoryTarget.target_position(
101
+ Trajectory.position(Position.meters((0.0, 0.0, 0.0), Frame.ITRF())),
102
+ Profile.Axis.X,
103
+ ),
104
+ Profile.TrajectoryTarget.target_velocity(
101
105
  Trajectory.position(Position.meters((0.0, 0.0, 0.0), Frame.ITRF())),
102
106
  Profile.Axis.X,
103
107
  ),
@@ -458,6 +458,41 @@ class TestState:
458
458
  assert isinstance(state, State)
459
459
  assert state.get_size() == 6
460
460
 
461
+ def test_from_dict_with_ballistic_coefficient(self):
462
+ data: dict = {
463
+ "timestamp": datetime.now(timezone.utc).isoformat(),
464
+ "rx_eci": 7000.0,
465
+ "ry_eci": 0.0,
466
+ "rz_eci": 0.0,
467
+ "vx_eci": 0.0,
468
+ "vy_eci": 7.5,
469
+ "vz_eci": 0.0,
470
+ "ballistic_coefficient": 2.2,
471
+ }
472
+
473
+ state: State = State.from_dict(data)
474
+
475
+ assert state is not None
476
+ assert isinstance(state, State)
477
+ assert state.get_size() == 7
478
+
479
+ data: dict = {
480
+ "timestamp": datetime.now(timezone.utc).isoformat(),
481
+ "rx_eci": 7000.0,
482
+ "ry_eci": 0.0,
483
+ "rz_eci": 0.0,
484
+ "vx_eci": 0.0,
485
+ "vy_eci": 7.5,
486
+ "vz_eci": 0.0,
487
+ "ballistic_coefficient": None,
488
+ }
489
+
490
+ state: State = State.from_dict(data)
491
+
492
+ assert state is not None
493
+ assert isinstance(state, State)
494
+ assert state.get_size() == 6
495
+
461
496
  @pytest.mark.parametrize(
462
497
  ("data", "expected_length", "expected_frame"),
463
498
  [
@@ -1414,6 +1414,7 @@ class State:
1414
1414
  - 'drag_coefficient'/'cd': The drag coefficient. Optional.
1415
1415
  - 'cross_sectional_area'/'surface_area': The cross-sectional area. Optional.
1416
1416
  - 'mass': The mass. Optional.
1417
+ - 'ballistic_coefficient'/'bc': The ballistic coefficient. Optional.
1417
1418
 
1418
1419
  Args:
1419
1420
  data (dict): The dictionary.
@@ -105,7 +105,7 @@ class Viewer:
105
105
  show_orbital_track: bool = False,
106
106
  color: str | None = None,
107
107
  image: str | None = None,
108
- ) -> None:
108
+ ) -> Viewer:
109
109
  """
110
110
  Add Orbit to Viewer.
111
111
 
@@ -116,6 +116,9 @@ class Viewer:
116
116
  show_orbital_track (bool, optional): Whether to show the orbital track. Defaults to False.
117
117
  color (str, optional): Color of the orbit. Defaults to None.
118
118
  image (str, optional): Logo to be added. Defaults to None.
119
+
120
+ Returns:
121
+ Viewer: The Viewer.
119
122
  """
120
123
  instants: list[Instant] = self._interval.generate_grid(step)
121
124
  states: list[State] = orbit.get_states_at(instants)
@@ -164,6 +167,8 @@ class Viewer:
164
167
  )
165
168
  )
166
169
 
170
+ return self
171
+
167
172
  def add_profile(
168
173
  self,
169
174
  profile: Profile,
@@ -172,7 +177,7 @@ class Viewer:
172
177
  cesium_asset_id: int | None = None,
173
178
  sensors: list[Sensor] | None = None,
174
179
  show_xyz_axes: bool = False,
175
- ) -> None:
180
+ ) -> Viewer:
176
181
  """
177
182
  Add Profile to Viewer.
178
183
 
@@ -183,6 +188,9 @@ class Viewer:
183
188
  cesium_asset_id (int, optional): The Cesium asset ID. Defaults to None.
184
189
  sensors (list[Sensor], optional): Sensors to be added to the asset. Defaults to None.
185
190
  show_xyz_axes (bool, optional): Whether to show the XYZ axes. Defaults to False.
191
+
192
+ Returns:
193
+ Viewer: The Viewer.
186
194
  """
187
195
 
188
196
  instants: list[Instant] = self._interval.generate_grid(step)
@@ -257,13 +265,15 @@ class Viewer:
257
265
  )
258
266
  )
259
267
 
268
+ return self
269
+
260
270
  def add_target(
261
271
  self,
262
272
  position: Position,
263
273
  size: int | None = None,
264
274
  color: str | None = None,
265
275
  label: str | None = None,
266
- ) -> None:
276
+ ) -> Viewer:
267
277
  """
268
278
  Add target to Viewer.
269
279
 
@@ -272,6 +282,9 @@ class Viewer:
272
282
  size (int, optional): Target size. Defaults to None.
273
283
  color (str, optional): Target color. Defaults to None.
274
284
  label (str, optional): Target label. Defaults to None.
285
+
286
+ Returns:
287
+ Viewer: The Viewer.
275
288
  """
276
289
 
277
290
  self._viewer.entities.add(
@@ -285,12 +298,14 @@ class Viewer:
285
298
  if label:
286
299
  self.add_label(position, label, size, color)
287
300
 
301
+ return self
302
+
288
303
  def add_line(
289
304
  self,
290
305
  positions: list[Position],
291
306
  size: int | None = None,
292
307
  color: str | None = None,
293
- ) -> None:
308
+ ) -> Viewer:
294
309
  """
295
310
  Add line to Viewer.
296
311
 
@@ -298,6 +313,9 @@ class Viewer:
298
313
  positions (list[Position]): Line positions.
299
314
  size (int, optional): Line size. Defaults to None.
300
315
  color (str, optional): Line color. Defaults to None.
316
+
317
+ Returns:
318
+ Viewer: The Viewer.
301
319
  """
302
320
 
303
321
  self._viewer.entities.add(
@@ -321,13 +339,15 @@ class Viewer:
321
339
  )
322
340
  )
323
341
 
342
+ return self
343
+
324
344
  def add_label(
325
345
  self,
326
346
  position: Position,
327
347
  text: str,
328
348
  size: int | None = None,
329
349
  color: str | None = None,
330
- ) -> None:
350
+ ) -> Viewer:
331
351
  """
332
352
  Add label to Viewer.
333
353
 
@@ -337,6 +357,8 @@ class Viewer:
337
357
  size (int, optional): Label size. Defaults to None.
338
358
  color (str, optional): Label color. Defaults to None.
339
359
 
360
+ Returns:
361
+ Viewer: The Viewer.
340
362
  """
341
363
 
342
364
  self._viewer.entities.add(
@@ -348,6 +370,8 @@ class Viewer:
348
370
  )
349
371
  )
350
372
 
373
+ return self
374
+
351
375
  def render(self) -> str:
352
376
  """
353
377
  Render Viewer as HTML string.