Target Tracking (With Yaw Compensation)¶
This tutorial demonstrates how to generate a target tracking profile, aligning with the target velocity direction
Setup¶
!pip install cesiumpy@git+https://github.com/open-space-collective/cesiumpy
Collecting cesiumpy@ git+https://github.com/open-space-collective/cesiumpy
Cloning https://github.com/open-space-collective/cesiumpy to /tmp/pip-install-g4chppwn/cesiumpy_c79e77af84a2423787c5aba9c15fd4e1
Running command git clone --filter=blob:none --quiet https://github.com/open-space-collective/cesiumpy /tmp/pip-install-g4chppwn/cesiumpy_c79e77af84a2423787c5aba9c15fd4e1
Resolved https://github.com/open-space-collective/cesiumpy to commit fe92a7d35e37f1f15e76ff38aac83bde17819cb5
Running command git submodule update --init --recursive -q
Preparing metadata (setup.py) ... ?25l-
done
?25hRequirement already satisfied: traitlets in /usr/local/lib/python3.11/dist-packages (from cesiumpy@ git+https://github.com/open-space-collective/cesiumpy) (5.14.3)
Requirement already satisfied: geopy>=1.11.0 in /usr/local/lib/python3.11/dist-packages (from cesiumpy@ git+https://github.com/open-space-collective/cesiumpy) (2.4.1)
Requirement already satisfied: geographiclib<3,>=1.52 in /usr/local/lib/python3.11/dist-packages (from geopy>=1.11.0->cesiumpy@ git+https://github.com/open-space-collective/cesiumpy) (2.1)
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.
[notice] A new release of pip is available: 25.0.1 -> 26.0.1
[notice] To update, run: python3.11 -m pip install --upgrade pip
import os
import cesiumpy
from ostk.mathematics.object import RealInterval
from ostk.physics import Environment
from ostk.physics.unit import Length
from ostk.physics.unit import Angle
from ostk.physics.time import Scale
from ostk.physics.time import Instant
from ostk.physics.time import Duration
from ostk.physics.time import Interval
from ostk.physics.time import DateTime
from ostk.physics.time import Time
from ostk.physics.coordinate import Position
from ostk.physics.coordinate.spherical import LLA
from ostk.astrodynamics import Trajectory
from ostk.astrodynamics.trajectory import Orbit
from ostk.astrodynamics.flight import Profile
from ostk.astrodynamics.access import Generator as AccessGenerator
from ostk.astrodynamics.access import AccessTarget
from ostk.astrodynamics.access import VisibilityCriterion
from ostk.astrodynamics.viewer import Viewer
from ostk.astrodynamics.viewer import ConicSensor
Computation¶
Initialize an environment:
environment = Environment.default(True)
earth = environment.access_celestial_object_with_name("Earth")
Construct an orbit:
orbit = Orbit.sun_synchronous(
epoch=Instant.date_time(DateTime(2024, 1, 1, 0, 0, 0), Scale.UTC),
altitude=Length.kilometers(550.0),
local_time_at_descending_node=Time(14, 30, 0),
celestial_object=earth,
)
Define an interval of interest:
interval = Interval.closed(
start_instant=Instant.date_time(DateTime(2024, 2, 9, 0, 0, 0), Scale.UTC),
end_instant=Instant.date_time(DateTime(2024, 2, 10, 0, 0, 0), Scale.UTC),
)
Define the coordinates of the target to track:
start_lla = LLA(
latitude=Angle.degrees(0.0),
longitude=Angle.degrees(0.0),
altitude=Length.meters(0.0),
)
end_lla = LLA(
latitude=Angle.degrees(0.5),
longitude=Angle.degrees(0.1),
altitude=Length.meters(0.0),
)
mid_lla = start_lla.calculate_intermediate_to(end_lla, 0.5)
Find one access during which the satellite is over the target:
visibility_criterion = VisibilityCriterion.from_aer_interval(
azimuth_interval=RealInterval.closed(0.0, 360.0),
elevation_interval=RealInterval.closed(60.0, 90.0),
range_interval=RealInterval.closed(0.0, 10000e3),
)
access_target = AccessTarget.from_lla(
visibility_criterion=visibility_criterion,
lla=mid_lla,
celestial=earth,
)
access_generator = AccessGenerator(
environment=environment,
)
accesses = access_generator.compute_accesses(
interval=interval,
access_target=access_target,
to_trajectory=orbit,
)
access = accesses[0]
instants = access.get_interval().generate_grid(Duration.seconds(1.0))
Construct a Vehicle Velocity, Local Horizontal (VVLH) frame from the orbit:
vvlh_frame = orbit.get_orbital_frame(Orbit.FrameType.VVLH)
Generate a flight profile:
line_scan_trajectory = Trajectory.ground_strip(
start_lla=start_lla,
end_lla=end_lla,
instants=instants,
)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[10], line 1
----> 1 line_scan_trajectory = Trajectory.ground_strip(
2 start_lla=start_lla,
3 end_lla=end_lla,
4 instants=instants,
5 )
AttributeError: type object 'ostk.astrodynamics.Trajectory' has no attribute 'ground_strip'
uncompensated_profile = Profile.custom_pointing(
orbit=orbit,
alignment_target=Profile.TrajectoryTarget.target_position(
trajectory=line_scan_trajectory,
axis=Profile.Axis.Z,
),
clocking_target=Profile.Target(
type=Profile.TargetType.VelocityECI,
axis=Profile.Axis.X,
),
)
yaw_compensated_profile = Profile.custom_pointing(
orbit=orbit,
alignment_target=Profile.TrajectoryTarget.target_position(
trajectory=line_scan_trajectory,
axis=Profile.Axis.Z,
),
clocking_target=Profile.TrajectoryTarget.target_velocity(
trajectory=line_scan_trajectory,
axis=Profile.Axis.X,
),
)
Visualize the scene in 3D:
# Get a token from https://cesium.com/learn/ion/cesium-ion-access-tokens/
viewer = Viewer(
interval=access.get_interval(),
cesium_token=os.environ.get("CESIUM_TOKEN"),
)
viewer.add_profile(
profile=yaw_compensated_profile,
step=Duration.seconds(10.0),
show_orbital_track=True,
cesium_asset_id=669199,
sensors=[
ConicSensor(
"Boresight",
[0.0, 0.0, 1.0],
cesiumpy.color.RED.with_alpha(0.5),
Angle.degrees(0.5),
Length.meters(6913000.0),
)
],
)
viewer.add_line(
positions=[Position.from_lla(lla) for lla in LLA.linspace(start_lla, end_lla, 100)]
)
with open("render.html", "w") as f:
f.write(viewer.render())