def locdir_at(self, phi, theta, psi, row, col, alt=0, geo=True): """ Given the satellite attitude, computes lon, lat of point row, col, alt. Args: phi, theta, psi: attitude angles of the satellite camera row, col: pixel coordinates in the image plane alt: altitude of the 3d point above the Earth surface geo: boolean flag telling whether to return geographic coordinates or Cartesian coordinates. Returns: geographic coordinates (lon, lat), or Cartesian coordinates (x, y, z). Cartesian coordinates are computed with respect to the orbital frame. """ # first compute coordinates of the 3-space point in the orbital frame orbital_to_camera = utils.rotation_3d('xyz', phi, theta, psi) v = np.dot(orbital_to_camera, self.instrument.sight_vector(col)) c = np.array([0, 0, self.orbit.radius]) r = PhysicalConstants.earth_radius + alt p = utils.intersect_line_and_sphere(v, c, r) if not geo: return p # then convert them to lon, lat, using t to get the satellite position if p is None: return p else: t = row * self.instrument.dwell_time mat_t_ol = self.rotational_to_orbital(t) return utils.lon_lat(np.dot(mat_t_ol, -c + p))
def target_point_orbital_frame(self, a, b, alt=0): """ Computes orbital coordinates of the ground point targeted by the satellite. Args: a: sight direction angle about the x axis of orbital frame, degrees b: angle about the y axis of orbital frame, degrees alt: altitude of the ground above the sphere Returns: numpy 1x3 array with the coordinates in the orbital frame """ # Earth center position in the orbital frame c = np.array([0, 0, self.radius]) # coordinates of the vector defined by angles a, b and coordinate z=1 # in the orbital frame a_rad = a * np.pi/180 b_rad = b * np.pi/180 v = np.array([np.tan(b_rad), -np.tan(a_rad), 1]) # intersection of the line directed by v with the Earth r = PhysicalConstants.earth_radius + alt return utils.intersect_line_and_sphere(v, c, r)
def target_point_orbital_frame(self, a, b, alt=0): """ Computes orbital coordinates of the ground point targeted by the satellite. Args: a: sight direction angle about the x axis of orbital frame, degrees b: angle about the y axis of orbital frame, degrees alt: altitude of the ground above the sphere Returns: numpy 1x3 array with the coordinates in the orbital frame """ # Earth center position in the orbital frame c = np.array([0, 0, self.radius]) # coordinates of the vector defined by angles a, b and coordinate z=1 # in the orbital frame a_rad = a * np.pi / 180 b_rad = b * np.pi / 180 v = np.array([np.tan(b_rad), -np.tan(a_rad), 1]) # intersection of the line directed by v with the Earth r = PhysicalConstants.earth_radius + alt return utils.intersect_line_and_sphere(v, c, r)
def pixel_projection_width(self, m, x=0, y=0): """ Computes the width of the projection of a pixel on the ground. Args: m: numpy 3x3 array representing the change of coordinates matrix between orbital frame and camera frame x, y (optional, default is 0, 0): coordinates of the pixel in the image plane Returns: width, in meters, of the projection of the pixel on the ground, in the pushbroom direction (orthogonal to the pushbroom movement) """ # pixel width and focal length in mm w = self.instrument.w_pix * 0.001 f = self.instrument.focal * 1000 # direction of the camera, expressed in the orbital frame v = np.dot(m, np.array([-x, -y, f])) # intersection of the line directed by v with the Earth c = np.array([0, 0, self.orbit.radius]) r = PhysicalConstants.earth_radius p = utils.intersect_line_and_sphere(v, c, r) # normal to the tangent plane to the Earth at the intersection point p n = p - c # projection of the left and right borders of the pixel on the ground v1 = np.dot(m, np.array([-(x + .5*w), -y, f])) v2 = np.dot(m, np.array([-(x - .5*w), -y, f])) p1 = utils.intersect_line_and_plane(v1, p, n) p2 = utils.intersect_line_and_plane(v2, p, n) return np.linalg.norm(p1 - p2)
def pixel_projection_width(self, m, x=0, y=0): """ Computes the width of the projection of a pixel on the ground. Args: m: numpy 3x3 array representing the change of coordinates matrix between orbital frame and camera frame x, y (optional, default is 0, 0): coordinates of the pixel in the image plane Returns: width, in meters, of the projection of the pixel on the ground, in the pushbroom direction (orthogonal to the pushbroom movement) """ # pixel width and focal length in mm w = self.instrument.w_pix * 0.001 f = self.instrument.focal * 1000 # direction of the camera, expressed in the orbital frame v = np.dot(m, np.array([-x, -y, f])) # intersection of the line directed by v with the Earth c = np.array([0, 0, self.orbit.radius]) r = PhysicalConstants.earth_radius p = utils.intersect_line_and_sphere(v, c, r) # normal to the tangent plane to the Earth at the intersection point p n = p - c # projection of the left and right borders of the pixel on the ground v1 = np.dot(m, np.array([-(x + .5 * w), -y, f])) v2 = np.dot(m, np.array([-(x - .5 * w), -y, f])) p1 = utils.intersect_line_and_plane(v1, p, n) p2 = utils.intersect_line_and_plane(v2, p, n) return np.linalg.norm(p1 - p2)