upstage.motion package#
Submodules#
upstage.motion.cartesian_model module#
0A 3-D intersection model for cartesian motion in UPSTAGE along straight-line paths.
- cartesian_linear_intersection(start: CartesianLocation, finish: CartesianLocation, speed: float, sensor_location: CartesianLocation, sensor_radius: float) tuple[list[CartesianLocation], list[float], list[str], float] #
Get the intersection of straight line motion and a sphere.
- Parameters:
start (CartesianLocation) – the start location of the mover
finish (CartesianLocation) – the finish location of the mover
speed (float) – the speed of the mover (in STAGE units)
sensor_location (CartesianLocation) – the location of the sensor
sensor_radius (float) – the radius of the sensor (in STAGE units)
- Returns:
_description_
- Return type:
tuple[list[CartesianLocation], list[float], list[str], float]
- ray_intersection(start: L, toward: L, center: L, radii: float | L, speed: float) tuple[list[L], list[float]] #
Ray intersection with ellispoid.
- Parameters:
start (XY | XYZ) – Start position
toward (XY | XYZ) – Point being looked at
center (XY | XYZ) – Center of the ellipsoid
radii (float | XY | XYZ) – Radii of each dimension of ellipsoid
speed (float) – Speed of the particle moving from start to toward
- Returns:
Intersecting positions and times.
- Return type:
tuple[list[XY] | list[XYZ], list[float]]
upstage.motion.geodetic_model module#
A model of the geodetic earth and intersecting paths/spheres.
- analytical_intersection(start: GeodeticLocation, finish: GeodeticLocation, speed: float, sensor_location: GeodeticLocation, sensor_radius: float) tuple[list[GeodeticLocation], list[float], list[str], float] #
Calculate the intersection of a great circle.
The circle is defined by start & finish and the sphere defined by sensor_location and sensor_radius.
This function mimics the above subdivide_intersection, but uses analytical equations that run much faster.
- Requires:
UP.add_stage_variable(“distance_units”, …) UP.add_stage_variable(“altitude_units”, …)
- Parameters:
start (GeodeticLocation) – the start location of the mover
finish (GeodeticLocation) – the finish location of the mover
speed (float) – the speed of the mover (in STAGE units)
sensor_location (GeodeticLocation) – the location of the sensor
sensor_radius (float) – the radius of the sensor (in STAGE units)
- Returns:
intersections, times, types, path_time
- Return type:
tuple[list[GeodeticLocation], list[float], list[str], float]
- subdivide_intersection(start: GeodeticLocation, finish: GeodeticLocation, speed: float, sensor_location: GeodeticLocation, sensor_radius: float) tuple[list[GeodeticLocation], list[float], list[str], float] #
Numerical intersection calculation.
- Requires:
UP.add_stage_variable(“intersection_model”, INTERSECTION_LOCATION_CALLABLE) UP.add_stage_variable(“distance_units”, …)
- Parameters:
start (GeodeticLocation) – Path start
finish (GeodeticLocation) – Path end
speed (float) – Speed on path
sensor_location (GeodeticLocation) – Location of a sensor
sensor_radius (float) – Radius of sensor line of sight.
- Returns:
intersections, times, types, path_time
- Return type:
tuple[list[GeodeticLocation], list[float], list[str], float]
upstage.motion.great_circle_calcs module#
Great circle calculations.
These equations were largely adapted from https://edwilliams.org/avform147.htm, although most of them can be verified from a number of open resources around the web. The overall algorithms have been slightly modified to support UPSTAGE.
- get_course_rad(point1: GeodeticLocation, point2: GeodeticLocation) float #
Get the course (in radians) between point1 and point2.
- Parameters:
point1 – the starting point
point2 – the ending point
- get_dist_rad(point1: GeodeticLocation, point2: GeodeticLocation) float #
Get the distance (in radians) between point1 and point2.
- Parameters:
point1 – the starting point
point2 – the ending point
- get_great_circle_points(pointA: GeodeticLocation, pointB: GeodeticLocation, pointD: GeodeticLocation, dist: float) tuple[list[tuple[float, float]], list[float]] | None #
Let points A and B define a great circle route and D be a third point.
Find the points on the great circle through A and B that lie a distance d from D, if they exist.
- Parameters:
pointA – GeodeticLocation of start of great circle
pointB – GeodeticLocation of end of great circle
pointD – GeodeticLocation, third point of interest (the center of sphere)
dist – (float) distance from third to point to find intersection on great circle (radians)
- get_pos_from_points_and_distance(point1: GeodeticLocation, point2: GeodeticLocation, dist: float) tuple[float, float] #
Get a position (lat, lon) given a starting position, ending position, and distance.
- Parameters:
point1 – GeodeticLocation of start of great circle
point2 – GeodeticLocation of end of great circle
dist – (float) distance along great circle to find third point
returns [lat, lon]
upstage.motion.motion module#
This file contains a queueing motion manager for sensor/mover intersections.
- class SensorMotionManager(intersection_model: Callable[[LOC_INPUT, LOC_INPUT, float, LOC_INPUT, float], tuple[list[LOC_INPUT], list[float], list[str], float]], debug: bool = False)#
Bases:
UpstageBase
Schedules the interaction of moving and detectable entities against non-moving ‘sensors’.
Movable objects must be Actors with: 1. GeodeticLocationChangingState OR CartesianLocationChangingState 2. DetectabilityState
Sensor objects MUST implement these two methods: 1. entity_entered_range(mover) 2. entity_exited_range(mover)
The first is called when a mover enters the sensor’s visiblity. The second is called when a mover leaves the visibility or becomes undetectable.
The motion manager will learn about sensor objects with:
sensor_motion_manager.add_sensor(sensor_object, location, radius)
Where location is a location object found in upstage.data_types and radius is a distance in the units defined in upstage.STAGE.
- add_sensor(sensor: SensorType, location_attr_name: str = 'location', radius_attr_name: str = 'radius') None #
Add a sensor to the motion manager.
- Parameters:
sensor (SensorType) – The sensor object
location_attr_name (str, optional) – Name of the location attribute. Defaults to “location”.
radius_attr_name (str, optional) – Name of the radius attribute. Defaults to “radius”.
upstage.motion.stepped_motion module#
This file contains a motion manager that does time-stepping.
- class SteppedMotionManager(timestep: float, max_empty_events: int = 3, debug: bool = False)#
Bases:
UpstageBase
Tests relative distances of objects with a location property.
Reports to “sensor” objects when something enters or exits a range.
Use this manager when the sensing entities are not static. If they are static, use SensorMotionManager.
Detectable objects and sensor objects must have an attribute that is a GeodeticLocationState OR CartesianLocationState
Detectable objects, if they aren’t Actors, could implement _get_detection_state() -> bool:` to allow this class to ignore them sometimes. The default way is to use a DetectabilityState on the actor.
Sensor objects MUST implement these two methods: 1. entity_entered_range(object) 2. entity_exited_range(object)
The first is called when an entity enters the sensor’s visiblity. The second is called when an entity leaves the visibility or becomes undetectable.
The sensor object CAN implement a method called detection_checker. That method takes the location of an object to detect and returns True/False.
The motion manager will learn about sensor objects with:
sensor_motion_manager.add_sensor(sensor_object, radius)
Where radius is a distance in the units defined in upstage.STAGE.
Simple usage: >>> manager = SteppedMotionManager(timestep=0.1) >>> UP.STAGE.motion_manager = manager >>> … >>> manager.add_sensor(binoculars, ‘vision_radius’) >>> manager.add_detectable(bird, ‘location’)
# TODO: Unify sensor and movable # TODO: Having only moving things be detectable/using _start_mover is easy, but this class lets us do static detection easier, so we may have to go about it differently. # TODO: Data structures for efficient distances
- add_detectable(detectable: Actor, location_attr_name: str = 'location', new_rate: float | None = None) None #
Add an object that is detectable to the manager.
The object must have an attribute that performs distance calculations. See the class docstring for more.
- Parameters:
detectable (Actor) – An object that has a location attribute
location_attr_name (str) – Name of the location attribute. Defaults to “location”.
new_rate (float | None) – Optional new rate for a detectable
faster ((if it needs)
likely) (most)
- add_sensor(sensor: SensorType, radius_attr_name: str = 'radius', location_attr_name: str = 'location') None #
Add a sensor the motion manager.
- Parameters:
sensor (SensorType) – The sensing object
radius_attr_name (str) – Radius attribute name. Defaults to “radius”.
location_attr_name (str) – Location attribute name. Defaults to “location”.
- run() Generator[Event, None, None] #
Run the main stepped motion loop.
- Yields:
Generator[SimpyEvent, None, None] – _description_
Module contents#
Motion features for UPSTAGE.