// Copyright (c) 2022 Boston Dynamics, Inc.  All rights reserved.
//
// Downloading, reproducing, distributing or otherwise using the SDK Software
// is subject to the terms and conditions of the Boston Dynamics Software
// Development Kit License (20191101-BDSDK-SL).

syntax = "proto3";

package bosdyn.api.graph_nav;

import "bosdyn/api/header.proto";
import "bosdyn/api/lease.proto";
import "bosdyn/api/license.proto";
import "bosdyn/api/world_object.proto";
import "bosdyn/api/graph_nav/map.proto";

option java_outer_classname = "RecordingProto";

// The RecordingEnvironment is a set of annotation information and a name for the
// current environment that will persist for all edges and waypoints until it is
// changed or updated
message RecordingEnvironment {
    // This will be prepended to the start of every waypoint name.
    string name_prefix = 1;
    // Persistent waypoint annotation that will be merged in
    // to all waypoints in this recording.
    Waypoint.Annotations waypoint_environment = 2;
    // Persistent edge annotation that will be merged in to all
    // waypoints in this recording.
    Edge.Annotations edge_environment = 3;
}

// The SetRecordingEnvironment request message sets a persistent recording environment
// until changed with another SetRecordingEnvironment rpc.
message SetRecordingEnvironmentRequest {
    // Common request header.
    RequestHeader header = 1;
    // Persistent environment to use while recording. This allows the
    // user to specify annotations and naming prefixes for new waypoints
    // and edges.
    RecordingEnvironment environment = 2;
    // The recording service is protected by a lease. The client must have a
    // lease to the recording service to modify its internal state.
    Lease lease = 3;
}

// The SetRecordingEnvironment response message includes the result and status of the request.
message SetRecordingEnvironmentResponse{
    // Common response header.
    ResponseHeader header = 1;
    // The results/status of the lease provided.
    LeaseUseResult lease_use_result = 2;
}

// The StartRecording request tells the recording service to begin creating waypoints with the
// specified recording_environment.
message StartRecordingRequest {
    // Common request header.
    RequestHeader header = 1;
    // The recording service is protected by a lease. The client must have a
    // lease to the recording service to modify its internal state.
    Lease lease = 2;
    // This will be merged into a copy of the existing persistent recording
    // environment and used as the environment for the created waypoint
    // and the edge from the previous waypoint to the new one.
    // It will not affect the persistent environment.
    RecordingEnvironment recording_environment = 3;
    // If filled out, asks that the record service verify that the given fiducial IDs
    // are presently visible before starting to record. This is useful for verifying
    // that the robot is where the user thinks it is in an area with known fiducials.
    repeated int32 require_fiducials = 4;
}

// The StartRecording response messge returns the first created waypoint, which is made at the location
// the robot was standing when the request was made, in addition to any status information.
message StartRecordingResponse {
    // Common response header.
    ResponseHeader header = 1;
    // The waypoint that was just created.
    Waypoint created_waypoint = 2;
    // The results/status of the lease provided.
    LeaseUseResult lease_use_result = 3;
    enum Status {
        // Status is unknown/unset.
        STATUS_UNKNOWN = 0;
        // Recording has been started.
        STATUS_OK = 1;
        // In this case we tried to start recording, but GraphNav was internally still waiting for
        // some data from the robot.
        STATUS_COULD_NOT_CREATE_WAYPOINT = 2;
        // Can't start recording because the robot is following a route.
        STATUS_FOLLOWING_ROUTE = 3;
        // When recording branches, the robot is not localized to the existing map before starting
        // to record a new branch.
        STATUS_NOT_LOCALIZED_TO_EXISTING_MAP = 4;
        // Can't start recording because the robot doesn't see the required fiducials.
        STATUS_MISSING_FIDUCIALS = 5;
        // Can't start recording because the map was too large for the license.
        STATUS_MAP_TOO_LARGE_LICENSE = 6;
        // A required remote cloud did not exist in the service directory.
        STATUS_REMOTE_CLOUD_FAILURE_NOT_IN_DIRECTORY = 7;
        // A required remote cloud did not have data.
        STATUS_REMOTE_CLOUD_FAILURE_NO_DATA = 8;
        // All fiducials are visible but at least one pose could not be determined accurately.
        STATUS_FIDUCIAL_POSE_NOT_OK = 9;
        // When recording branches, the robot is too far from the existing map when starting
        // to record a new branch.
        STATUS_TOO_FAR_FROM_EXISTING_MAP = 10;
    }
    // Return status for the request.
    Status status = 4;

    // If the status is STATUS_MISSING_FIDUCIALS, these are the fiducials that are not currently
    // visible.
    repeated int32 missing_fiducials = 5;

    // If the status is STATUS_FIDUCIAL_POSE_NOT_OK, these are the fiducials that could not be
    // localized confidently.
    repeated int32 bad_pose_fiducials = 7;

    // Large graphs can only be uploaded if the license permits them. Recording
    // will stop automatically when the graph gets too large. If StartRecording
    // is requested again after the graph gets too large, it will fail, and license
    // status will be filled out.
    LicenseInfo.Status license_status = 6;
}

// The StopRecording request message tells the robot to no longer continue adding waypoints and
// edges to the graph.
message StopRecordingRequest {
    // Common request header.
    RequestHeader header = 1;
    // The recording service is protected by a lease. The client must have a
    // lease to the recording service to modify its internal state.
    Lease lease = 2;
}

// The StopRecording response message contains the status of this request and any useful error
// information if the request fails.
message StopRecordingResponse {
    // Common response header.
    ResponseHeader header = 1;
    enum Status {
        // Status is unknown/unset.
        STATUS_UNKNOWN = 0;
        // Recording is stopped.
        STATUS_OK = 1;
        // In this case we tried to stop recording, but had an incorrect localization.
        // graph_nav is expected to be localized to the final waypoint in the chain before
        // we stop recording.
        STATUS_NOT_LOCALIZED_TO_END = 2;
        // The robot is still processing the map it created to where the robot is currently located.
        // You can't stop recording until that processing is finished.  You should not move
        // the robot, then try to stop recording again after 1-2 seconds.
        STATUS_NOT_READY_YET = 3;
    }
    // The return status for the request.
    Status status = 2;
    // If not localized to end, specifies which waypoint we are localized to.
    string error_waypoint_localized_id = 3;
    // The results/status of the lease provided.
    LeaseUseResult lease_use_result = 4;
}


// The CreateWaypoint request message specifies a name and environment the robot should
// use to generate a waypoint in the graph at it's current location.
message CreateWaypointRequest {
    // Common request header.
    RequestHeader header = 1;
    // Name of the waypoint to create. Overrides any naming prefix.
    string waypoint_name = 2;
    // This will be merged into a copy of the existing persistent recording
    // environment and used as the environment for the created waypoint
    // and the edge from the previous waypoint to the new one.
    // It will not affect the persistent environment.
    RecordingEnvironment recording_environment = 3;
    // The recording service is protected by a lease. The client must have a
    // lease to the recording service to modify its internal state.
    Lease lease = 4;
    // If filled out, asks that the record service verify that the given fiducial IDs
    // are presently visible before creating a waypoint. This is useful for verifying
    // that the robot is where the user thinks it is in an area with known fiducials.
    repeated int32 require_fiducials = 5;
    // Additional world objects to insert into this waypoint. 
    repeated WorldObject world_objects = 6;
}

// The CreateWaypoint response message contains the complete waypoint, and the associated
// edge connecting this waypoint to the graph when the request succeeds.
message CreateWaypointResponse {
    // Common response header.
    ResponseHeader header = 1;
    // The waypoint that was just created.
    Waypoint created_waypoint = 2;
    // The edge connecting the waypoint just created with the last created waypoint in the map.
    Edge created_edge = 3;
    enum Status {
        // Status is unknown/unset.
        STATUS_UNKNOWN = 0;
        // The waypoint was successfully created.
        STATUS_OK = 1;
        // Clients can only create waypoints when recording.
        STATUS_NOT_RECORDING = 2;
        // An internal server error prevented the creation of the waypoint.
        STATUS_COULD_NOT_CREATE_WAYPOINT = 3;
        // Could not see the required fiducials.
        STATUS_MISSING_FIDUCIALS = 4;
        // The map was too big to create a waypoint based on the license.
        STATUS_MAP_TOO_LARGE_LICENSE = 5;
        // A required remote cloud did not exist in the service directory.
        STATUS_REMOTE_CLOUD_FAILURE_NOT_IN_DIRECTORY = 6;
        // A required remote cloud did not have data.
        STATUS_REMOTE_CLOUD_FAILURE_NO_DATA = 7;
        // All fiducials are visible but their pose could not be determined accurately.
        STATUS_FIDUCIAL_POSE_NOT_OK = 8;

    }
    // Return status for the request.
    Status status = 5;
    // The results/status of the lease provided.
    LeaseUseResult lease_use_result = 4;

    // If the status is STATUS_MISSING_FIDUCIALS, the following fiducials
    // were not visible to the robot when trying to create the waypoint.
    repeated int32 missing_fiducials = 6;

    // If the status is STATUS_FIDUCIAL_POSE_NOT_OK, these are the fiducials that could not be
    // localized confidently.
    repeated int32 bad_pose_fiducials = 8;

    // Large graphs can only be uploaded if the license permits them. Recording
    // will stop automatically when the graph gets too large. If CreateWaypointResponse
    // is requested after the graph gets too large, it will fail, and license
    // status will be filled out.
    LicenseInfo.Status license_status = 7;
}

// The CreateEdge request message specifies an edge to create between two existing waypoints.
// The edge must not already exist in the map. This can be used to close a loop or to add any
// additional edges.
message CreateEdgeRequest {
    // Common request header.
    RequestHeader header = 1;
    // Create an edge between two existing waypoints in the map with
    // the given parameters.
    Edge edge = 2;
    // The recording service is protected by a lease. The client must have a
    // lease to the recording service to modify its internal state.
    Lease lease = 3;
}

// The CreateEdge response message contains the status of this request and any useful error
// information if the request fails.
message CreateEdgeResponse {
    // Common response header.
    ResponseHeader header = 1;
    enum Status {
        // Status is unknown/unset.
        STATUS_UNKNOWN = 0;
        // The edge was successfully created.
        STATUS_OK = 1;
        // Edge already exists with the given ID.
        STATUS_EXISTS = 2;
        // Clients can only create edges when recording.
        STATUS_NOT_RECORDING = 3;
        // One or more of the specified waypoints aren't in the map.
        STATUS_UNKNOWN_WAYPOINT = 4;
        // Specified edge did not include a transform.
        STATUS_MISSING_TRANSFORM = 5;
    }
    // Return status for the request.
    Status status = 2;
    // If set, the existing edge that caused the STATUS_EXISTS error.
    Edge error_existing_edge = 3;
    // The results/status of the lease provided.
    LeaseUseResult lease_use_result = 4;
}

// The GetRecordStatus request message asks for the current state of the recording service.
message GetRecordStatusRequest {
    // Common request header.
    RequestHeader header = 1;
}

// The GetRecordStatus response message returns whether the service is currently recording and what the
// persistent recording environment is at the time the request was recieved.
message GetRecordStatusResponse {
    // Common response header.
    ResponseHeader header = 1;
    // If true, the record service is actively recording
    // a chain.
    bool is_recording = 2;
    // The current persistent recording environment.
    RecordingEnvironment recording_environment = 3;
    enum MapState {
        MAP_STATE_UNKNOWN = 0;
        // Successfully started recording.
        MAP_STATE_OK = 1;
        // Unable to continue recording because a larger map requires an upgraded license.
        MAP_STATE_TOO_LARGE_FOR_LICENSE = 2;
    };
    MapState map_state = 4;
}
