예제 #1
0
def camera_angle_of_view(
    min_mid_max: video_data.ErrorDirection = video_data.ErrorDirection.MID
) -> np.ndarray:
    # TODO: Figure out min/max error terms.
    # Max value is obtained with:
    # max alpha, min d, min pitch
    # Min value is obtained with:
    # min alpha, max d, max pitch
    gs_fit = ground_speed_curve_fit(-min_mid_max)
    # aspect_fit = aspect.aspects_curve_fit(min_mid_max)
    pitch_data = pitch.pitches(-min_mid_max)

    OBSERVER_POSITION_X = 2250
    OBSERVER_POSITION_Y = -750

    for data in video_data.AIRCRAFT_LENGTH_IN_PIXELS:
        t = data.video_time.time
        px = data.length_px
        x = OBSERVER_POSITION_X - ground_speed_integral(0, t, gs_fit)
        d = math.sqrt(x**2 + OBSERVER_POSITION_Y**2)
        alpha = abs(math.atan2(OBSERVER_POSITION_Y, x))
        pitch_angle = video_utils.interpolate(pitch_data[:, 0],
                                              pitch_data[:, 1], t)
        apparent_length = video_data.TRANSIT_REFERENCE_LENGTH * math.sin(
            alpha) * math.cos(math.radians(pitch_angle))
        px_per_m = px / apparent_length
        width_in_m = video_data.SCREENSHOT_WIDTH / px_per_m
        angle_of_view = math.degrees(2 * math.atan(width_in_m / (2 * d)))
        print('{:<4.1f} {:6.3f}'.format(t, angle_of_view))
예제 #2
0
def markdown_table_aircraft_start() -> typing.Tuple[typing.List[str], str]:
    """
    Returns a markdown table and a title for the distance estimates at start of take off.
    """
    ret = [
        '| Calculation | Video Time t (s) | Distance from start of Runway (m) | Distance from start of Runway at t=0 (m) |',
        '| --- | --: | --: | --: |',
    ]
    labels = (
        'Mid speed -10 knots',
        'Mid speed',
        'Mid speed +10 knots',
    )
    three_dist_arrays = get_distances_min_mid_max(
        video_data.TIME_VIDEO_END_ASPHALT.time)
    # Time ranges for min/mid/max of start of take off
    t_range = [arr[0][0] for arr in three_dist_arrays]
    # Distance of start of take off from start of runway for min/mid/max
    d_range = [arr[0][1] for arr in three_dist_arrays]
    # Distance of start of video from start of runway for min/mid/max
    d_range_video_start = [
        video_utils.interpolate(arr[:, 0], arr[:, 1], 0.0)
        for arr in three_dist_arrays
    ]
    for label, arr, d_video_start in zip(labels, three_dist_arrays,
                                         d_range_video_start):
        t, d = arr[0]
        ret.append('| {} | {:.1f} | {:.0f} | {:.0f} |'.format(
            label, t, d, d_video_start))
    ret.append(
        '| **{}** | **{:.1f} ±{:.1f}** | **{:.0f} ±{:.0f}** | **{:.0f} ±{:.0f}** |'
        .format(
            'Range and worst error',
            t_range[1],
            max(abs(t_range[2] - t_range[1]), abs(t_range[0] - t_range[1])),
            d_range[1],
            max(abs(d_range[2] - d_range[1]), abs(d_range[0] - d_range[1])),
            d_range_video_start[1],
            max(abs(d_range_video_start[2] - d_range_video_start[1]),
                abs(d_range_video_start[0] - d_range_video_start[1])),
        ))
    return ret, 'Distance Estimates for the Start of Take off'
예제 #3
0
def _transit(t: float) -> float:
    """Returns the apparent transit time, dt, of the aircraft fuselage at time t."""
    xS = [v.time for v in video_data.AIRCRAFT_TRANSITS]
    yS = [v.dt for v in video_data.AIRCRAFT_TRANSITS]
    return video_utils.interpolate(xS, yS, t)
예제 #4
0
def _pitch(t: float) -> float:
    """Returns the apparent pitch angle of the aircraft at time t.
    Due to camera roll this may not be accurate."""
    xS = [v.video_time.time for v in video_data.AIRCRAFT_PITCHES]
    yS = [v.angle for v in video_data.AIRCRAFT_PITCHES]
    return video_utils.interpolate(xS, yS, t)
예제 #5
0
def test_interpolate(x, y):
    # [4, 8, 12, 16]
    xS = list(range(4, 17, 4))
    # [8, 16, 24, 32]
    yS = [v * 2 for v in xS]
    assert y == video_utils.interpolate(xS, yS, x)
예제 #6
0
def _gnuplot_distance(
    offset_distance_at_t: float,
    include_labels_t_0: bool,
    stream: typing.TextIO = sys.stdout,
) -> typing.List[str]:
    """
    If offset_distance_at_t is non-zero an offset will be applied that is the
    runway length - the distance at that offset time.
    """
    three_dist_arrays = get_distances_min_mid_max(offset_distance_at_t)
    plot_common.gnuplot_write_arrays(stream, *three_dist_arrays)
    plot_data = ['# Start distance arrows and labels']
    if offset_distance_at_t == 0.0:
        text_offset = 0
    else:
        text_offset = 1000
    plot_data.extend([
        # set arrow from -30.137,0 to -30.137,-791.8 lt 1
        'set arrow from {t:.3f},{offset:d} to {t:.3f},{d:.3f} lt {lt:d}'.
        format(
            t=three_dist_arrays[i][0, 0],
            offset=text_offset + i * 200,
            d=three_dist_arrays[i][0, 1],
            lt=i + 1,
        ) for i in range(len(three_dist_arrays))
    ])
    plot_data.extend([
        # set label 1 "Calculated start at -30s, -790m" at -30.137,100 left font ",10" # rotate by 45
        'set label "Calculated start at {t:.1f}s, {d:.0f}m" at {t:.1f},{offset:d} left font ",9"'
        .format(
            t=three_dist_arrays[i][0, 0],
            offset=text_offset + 100 + i * 200,
            d=three_dist_arrays[i][0, 1],
        ) for i in range(len(three_dist_arrays))
    ])
    plot_data.append('# End labels at start of take off')
    if include_labels_t_0:
        plot_data.append('# Labels at t=0')
        for i in range(len(three_dist_arrays)):
            d = video_utils.interpolate(three_dist_arrays[i][:, 0],
                                        three_dist_arrays[i][:, 1], 0.0)
            plot_data.append(
                # set arrow from -30.137,0 to -30.137,-791.8 lt 1
                'set arrow from {t:.3f},{d:.1f} to 0.0,{d:.3f} lt {lt:d}'.
                format(
                    t=6.0,
                    d=d,
                    lt=i + 1,
                ))
            plot_data.append(
                # set label 1 "Calculated start at -30s, -790m" at -30.137,100 left font ",10" # rotate by 45
                'set label "t=0.0s, d={d:.0f}m" at {t:.1f},{d:.1f} left font ",9"'
                .format(
                    t=6.0,
                    d=d,
                ))
        plot_data.append('# End labels at t=0')
    if offset_distance_at_t == 0.0:
        d_to = 1850
    else:
        d_to = video_data.RUNWAY_LEN_M - 100
    d_from = d_to - 850
    plot_data.append(
        'set arrow from {t:.3f},{d_from:d} to {t:.3f},{d_to:d} lt -1'.format(
            d_from=d_from,
            d_to=d_to,
            t=video_data.TIME_VIDEO_END_ASPHALT.time,
        ))
    plot_data.append(
        # set label 7 "End asphalt 27.8s" at 27.8,900 center font ",10"
        'set label "End asphalt {t:.1f}s" at {t:.1f},{d:d} center font ",10"'.
        format(
            d=d_from - 100,
            t=video_data.TIME_VIDEO_END_ASPHALT.time,
        ))

    if offset_distance_at_t == 0.0:
        plot_data.extend([
            # set arrow from 17.8,1919 to 27.8,1919 as 4 lt 1
            'set arrow from {t0:.3f},{distance:.3f} to {t1:.3f},{distance:.3f} lt {lt:d}'
            .format(
                t0=video_data.TIME_VIDEO_END_ASPHALT.time - 10,
                t1=video_data.TIME_VIDEO_END_ASPHALT.time,
                distance=np.interp(
                    video_data.TIME_VIDEO_END_ASPHALT.time,
                    three_dist_arrays[i][:, 0],
                    three_dist_arrays[i][:, 1],
                ),
                lt=i + 1,
            ) for i in range(len(three_dist_arrays))
        ])
        plot_data.extend([
            # set label 4 "1920m" at 17,1920 right font ",10" # rotate by 45
            'set label "{distance:.0f}m" at {t:.1f},{distance:.1f} right font ",10"'
            .format(
                t=video_data.TIME_VIDEO_END_ASPHALT.time - 10 - 1,
                distance=np.interp(
                    video_data.TIME_VIDEO_END_ASPHALT.time,
                    three_dist_arrays[i][:, 0],
                    three_dist_arrays[i][:, 1],
                ),
            ) for i in range(len(three_dist_arrays))
        ])
    else:
        plot_data.append(
            'set arrow from {t0:.3f},{distance:.3f} to {t1:.3f},{distance:.3f} lt {lt:d}'
            .format(
                t0=video_data.TIME_VIDEO_END_ASPHALT.time - 10,
                t1=video_data.TIME_VIDEO_END_ASPHALT.time,
                distance=video_data.RUNWAY_LEN_M,
                lt=2,
            ))
        plot_data.append(
            'set label "{distance:.0f}m" at {t:.1f},{distance:.1f} right font ",10"'
            .format(
                t=video_data.TIME_VIDEO_END_ASPHALT.time - 10 - 1,
                distance=video_data.RUNWAY_LEN_M,
            ))
    plot_data.append('# End video')
    # TODO: Constants here, they should be computed.
    if offset_distance_at_t == 0.0:
        d_to = 2350
    else:
        d_to = 3700
    d_from = d_to - 850
    plot_data.append(
        # set arrow from 33.7,1500 to 33.7,2350 as 11 lt -1
        'set arrow from {t:.3f},{d_from:d} to {t:.3f},{d_to:d} lt -1'.format(
            t=video_data.TIME_VIDEO_END.time,
            d_from=d_from,
            d_to=d_to,
        ))
    plot_data.append(
        # set label 11 "End video 33.7s" at 33.7,1400 center font ",10" # rotate by 45
        'set label "End video {t:.1f}s" at {t:.1f},{d:d} center font ",10"'.
        format(t=video_data.TIME_VIDEO_END.time, d=d_from - 100))
    if offset_distance_at_t == 0.0:
        # Plot individual arrows and labels of end of video
        plot_data.extend([
            # set arrow from 23.7,2432.8 to 33.7,2432.8 as 8 lt 1
            'set arrow from {t0:.3f},{distance:.3f} to {t1:.3f},{distance:.3f} lt {lt:d}'
            .format(
                t0=video_data.TIME_VIDEO_END.time - 10,
                t1=video_data.TIME_VIDEO_END.time,
                distance=np.interp(
                    video_data.TIME_VIDEO_END.time,
                    three_dist_arrays[i][:, 0],
                    three_dist_arrays[i][:, 1],
                ),
                lt=i + 1,
            ) for i in range(len(three_dist_arrays))
        ])
        plot_data.extend([
            # label 10 "2770m" at 23,2770 right font ",10" # rotate by 45
            'set label "{distance:.0f}m" at {t:.1f},{distance:.1f} right font ",10"'
            .format(
                t=video_data.TIME_VIDEO_END.time - 10 - 1,
                distance=np.interp(
                    video_data.TIME_VIDEO_END.time,
                    three_dist_arrays[i][:, 0],
                    three_dist_arrays[i][:, 1],
                ),
            ) for i in range(len(three_dist_arrays))
        ])
    return plot_data
예제 #7
0
def gnuplot_ground_speed_extrapolated(
        stream: typing.TextIO = sys.stdout) -> typing.List[str]:
    gs_arrays = [
        video_analysis.ground_speeds(min_max)
        for min_max in list(video_data.ErrorDirection)
    ]
    gs_fits = [
        plot_common.get_gs_fit(err) for err in video_data.ErrorDirection
    ]
    result = [
        '# "{}"'.format(
            'Grounds speed, mid data and smoothed data, extrapolated.')
    ]
    notes = [
        'Columns',
        '1: Time (s)',
        '2: Ground speed, mid values (knots).',
        '3: Time, minimum (s).',
        '4: Time, maximum (s).',
        '5: Ground speed, min values (knots).',
        '6: Ground speed, max values (knots).',
        '7: Ground speed extrapolated, mid values (knots).',
        '8: Ground speed extrapolated, min values (knots).',
        '9: Ground speed extrapolated, max values (knots).',
    ]
    if len(notes):
        result.append('#')
        result.append('# Notes:')
        for note in notes:
            result.append('# {}'.format(note))
    gs_arrays_extrapolated = []
    for fit in gs_fits:
        gs_arrays_extrapolated.append(
            np.array([(t, video_analysis.ground_speed_from_fit(t, fit))
                      for t in plot_constants.EXTRAPOLATED_RANGE]))
    # Convert selected columns to knots
    k = video_utils.m_p_s_to_knots(1.0)
    for i in range(3):
        gs_arrays[i][:, 1] *= k
        gs_arrays_extrapolated[i][:, 1] *= k

    stream.write('\n'.join(result))
    stream.write('\n')
    plot_common.gnuplot_write_arrays(
        stream,
        gs_arrays[1],
        np.column_stack((gs_arrays[1][:, 0],
                         gs_arrays[1][:, 0] - video_data.ERROR_TIMESTAMP)),
        np.column_stack((gs_arrays[1][:, 0],
                         gs_arrays[1][:, 0] + video_data.ERROR_TIMESTAMP)),
        gs_arrays[0],
        gs_arrays[2],
        gs_arrays_extrapolated[1],
        gs_arrays_extrapolated[0],
        gs_arrays_extrapolated[2],
    )
    # Print time for v=0
    plot_data = []
    for i in range(len(gs_arrays_extrapolated)):
        t = video_utils.interpolate(gs_arrays_extrapolated[i][:, 1],
                                    gs_arrays_extrapolated[i][:, 0], 0.0)
        print('Time start[{:d}] t, v=0: {:.3f} Polynomial roots: {}'.format(
            i, t, np.roots(list(reversed(gs_fits[i])))))
        plot_data.append(
            'set arrow from {t:.3f},{offset:d} to {t:.3f},{zero:.3f} lt {lt:d}'
            .format(
                t=t,
                offset=50 + i * 25,
                zero=0.0,
                lt=i + 1,
            ))
        plot_data.append(
            'set label "t={t0:.1f}s" at {t1:.1f},{offset:d} left font ",12"'.
            format(
                t0=t,
                t1=t - 2,
                offset=54 + i * 25,
            ))
    return plot_data