Skip to content

Commit a68fe71

Browse files
Release v4.0.0 of Boston Dynamics Spot SDK
1 parent 5a33a7b commit a68fe71

File tree

109 files changed

+3084
-1153
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+3084
-1153
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ The official Spot SDK documentation also contains information relevant to the C+
1919
* [Payload developer documentation](https://dev.bostondynamics.com/docs/payload/readme). Payloads add additional sensing, communication, and control capabilities beyond what the base platform provides. The Payload ICD covers the mechanical, electrical, and software interfaces that Spot supports.
2020
* [Spot API protocol definition](https://dev.bostondynamics.com/docs/protos/readme). This reference guide covers the details of the protocol applications used to communicate to Spot. Application developers who wish to use a language other than Python can implement clients that speak the protocol.
2121

22-
This is version 3.3.2 of the C++ SDK. Please review the [Release Notes](docs/cpp_release_notes.md) to see what has changed.
22+
This is version 4.0.0 of the C++ SDK. Please review the [Release Notes](docs/cpp_release_notes.md) to see what has changed.
2323

2424
## Contents
2525

choreography_protos/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ Development Kit License (20191101-BDSDK-SL).
1212
<img src="https://www.bostondynamics.com/sites/default/files/2020-05/spot.png" style="max-width:50%;">
1313
</p>
1414

15-
The bosdyn-choreography-protos wheel contains the Protobuf definitions in the Boston Dynamics Choreography API. The message and service types defined in this wheel are used by the clients in [bosdyn-choreography-client](https://pypi.org/project/bosdyn-choreography-client/) wheel to communicate with the services running on the Spot robots.
15+
The bosdyn-choreography-protos wheel has been deprecated. The Python implementation for the Protobuf definitions previously stored in this build has been integrated with the [bosdyn-api wheel](https://pypi.org/project/bosdyn-api/).

choreography_protos/bosdyn/api/README.md

-15
This file was deleted.

cpp/CMakeLists.txt

+217-112
Large diffs are not rendered by default.

cpp/bosdyn/client/data_acquisition/data_acquisition_client.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,40 @@ void DataAcquisitionClient::OnCancelAcquisitionComplete(
162162
promise.set_value({ret_status, std::move(response)});
163163
}
164164

165+
// RPC to request live data for each capability
166+
std::shared_future<DataAcquisitionLiveDataResultType> DataAcquisitionClient::GetLiveDataAsync(
167+
::bosdyn::api::LiveDataRequest& request, const RPCParameters& parameters) {
168+
std::promise<DataAcquisitionLiveDataResultType> response;
169+
std::shared_future<DataAcquisitionLiveDataResultType> future = response.get_future();
170+
BOSDYN_ASSERT_PRECONDITION(m_stub != nullptr, "Stub for service is unset!");
171+
172+
MessagePumpCallBase* one_time =
173+
InitiateAsyncCall<::bosdyn::api::LiveDataRequest, ::bosdyn::api::LiveDataResponse,
174+
::bosdyn::api::LiveDataResponse>(
175+
request,
176+
std::bind(&::bosdyn::api::DataAcquisitionService::Stub::AsyncGetLiveData, m_stub.get(), _1, _2,
177+
_3),
178+
std::bind(&DataAcquisitionClient::OnLiveDataComplete, this, _1, _2, _3, _4, _5),
179+
std::move(response), parameters);
180+
181+
return future;
182+
}
183+
184+
DataAcquisitionLiveDataResultType DataAcquisitionClient::GetLiveData(
185+
::bosdyn::api::LiveDataRequest& request, const RPCParameters& parameters) {
186+
return GetLiveDataAsync(request, parameters).get();
187+
}
188+
189+
void DataAcquisitionClient::OnLiveDataComplete(
190+
MessagePumpCallBase* call, const ::bosdyn::api::LiveDataRequest& request,
191+
::bosdyn::api::LiveDataResponse&& response, const grpc::Status& status,
192+
std::promise<DataAcquisitionLiveDataResultType> promise) {
193+
::bosdyn::common::Status ret_status = ProcessResponseAndGetFinalStatus<::bosdyn::api::LiveDataResponse>(
194+
status, response, SDKErrorCode::Success);
195+
196+
promise.set_value({ret_status, std::move(response)});
197+
}
198+
165199
// Start of ServiceClient overrides.
166200
ServiceClient::QualityOfService DataAcquisitionClient::GetQualityOfService() const {
167201
return QualityOfService::NORMAL;

cpp/bosdyn/client/data_acquisition/data_acquisition_client.h

+14
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ typedef Result<::bosdyn::api::AcquireDataResponse> DataAcquisitionAcquireDataRes
2222
typedef Result<::bosdyn::api::GetStatusResponse> DataAcquisitionGetStatusResultType;
2323
typedef Result<::bosdyn::api::GetServiceInfoResponse> DataAcquisitionServiceInfoResultType;
2424
typedef Result<::bosdyn::api::CancelAcquisitionResponse> DataAcquisitionCancelAcquisitionResultType;
25+
typedef Result<::bosdyn::api::LiveDataResponse> DataAcquisitionLiveDataResultType;
2526

2627
class DataAcquisitionClient : public ServiceClient {
2728
public:
@@ -61,6 +62,14 @@ class DataAcquisitionClient : public ServiceClient {
6162
DataAcquisitionCancelAcquisitionResultType CancelAcquisition(
6263
::bosdyn::api::CancelAcquisitionRequest& request, const RPCParameters& parameters = RPCParameters());
6364

65+
// Asynchronous RPC to request live data for each capability.
66+
std::shared_future<DataAcquisitionLiveDataResultType> GetLiveDataAsync(
67+
::bosdyn::api::LiveDataRequest& request, const RPCParameters& parameters = RPCParameters());
68+
69+
// Synchronous RPC to request live data for each capability.
70+
DataAcquisitionLiveDataResultType GetLiveData(
71+
::bosdyn::api::LiveDataRequest& request, const RPCParameters& parameters = RPCParameters());
72+
6473
// Start of ServiceClient overrides.
6574
QualityOfService GetQualityOfService() const override;
6675
void SetComms(const std::shared_ptr<grpc::ChannelInterface>& channel) override;
@@ -95,6 +104,11 @@ class DataAcquisitionClient : public ServiceClient {
95104
::bosdyn::api::CancelAcquisitionResponse&& response, const grpc::Status& status,
96105
std::promise<DataAcquisitionCancelAcquisitionResultType> promise);
97106

107+
// Callback function registered for the asynchronous calls to get live data.
108+
void OnLiveDataComplete(MessagePumpCallBase* call, const ::bosdyn::api::LiveDataRequest& request,
109+
::bosdyn::api::LiveDataResponse&& response, const grpc::Status& status,
110+
std::promise<DataAcquisitionLiveDataResultType> promise);
111+
98112
std::unique_ptr<::bosdyn::api::DataAcquisitionService::Stub> m_stub;
99113

100114
// Default service name for the Data Acquisition service.

cpp/bosdyn/client/data_acquisition_store/data_acquisition_store_client.cpp

+85
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,91 @@ void DataAcquisitionStoreClient::OnStoreAlertDataComplete(
358358
promise.set_value({ret_status, std::move(response)});
359359
}
360360

361+
std::shared_future<DataAcquisitionStoreQueryStoredCapturesResultType>
362+
DataAcquisitionStoreClient::QueryStoredCapturesAsync(
363+
::bosdyn::api::QueryStoredCapturesRequest& request, const RPCParameters& parameters) {
364+
std::promise<DataAcquisitionStoreQueryStoredCapturesResultType> response;
365+
std::shared_future<DataAcquisitionStoreQueryStoredCapturesResultType> future =
366+
response.get_future();
367+
BOSDYN_ASSERT_PRECONDITION(m_stub != nullptr, "Stub for service is unset!");
368+
369+
MessagePumpCallBase* one_time =
370+
InitiateResponseStreamAsyncCall<::bosdyn::api::QueryStoredCapturesRequest,
371+
::bosdyn::api::DataChunk,
372+
::bosdyn::api::QueryStoredCapturesResponse>(
373+
request,
374+
std::bind(&::bosdyn::api::DataAcquisitionStoreService::Stub::AsyncQueryStoredCaptures,
375+
m_stub.get(), _1, _2, _3, _4),
376+
std::bind(&DataAcquisitionStoreClient::OnQueryStoredCapturesComplete, this, _1, _2, _3,
377+
_4, _5),
378+
std::move(response), parameters);
379+
380+
return future;
381+
}
382+
383+
DataAcquisitionStoreQueryStoredCapturesResultType DataAcquisitionStoreClient::QueryStoredCaptures(
384+
::bosdyn::api::QueryStoredCapturesRequest& request, const RPCParameters& parameters) {
385+
return QueryStoredCapturesAsync(request, parameters).get();
386+
}
387+
388+
void DataAcquisitionStoreClient::OnQueryStoredCapturesComplete(
389+
MessagePumpCallBase* call, const ::bosdyn::api::QueryStoredCapturesRequest& request,
390+
std::vector<::bosdyn::api::DataChunk>&& responses, const grpc::Status& status,
391+
std::promise<DataAcquisitionStoreQueryStoredCapturesResultType> promise) {
392+
std::vector<const ::bosdyn::api::DataChunk*> chunks;
393+
for (auto& chunk : responses) {
394+
chunks.push_back(&chunk);
395+
}
396+
397+
auto response_result =
398+
MessageFromDataChunks<::bosdyn::api::QueryStoredCapturesResponse>(chunks);
399+
if (!response_result) {
400+
promise.set_value(response_result);
401+
return;
402+
}
403+
404+
::bosdyn::api::QueryStoredCapturesResponse&& response = response_result.move();
405+
auto ret_status = ProcessResponseAndGetFinalStatus<::bosdyn::api::QueryStoredCapturesResponse>(
406+
status, response, SDKErrorCode::Success);
407+
promise.set_value({ret_status, std::move(response)});
408+
}
409+
410+
std::shared_future<DataAcquisitionStoreQueryMaxCaptureIdResultType>
411+
DataAcquisitionStoreClient::QueryMaxCaptureIdAsync(const RPCParameters& parameters) {
412+
::bosdyn::api::QueryMaxCaptureIdRequest request;
413+
std::promise<DataAcquisitionStoreQueryMaxCaptureIdResultType> response;
414+
std::shared_future<DataAcquisitionStoreQueryMaxCaptureIdResultType> future =
415+
response.get_future();
416+
BOSDYN_ASSERT_PRECONDITION(m_stub != nullptr, "Stub for service is unset!");
417+
418+
MessagePumpCallBase* one_time = InitiateAsyncCall<::bosdyn::api::QueryMaxCaptureIdRequest,
419+
::bosdyn::api::QueryMaxCaptureIdResponse,
420+
::bosdyn::api::QueryMaxCaptureIdResponse>(
421+
request,
422+
std::bind(&::bosdyn::api::DataAcquisitionStoreService::Stub::AsyncQueryMaxCaptureId,
423+
m_stub.get(), _1, _2, _3),
424+
std::bind(&DataAcquisitionStoreClient::OnQueryMaxCaptureIdComplete, this, _1, _2, _3, _4,
425+
_5),
426+
std::move(response), parameters);
427+
428+
return future;
429+
}
430+
431+
DataAcquisitionStoreQueryMaxCaptureIdResultType DataAcquisitionStoreClient::QueryMaxCaptureId(
432+
const RPCParameters& parameters) {
433+
return QueryMaxCaptureIdAsync(parameters).get();
434+
}
435+
436+
void DataAcquisitionStoreClient::OnQueryMaxCaptureIdComplete(
437+
MessagePumpCallBase* call, const ::bosdyn::api::QueryMaxCaptureIdRequest& request,
438+
::bosdyn::api::QueryMaxCaptureIdResponse&& response, const grpc::Status& status,
439+
std::promise<DataAcquisitionStoreQueryMaxCaptureIdResultType> promise) {
440+
::bosdyn::common::Status ret_status =
441+
ProcessResponseAndGetFinalStatus<::bosdyn::api::QueryMaxCaptureIdResponse>(
442+
status, response, SDKErrorCode::Success);
443+
444+
promise.set_value({ret_status, std::move(response)});
445+
}
361446

362447
// Start of ServiceClient overrides.
363448
ServiceClient::QualityOfService DataAcquisitionStoreClient::GetQualityOfService() const {

cpp/bosdyn/client/data_acquisition_store/data_acquisition_store_client.h

+30
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ typedef Result<::bosdyn::api::StoreMetadataResponse> DataAcquisitionStoreStoreMe
3030
typedef Result<::bosdyn::api::ListStoredAlertDataResponse>
3131
DataAcquisitionStoreListStoredAlertDataResultType;
3232
typedef Result<::bosdyn::api::StoreAlertDataResponse> DataAcquisitionStoreStoreAlertDataResultType;
33+
typedef Result<::bosdyn::api::QueryStoredCapturesResponse>
34+
DataAcquisitionStoreQueryStoredCapturesResultType;
35+
typedef Result<::bosdyn::api::QueryMaxCaptureIdResponse>
36+
DataAcquisitionStoreQueryMaxCaptureIdResultType;
3337

3438
class DataAcquisitionStoreClient : public ServiceClient {
3539
public:
@@ -127,6 +131,23 @@ class DataAcquisitionStoreClient : public ServiceClient {
127131
::bosdyn::api::StoreAlertDataRequest& request,
128132
const RPCParameters& parameters = RPCParameters());
129133

134+
// Asynchronous RPC to trigger data acquisition store to query stored captures.
135+
std::shared_future<DataAcquisitionStoreQueryStoredCapturesResultType> QueryStoredCapturesAsync(
136+
::bosdyn::api::QueryStoredCapturesRequest& request,
137+
const RPCParameters& parameters = RPCParameters());
138+
139+
// Synchronous RPC to trigger data acquisition store to query stored captures.
140+
DataAcquisitionStoreQueryStoredCapturesResultType QueryStoredCaptures(
141+
::bosdyn::api::QueryStoredCapturesRequest& request,
142+
const RPCParameters& parameters = RPCParameters());
143+
144+
// Asynchronous RPC to get the maximum stored capture_id.
145+
std::shared_future<DataAcquisitionStoreQueryMaxCaptureIdResultType> QueryMaxCaptureIdAsync(
146+
const RPCParameters& parameters = RPCParameters());
147+
148+
// Synchronous RPC to get the maximum stored capture_id.
149+
DataAcquisitionStoreQueryMaxCaptureIdResultType QueryMaxCaptureId(
150+
const RPCParameters& parameters = RPCParameters());
130151

131152
// Start of ServiceClient overrides.
132153
QualityOfService GetQualityOfService() const override;
@@ -197,6 +218,15 @@ class DataAcquisitionStoreClient : public ServiceClient {
197218
::bosdyn::api::StoreAlertDataResponse&& response, const grpc::Status& status,
198219
std::promise<DataAcquisitionStoreStoreAlertDataResultType> promise);
199220

221+
void OnQueryStoredCapturesComplete(
222+
MessagePumpCallBase* call, const ::bosdyn::api::QueryStoredCapturesRequest& request,
223+
std::vector<::bosdyn::api::DataChunk>&& responses, const grpc::Status& status,
224+
std::promise<DataAcquisitionStoreQueryStoredCapturesResultType> promise);
225+
226+
void OnQueryMaxCaptureIdComplete(
227+
MessagePumpCallBase* call, const ::bosdyn::api::QueryMaxCaptureIdRequest& request,
228+
::bosdyn::api::QueryMaxCaptureIdResponse&& response, const grpc::Status& status,
229+
std::promise<DataAcquisitionStoreQueryMaxCaptureIdResultType> promise);
200230

201231
std::unique_ptr<::bosdyn::api::DataAcquisitionStoreService::Stub> m_stub;
202232

cpp/bosdyn/client/graph_nav/graph_nav_error_codes.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ DEFINE_PROTO_ENUM_ERRORCODE_IMPL_GRAPHNAV(NavigateToAnchorResponse_Status, valco
1919
// NOTE: NavigationFeedbackResponse is not converted to std::error_code on purpose.
2020
DEFINE_PROTO_ENUM_ERRORCODE_IMPL_GRAPHNAV(DownloadWaypointSnapshotResponse_Status, valcode == 1)
2121
DEFINE_PROTO_ENUM_ERRORCODE_IMPL_GRAPHNAV(DownloadEdgeSnapshotResponse_Status, valcode == 1)
22+
DEFINE_PROTO_ENUM_ERRORCODE_IMPL_GRAPHNAV(UploadWaypointSnapshotResponse_Status, valcode == 1)
23+
DEFINE_PROTO_ENUM_ERRORCODE_IMPL_GRAPHNAV(UploadGraphResponse_Status, valcode == 1)
24+

cpp/bosdyn/client/lease/lease.cpp

+26-13
Original file line numberDiff line numberDiff line change
@@ -196,28 +196,43 @@ bool Lease::IsValid() const {
196196
return !m_lease_proto.resource().empty() && m_lease_proto.sequence_size() > 0;
197197
}
198198

199-
void Lease::UpdateFromLeaseUseResult(const ::bosdyn::api::LeaseUseResult& lease_use_result) {
199+
bool Lease::UpdateFromLeaseUseResult(const ::bosdyn::api::LeaseUseResult& lease_use_result) {
200200
if (lease_use_result.status() == ::bosdyn::api::LeaseUseResult::STATUS_OLDER) {
201-
// The lease from the lease wallet was an older lease.
202-
if (Compare(Lease(lease_use_result.attempted_lease())) == CompareResult::SAME) {
203-
// If the lease use result's lease matches this current lease, then mark it as other
204-
// owner since it was found to be an older lease and we never incremented it.
205-
m_lease_status = LeaseStatus::OTHER_OWNER;
201+
// The lease was reported as being too old. Check if that applies to our current lease.
202+
Lease latest_known_lease(lease_use_result.latest_known_lease());
203+
if (latest_known_lease.IsValid()) {
204+
const auto cmp = Compare(latest_known_lease);
205+
if (cmp == Lease::CompareResult::NEWER || cmp == Lease::CompareResult::SAME) {
206+
// The attempted lease was older, but the lease in the wallet has been updated in
207+
// the meantime to something that is newer than what the robot has seen, so this
208+
// OLDER result is no longer relevant.
209+
return false;
210+
}
206211
}
212+
// The lease from the lease wallet was an older lease.
213+
m_lease_status = LeaseStatus::OTHER_OWNER;
214+
return true;
207215
} else if (lease_use_result.status() == ::bosdyn::api::LeaseUseResult::STATUS_WRONG_EPOCH) {
208-
// The lease from the lease wallet is the wrong epoch.
209-
if (Compare(Lease(lease_use_result.attempted_lease())) == CompareResult::SAME) {
216+
// The lease is reported as having the wrong epoch.
217+
// Check if that applies to our current lease.
218+
if (m_lease_proto.epoch() != lease_use_result.latest_known_lease().epoch()) {
210219
// If the lease use result's lease matches this current lease, then mark it as unowned
211220
// because it is now entirely wrong (different epochs) for the resource.
212221
m_lease_status = LeaseStatus::UNOWNED;
222+
return true;
213223
}
224+
return false;
214225
} else if (lease_use_result.status() == ::bosdyn::api::LeaseUseResult::STATUS_REVOKED) {
215-
// The lease from the lease wallet is the wrong epoch.
216-
if (Compare(Lease(lease_use_result.attempted_lease())) == CompareResult::SAME) {
226+
// The lease was reported as revoked. Check if that applies to our current lease.
227+
auto comparison = Compare(Lease(lease_use_result.attempted_lease()));
228+
if (comparison == CompareResult::SAME || comparison == CompareResult::SUB_LEASE) {
217229
// If the lease use result's lease matches this current lease, then mark it as revoked.
218230
m_lease_status = LeaseStatus::REVOKED;
231+
return true;
219232
}
233+
return false;
220234
}
235+
return true;
221236
}
222237

223238
Lease Lease::SplitLease(const std::string& resource, const ResourceHierarchy& hierarchy) const {
@@ -230,9 +245,7 @@ Lease Lease::SplitLease(const std::string& resource, const ResourceHierarchy& hi
230245
}
231246

232247
Lease result(*this);
233-
const auto& sub_hierarchy = hierarchy.GetHierarchy(resource);
234-
const auto& resource_tree = sub_hierarchy.ResourceTree();
235-
result.m_lease_proto.set_resource(resource_tree.resource());
248+
result.m_lease_proto.set_resource(resource);
236249
return result;
237250
}
238251

cpp/bosdyn/client/lease/lease.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,9 @@ class Lease {
215215
bool IsValid() const;
216216

217217
// Update internal instance of LeaseState from given lease.
218-
void UpdateFromLeaseUseResult(const ::bosdyn::api::LeaseUseResult& lease_use_result);
218+
// Returns true if the lease_use_result is still applicable to this lease. False if it
219+
// has been superseded.
220+
bool UpdateFromLeaseUseResult(const ::bosdyn::api::LeaseUseResult& lease_use_result);
219221

220222
// Get the current ownership status of the lease.
221223
LeaseStatus GetLeaseStatus() const { return m_lease_status; }

0 commit comments

Comments
 (0)