UNPKG

spot-sdk-js

Version:

Develop applications and payloads for Spot using the unofficial Boston Dynamics Spot Node.js SDK.

355 lines (300 loc) 14.2 kB
const map_pb = require('../bosdyn/api/graph_nav/map_pb'); const nav_pb = require('../bosdyn/api/graph_nav/nav_pb'); const recording_pb = require('../bosdyn/api/graph_nav/recording_pb'); const recording_service_pb = require('../bosdyn/api/graph_nav/recording_service_pb'); const recording_service = require('../bosdyn/api/graph_nav/recording_service_grpc_pb'); const { BaseClient, error_factory, handle_unset_status_error, handle_common_header_errors, handle_lease_use_result_errors, common_header_errors } = require('./common'); const {ResponseError} = require('./exceptions'); const WaypointRegion = { DEFAULT_REGION: 1, EMPTY_REGION: 2, CIRCLE_REGION: 3 }; class GraphNavRecordingServiceClient extends BaseClient { static default_service_name = 'recording-service'; static service_type = 'bosdyn.api.graph_nav.GraphNavRecordingService'; constructor(){ super(recording_service.GraphNavRecordingServiceClient); } async start_recording(lease = null, recording_environment = null, args){ const request = this._build_start_recording_request(lease, recording_environment); return await this.call(this._stub.startRecording, request, _get_status, _start_recording_error, args); } start_recording_async(lease = null, recording_environment = null, args){ const request = this._build_start_recording_request(lease, recording_environment); return this.call_async(this._stub.startRecording, request, _get_status, _start_recording_error, args); } async stop_recording(lease = null, args){ const request = this._build_stop_recording_request(lease); return await this.call(this._stub.stopRecording, request, _get_status, _stop_recording_error, args); } stop_recording_async(lease = null, args){ const request = this._build_stop_recording_request(lease); return this.call_async(this._stub.stopRecording, request, _get_status, _stop_recording_error, args); } async get_record_status(args){ const request = this._build_get_record_status_request(); return await this.call(this._stub.getRecordStatus, request, _get_response, common_header_errors, args); } get_record_status_async(args){ const request = this._build_get_record_status_request(); return this.call_async(this._stub.getRecordStatus, request, _get_response, common_header_errors, args); } async set_recording_environment(lease = null, recording_environment = null, args){ const request = this._build_set_recording_environment_request(lease, recording_environment); return await this.call(this._stub.SetRecordingEnvironment, request, null, common_header_errors, args); } set_recording_environment_async(lease = null, recording_environment = null, args){ const request = this._build_set_recording_environment_request(lease, recording_environment); return this.call_async(this._stub.setRecordingEnvironment, request, null, common_header_errors, args); } async create_waypoint(lease = null, waypoint_name = null, recording_environment = null, args){ const request = this._build_create_waypoint_request(waypoint_name, recording_environment, lease); return await this.call(this._stub.createWaypoint, request, _get_response, _create_waypoint_error, args); } create_waypoint_async(lease = null, waypoint_name = null, recording_environment = null, args){ const request = this._build_create_waypoint_request(waypoint_name, recording_environment, lease); return this.call_async(this._stub.createWaypoint, request, _get_response, _create_waypoint_error, args); } async create_edge(lease = null, edge = null, args){ const request = this._build_create_edge_request(edge, lease); return await this.call(this._stub.createEdge, request, _get_status, _create_edge_error, args); } create_edge_async(lease = null, edge = null, args){ var request = this._build_create_edge_request(edge, lease); return this.call_async(this._stub.createEdge, request, _get_status, _create_edge_error, args); } static _build_start_recording_request(lease, recording_env){ return new recording_pb.StartRecordingRequest().setLease(lease).setRecordingEnvironment(recording_env); } static _build_stop_recording_request(lease){ return new recording_pb.StopRecordingRequest().setLease(lease); } static _build_get_record_status_request(){ return new recording_pb.GetRecordStatusRequest(); } static _build_set_recording_environment_request(lease, recording_env){ return new recording_pb.SetRecordingEnvironmentRequest().setEnvironment(recording_env).setLease(lease); } static _build_create_waypoint_request(waypoint_name, recording_env, lease){ const req = new recording_pb.CreateWaypointRequest() .setWaypointName(waypoint_name) .setRecordingEnvironment(recording_env) .setLease(lease); return req; } static _build_create_edge_request(edge, lease){ return new recording_pb.CreateEdgeRequest().setEdge(edge).setLease(lease); } static make_recording_environment(name, waypoint_env, edge_env){ const req = new recording_pb.RecordingEnvironment() .setNamePrefix(name) .setWaypointEnvironment(waypoint_env) .setEdgeEnvironment(edge_env); return req; } static make_waypoint_environment(name, region = WaypointRegion.DEFAULT_REGION, dist_2d = null, args){ const waypoint_env = new map_pb.Waypoint.Annotations().setName(name); if(region == WaypointRegion.DEFAULT_REGION){ const scan_match_region = new graph_nav.Waypoint.Annotations.LocalizeRegion() .setDefaultRegion(new map_pb.Waypoint.Annotations.LocalizeRegion.Default()) .setState(map_pb.AnnotationState.ANNOTATION_STATE_SET); waypoint_env.setScanMatchRegion(scan_match_region); }else if(region == WaypointRegion.EMPTY_REGION){ const scan_match_region = new graph_nav.Waypoint.Annotations.LocalizeRegion() .setEmpty(new map_pb.Waypoint.Annotations.LocalizeRegion.Empty()) .setState(map_pb.AnnotationState.ANNOTATION_STATE_SET); waypoint_env.setScanMatchRegion(scan_match_region); }else if(region == WaypointRegion.CIRCLE_REGION){ const scan_match_region = new graph_nav.Waypoint.Annotations.LocalizeRegion(); if(dist_2d != null){ scan_match_region.setCircle(new map_pb.Waypoint.Annotations.LocalizeRegion.Circle2D().setDist2d(dist_2d)); scan_match_region.setState(map_pb.AnnotationState.ANNOTATION_STATE_SET); }else{ scan_match_region.setState(map_pb.AnnotationState.ANNOTATION_STATE_NONE); } waypoint_env.setScanMatchRegion(scan_match_region); }else{ const scan_match_region = new graph_nav.Waypoint.Annotations.LocalizeRegion() .setState(map_pb.AnnotationState.ANNOTATION_STATE_NONE); waypoint_env.setScanMatchRegion(scan_match_region); } return waypoint_env; } static make_edge_environment(vel_limit = null, direction_constraint = map_pb.Edge.Annotations.DirectionConstraint.DIRECTION_CONSTRAINT_NONE, require_alignment = false, flat_ground = false, ground_mu_hint = .8, grated_floor = false){ const edge_env = new map_pb.Edge.Annotations(); edge_env.setRequireAlignment(require_alignment); edge_env.setFlatGround(flat_ground); edge_env.setGratedFloor(grated_floor); if (ground_mu_hint > 0) edge_env.setGroundMuHint(ground_mu_hint); if(vel_limit != null) edge_env.setVelLimit(vel_limit); edge_env.setDirectionConstraint(direction_constraint); const stairs = new map_pb.Edge.Annotations.StairData().setState(map_pb.AnnotationState.ANNOTATION_STATE_NONE) edge_env.setStairs(stairs); return edge_env; } static make_edge(from_waypoint_id, to_waypoint_id, from_tform_to, edge_environment = null){ const edge_id = new map_pb.Edge.Id().setFromWaypoint(from_waypoint_id).setToWaypoint(to_waypoint_id); const edge = new map_pb.Edge().setId(edge_id).setFromTformTo(from_tform_to); if(edge_environment != null) edge.setAnnotations(edge_environment); return edge; } }; class RecordingServiceResponseError extends ResponseError { constructor(msg){ super(msg); this.name = 'RecordingServiceResponseError'; } }; class CouldNotCreateWaypointError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'CouldNotCreateWaypointError'; } }; class NotRecordingError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'NotRecordingError'; } }; class UnknownWaypointError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'UnknownWaypointError'; } }; class EdgeExistsError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'EdgeExistsError'; } }; class EdgeMissingTransformError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'EdgeMissingTransformError'; } }; class NotLocalizedToEndError extends ResponseError { constructor(msg){ super(msg); this.name = 'NotLocalizedToEndError'; } }; class FollowingRouteError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'FollowingRouteError'; } }; class NotLocalizedToExistingMapError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'NotLocalizedToExistingMapError'; } }; class RemoteCloudFailureNotInDirectoryError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'RemoteCloudFailureNotInDirectoryError'; } }; class RemoteCloudFailureNoDataError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'RemoteCloudFailureNoDataError'; } }; class NotReadyYetError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'NotReadyYetError'; } }; class MapTooLargeLicenseError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'MapTooLargeLicenseError'; } }; class MissingFiducialsError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'MissingFiducialsError'; } }; class FiducialPoseError extends RecordingServiceResponseError { constructor(msg){ super(msg); this.name = 'FiducialPoseError'; } }; function _get_status(response){ return response.getStatus(); } function _get_response(response){ return response; } const _START_RECORDING_STATUS_TO_ERROR = { STATUS_OK: [null, null], STATUS_COULD_NOT_CREATE_WAYPOINT: [CouldNotCreateWaypointError, 'Service could not create a waypoint.'], STATUS_FOLLOWING_ROUTE: [FollowingRouteError, 'Cannot start recording while the robot is already following a route.'], STATUS_NOT_LOCALIZED_TO_EXISTING_MAP: [NotLocalizedToExistingMapError, 'The robot is not localized to the existing map and cannot start recording.'], STATUS_MISSING_FIDUCIALS: [MissingFiducialsError, 'One or more required fiducials were not detected.'], STATUS_MAP_TOO_LARGE_LICENSE: [MapTooLargeLicenseError, 'Map exceeds the size allowed by the license.'], STATUS_REMOTE_CLOUD_FAILURE_NOT_IN_DIRECTORY: [RemoteCloudFailureNotInDirectoryError, 'Failed to start recording because a remote point cloud (e.g. a LIDAR) is not registered to the service directory.'], STATUS_REMOTE_CLOUD_FAILURE_NO_DATA: [RemoteCloudFailureNoDataError, 'Failed to start recording because a remote point cloud (e.g. a LIDAR) is not delivering data.'], STATUS_FIDUCIAL_POSE_NOT_OK: [FiducialPoseError, 'The pose of one or more required fiducials could not be determined accurately.'] }; const _STOP_RECORDING_STATUS_TO_ERROR = { STATUS_OK: [null, null], STATUS_NOT_LOCALIZED_TO_END: [NotLocalizedToEndError, 'Stop recording failed to localize to the last created waypoint.'], STATUS_NOT_READY_YET: [NotReadyYetError, 'The service is processing the map at it\'s current position. Try again in 1-2 seconds.'] }; const _CREATE_WAYPOINT_STATUS_TO_ERROR = { STATUS_OK: [null, null], STATUS_NOT_RECORDING: [NotRecordingError, 'The recording service has not been started.'], STATUS_COULD_NOT_CREATE_WAYPOINT: [CouldNotCreateWaypointError, 'Service could not create a waypoint.'], STATUS_REMOTE_CLOUD_FAILURE_NOT_IN_DIRECTORY: [RemoteCloudFailureNotInDirectoryError, 'Failed to start recording because a remote point cloud (e.g. a LIDAR) is not registered to the service directory.'], STATUS_REMOTE_CLOUD_FAILURE_NO_DATA: [RemoteCloudFailureNoDataError, 'Failed to start recording because a remote point cloud (e.g. a LIDAR) is not delivering data.'] }; const _CREATE_EDGE_STATUS_TO_ERROR = { STATUS_OK: [null, null], STATUS_NOT_RECORDING: [NotRecordingError, 'The recording service has not been started.'], STATUS_EXISTS: [EdgeExistsError, 'The edge requested with the given ID already exists in the map.'], STATUS_UNKNOWN_WAYPOINT: [UnknownWaypointError, 'The edge requested has a waypoint id that is unknown.'], STATUS_MISSING_TRANSFORM: [EdgeMissingTransformError, 'The edge requested is missing the from_T_to transform in the edge.'] }; function _start_recording_error(response){ return error_factory(response, response.getStatus(), Object.keys(recording_pb.StartRecordingResponse.Status), _START_RECORDING_STATUS_TO_ERROR); } function _stop_recording_error(response){ return error_factory(response, response.getStatus(), Object.keys(recording_pb.StopRecordingResponse.Status), _STOP_RECORDING_STATUS_TO_ERROR); } function _create_waypoint_error(response){ return error_factory(response, response.getStatus(), Object.keys(recording_pb.CreateWaypointResponse.Status), _CREATE_WAYPOINT_STATUS_TO_ERROR); } function _create_edge_error(response){ return error_factory(response, response.getStatus(), Object.keys(recording_pb.CreateEdgeResponse.Status), _CREATE_EDGE_STATUS_TO_ERROR); } module.exports = { GraphNavRecordingServiceClient, RecordingServiceResponseError, CouldNotCreateWaypointError, NotRecordingError, UnknownWaypointError, EdgeExistsError, EdgeMissingTransformError, NotLocalizedToEndError, FollowingRouteError, NotLocalizedToExistingMapError, NotReadyYetError };