📍 GPS Coverage Map

Scroll down for video of capture and the capture graph code!

Session Loading...
Left stereo image
Solar Azimuth: --°  |  Altitude: --°  |  Date: --
Focal Shift -3.3%

🎬 Capture Video

📄 Capture Graph Code

Client-Side Stereo Capture Procedure

def stereo_capture_procedure() -> cgp.ProcedureSequence:
    """Client-side procedure for stereo image capture."""
    root = cgp.GetRootDirectory()
    session = root.new_session("G3C")

    # Load instruction image
    instruction_image = root.new_file("instructions").load(
        or_else=cgp.NullProcedure(return_type=cgp.PImage)
    )

    # Get reference from first session for alignment
    reference_session = root.get_first_session("G3C")

    # Capture aligned stereo pair
    left_photo = cgp.CaptureAlignedImage(
        label="Capture Left Photo",
        reference_image=reference_session.new_file("left").load(
            or_else=cgp.NullProcedure(return_type=cgp.PImage)
        ),
    )
    right_photo = cgp.CaptureAlignedImage(
        label="Capture Right Photo",
        reference_image=reference_session.new_file("right").load(
            or_else=cgp.NullProcedure(return_type=cgp.PImage)
        ),
    )

    return cgp.ProcedureSequence(
        label="G3C Stereo Capture",
        procedures=[
            session.new_file("left").save(left_photo),
            session.new_file("right").save(right_photo),
        ],
    )

Server-Side Solar Scheduler

def calculate_optimal_slots(target, sessions) -> cg.List:
    """Compute optimal capture times using solar angle scheduling."""
    location = target._metadata._capture_location

    # Generate candidate times for next 24 hours
    candidates = cg.List([])
    candidates.date = cgsh.forecast.times(
        resolution=timedelta(minutes=1),
        span=timedelta(hours=24),
    )

    # Get weather forecast and solar positions
    candidates.weather = cgsh.forecast.nearest_weather(
        weather=cgsh.forecast.hourly_weather(location, days=3),
        times=candidates.date,
    )
    candidates.solar_angle = cgsh.forecast.solar_position(location, candidates.date)

    # Distance function combining solar angle and weather
    distance_fn = cgsh.distance.combine(
        solar_angle=cgsh.distance.solar(sigma_deg=2.0),
        weather=cgsh.distance.weather(sigma_cloud_cover_ratio=0.4),
    )

    # Select optimal slots using void-and-cluster
    return cgsh.select_sessions(
        potential_sessions=candidates,
        previous_sessions=sessions,
        distance_fn=distance_fn,
        energy_fn=cgsh.energy.gaussian(sigma=1),
        selections=3,
    )