Skip to content

Commit 1789a26

Browse files
Merge branch 'boston-dynamics:master' into master
2 parents bc6a394 + b5b8a83 commit 1789a26

27 files changed

+1717
-19
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 4.0.0 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.2 of the C++ SDK. Please review the [Release Notes](docs/cpp_release_notes.md) to see what has changed.
2323

2424
## Contents
2525

cpp/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# This file is autogenerated.
88

99
cmake_minimum_required (VERSION 3.10.2)
10-
project (bosdyn VERSION 4.0.0)
10+
project (bosdyn VERSION 4.0.2)
1111

1212
# Dependencies:
1313
find_package(protobuf REQUIRED)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Copyright (c) 2023 Boston Dynamics, Inc. All rights reserved.
3+
*
4+
* Downloading, reproducing, distributing or otherwise using the SDK Software
5+
* is subject to the terms and conditions of the Boston Dynamics Software
6+
* Development Kit License (20191101-BDSDK-SL).
7+
*/
8+
9+
10+
#include "bosdyn/client/error_codes/joint_control_stream_error_code.h"
11+
#include "bosdyn/client/error_codes/error_type_condition.h"
12+
#include "bosdyn/client/error_codes/sdk_error_code.h"
13+
#include "bosdyn/common/success_condition.h"
14+
15+
namespace { // anonymous namespace
16+
17+
struct JointControlStreamErrorCodeCategory : std::error_category {
18+
const char* name() const noexcept override;
19+
std::string message(int ev) const override;
20+
bool equivalent(int valcode, const std::error_condition& cond) const noexcept override;
21+
};
22+
23+
bool JointControlStreamErrorCodeCategory::equivalent(
24+
int valcode, const std::error_condition& cond) const noexcept {
25+
if (cond == SuccessCondition::Success) return (valcode == 0);
26+
if (cond == ErrorTypeCondition::SDKError) return true;
27+
return false;
28+
}
29+
30+
const char* JointControlStreamErrorCodeCategory::name() const noexcept {
31+
return "JointControlStreamErrorCode";
32+
}
33+
34+
std::string JointControlStreamErrorCodeCategory::message(int value) const {
35+
switch (static_cast<JointControlStreamErrorCode>(value)) {
36+
case JointControlStreamErrorCode::Success:
37+
return "Success";
38+
case JointControlStreamErrorCode::RequestWriterFailed:
39+
return "Getting request writer failed";
40+
case JointControlStreamErrorCode::ResponseReaderFailed:
41+
return "Getting response reader failed";
42+
case JointControlStreamErrorCode::StreamingFailed:
43+
return "Streaming for joint control failed";
44+
}
45+
return "(JointControlStreamErrorCode: unrecognized error)";
46+
}
47+
48+
const JointControlStreamErrorCodeCategory JointControlStreamErrorCodeCategory_category{};
49+
50+
} // anonymous namespace
51+
52+
std::error_code make_error_code(JointControlStreamErrorCode value) {
53+
return {static_cast<int>(value), JointControlStreamErrorCodeCategory_category};
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Copyright (c) 2023 Boston Dynamics, Inc. All rights reserved.
3+
*
4+
* Downloading, reproducing, distributing or otherwise using the SDK Software
5+
* is subject to the terms and conditions of the Boston Dynamics Software
6+
* Development Kit License (20191101-BDSDK-SL).
7+
*/
8+
9+
10+
#pragma once
11+
12+
#include <system_error>
13+
14+
// Need to be more specific or removed when streaming client is changed to use general form as we
15+
// did in other clients.
16+
enum class JointControlStreamErrorCode {
17+
// Success
18+
Success = 0,
19+
// Getting request_writer failed
20+
RequestWriterFailed = 1,
21+
// Getting response reader failed
22+
ResponseReaderFailed = 2,
23+
// Streaming for joint control failed
24+
StreamingFailed = 3,
25+
};
26+
27+
namespace std {
28+
template <>
29+
struct is_error_code_enum<JointControlStreamErrorCode> : true_type {};
30+
} // namespace std
31+
32+
std::error_code make_error_code(JointControlStreamErrorCode);

cpp/bosdyn/client/robot_command/robot_command_builder.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ ::bosdyn::api::RobotCommand SafePowerOffCommand() {
5252
return command;
5353
}
5454

55+
::bosdyn::api::RobotCommand JointCommand() {
56+
::bosdyn::api::RobotCommand command;
57+
command.mutable_full_body_command()->mutable_joint_request();
58+
return command;
59+
}
60+
5561
::bosdyn::api::RobotCommand SitCommand(const ::bosdyn::api::spot::MobilityParams& params) {
5662
::bosdyn::api::RobotCommand command;
5763
command.mutable_synchronized_command()->mutable_mobility_command()->mutable_params()->CopyFrom(

cpp/bosdyn/client/robot_command/robot_command_builder.h

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ ::bosdyn::api::RobotCommand SelfrightCommand();
6565
*/
6666
::bosdyn::api::RobotCommand SafePowerOffCommand();
6767

68+
::bosdyn::api::RobotCommand JointCommand();
69+
6870
/**
6971
* Command the robot to sit.
7072
*

cpp/bosdyn/client/robot_command/robot_command_helpers.cpp

+60-8
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,23 @@ const std::error_category& BlockingRobotCommandErrorCategory() {
6767
RobotCommandFeedbackResultType BlockUntilArmArrives(
6868
::bosdyn::client::RobotCommandClient& robot_command_client, int cmd_id, int timeout_sec,
6969
int poll_period_msec) {
70+
return BlockUntilArmArrives(robot_command_client, cmd_id, std::chrono::seconds(timeout_sec),
71+
std::chrono::milliseconds(poll_period_msec));
72+
}
73+
74+
RobotCommandFeedbackResultType BlockUntilArmArrives(
75+
::bosdyn::client::RobotCommandClient& robot_command_client, int cmd_id,
76+
::bosdyn::common::Duration timeout, ::bosdyn::common::Duration poll_period) {
7077
::bosdyn::api::RobotCommandFeedbackRequest feedback_req;
7178
feedback_req.set_robot_command_id(cmd_id);
7279

7380
::bosdyn::client::RobotCommandFeedbackResultType feedback_res;
7481

75-
auto start_time = ::bosdyn::common::NowNsec();
76-
const auto end_time = start_time + ::bosdyn::common::SecToNsec(timeout_sec);
82+
auto start_time = ::bosdyn::common::NsecSinceEpoch();
83+
const auto end_time = start_time + timeout;
7784

78-
while (timeout_sec <= 0 || ::bosdyn::common::NowNsec() < end_time) {
85+
while (timeout <= ::bosdyn::common::Duration(0) ||
86+
::bosdyn::common::NsecSinceEpoch() < end_time) {
7987
feedback_res = robot_command_client.RobotCommandFeedback(feedback_req);
8088
// If the RPC timed out but this function hasn't timed out, keep trying.
8189
if (!feedback_res.status &&
@@ -137,7 +145,7 @@ RobotCommandFeedbackResultType BlockUntilArmArrives(
137145
feedback_res.move()};
138146
}
139147

140-
std::this_thread::sleep_for(std::chrono::milliseconds(poll_period_msec));
148+
std::this_thread::sleep_for(poll_period);
141149
}
142150
return {{BlockingRobotCommandErrorCode::CommandTimeoutError, "ArmCommand failed or timed out."},
143151
feedback_res.response};
@@ -146,15 +154,23 @@ RobotCommandFeedbackResultType BlockUntilArmArrives(
146154
RobotCommandFeedbackResultType BlockUntilGripperArrives(
147155
::bosdyn::client::RobotCommandClient& robot_command_client, int cmd_id, int timeout_sec,
148156
int poll_period_msec) {
157+
return BlockUntilGripperArrives(robot_command_client, cmd_id, std::chrono::seconds(timeout_sec),
158+
std::chrono::milliseconds(poll_period_msec));
159+
}
160+
161+
RobotCommandFeedbackResultType BlockUntilGripperArrives(
162+
::bosdyn::client::RobotCommandClient& robot_command_client, int cmd_id,
163+
::bosdyn::common::Duration timeout, ::bosdyn::common::Duration poll_period) {
149164
::bosdyn::api::RobotCommandFeedbackRequest feedback_req;
150165
feedback_req.set_robot_command_id(cmd_id);
151166

152167
::bosdyn::client::RobotCommandFeedbackResultType feedback_res;
153168

154-
auto start_time = ::bosdyn::common::NowNsec();
155-
const auto end_time = start_time + ::bosdyn::common::SecToNsec(timeout_sec);
169+
auto start_time = ::bosdyn::common::NsecSinceEpoch();
170+
const auto end_time = start_time + timeout;
156171

157-
while (timeout_sec <= 0 || ::bosdyn::common::NowNsec() < end_time) {
172+
while (timeout <= ::bosdyn::common::Duration(0) ||
173+
::bosdyn::common::NsecSinceEpoch() < end_time) {
158174
feedback_res = robot_command_client.RobotCommandFeedback(feedback_req);
159175
// If the RPC timed out but this function hasn't timed out, keep trying.
160176
if (!feedback_res.status &&
@@ -174,12 +190,48 @@ RobotCommandFeedbackResultType BlockUntilGripperArrives(
174190
return {{BlockingRobotCommandErrorCode::Success}, feedback_res.move()};
175191
}
176192

177-
std::this_thread::sleep_for(std::chrono::milliseconds(poll_period_msec));
193+
std::this_thread::sleep_for(poll_period);
178194
}
179195
return {{BlockingRobotCommandErrorCode::CommandTimeoutError,
180196
"The GripperCommand failed or timed out."},
181197
feedback_res.move()};
182198
}
199+
200+
RobotCommandFeedbackResultType BlockUntilStandComplete(
201+
::bosdyn::client::RobotCommandClient& robot_command_client, int cmd_id,
202+
::bosdyn::common::Duration timeout, ::bosdyn::common::Duration poll_period) {
203+
::bosdyn::api::RobotCommandFeedbackRequest feedback_req;
204+
feedback_req.set_robot_command_id(cmd_id);
205+
206+
::bosdyn::client::RobotCommandFeedbackResultType feedback_res;
207+
208+
auto start_time = ::bosdyn::common::NsecSinceEpoch();
209+
const auto end_time = start_time + timeout;
210+
211+
while (timeout <= ::bosdyn::common::Duration(0) ||
212+
::bosdyn::common::NsecSinceEpoch() < end_time) {
213+
feedback_res = robot_command_client.RobotCommandFeedback(feedback_req);
214+
// If the RPC timed out but this function hasn't timed out, keep trying.
215+
if (!feedback_res.status &&
216+
feedback_res.status.code() != ::bosdyn::client::RPCErrorCode::TimedOutError) {
217+
return feedback_res;
218+
}
219+
220+
auto stand_feedback = feedback_res.response.feedback()
221+
.synchronized_feedback()
222+
.mobility_command_feedback()
223+
.stand_feedback();
224+
225+
if (stand_feedback.status() == ::bosdyn::api::StandCommand::Feedback::STATUS_IS_STANDING) {
226+
return {{BlockingRobotCommandErrorCode::Success}, feedback_res.move()};
227+
}
228+
229+
std::this_thread::sleep_for(poll_period);
230+
}
231+
return {{BlockingRobotCommandErrorCode::CommandTimeoutError,
232+
"The StandCommand failed or timed out."},
233+
feedback_res.move()};
234+
}
183235
} // namespace client
184236

185237
} // namespace bosdyn

cpp/bosdyn/client/robot_command/robot_command_helpers.h

+65-2
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,33 @@ std::error_code make_error_code(BlockingRobotCommandErrorCode);
4545
* move was canceled (the arm failed to reach the goal). See the proto definitions in
4646
* arm_command.proto for more information about why a trajectory would succeed or fail.
4747
*/
48-
RobotCommandFeedbackResultType BlockUntilArmArrives(
48+
[[deprecated]] RobotCommandFeedbackResultType BlockUntilArmArrives(
4949
::bosdyn::client::RobotCommandClient& robot_command_client, int cmd_id, int timeout_sec = 0,
5050
int poll_period_msec = 100);
5151

52+
/**
53+
* Blocks until the arm achieves a finishing state for the specific arm command. This helper will
54+
* block and check the feedback for ArmCartesianCommand, GazeCommand, ArmJointMoveCommand,
55+
* NamedArmPositionsCommand, and ArmImpedanceCommand.
56+
*
57+
* @param robot_command_client (bosdyn.client.RobotCommandClient): The robot command client, used to
58+
* request command feedback.
59+
* @param cmd_id (int): The command ID returned by the robot when the arm movement command was sent.
60+
* @param timeout (Duration): Duration after which we'll return no matter what the
61+
* robot's state is. If unset, 0, or negative, this function will never time out and only return
62+
* when there is finished command feedback.
63+
* @param poll_period (Duration): Duration to wait between requesting feedback updates. Default is
64+
* 100 ms.
65+
*
66+
* @return True if successfully got to the end of the trajectory, False if the arm stalled or the
67+
* move was canceled (the arm failed to reach the goal). See the proto definitions in
68+
* arm_command.proto for more information about why a trajectory would succeed or fail.
69+
*/
70+
RobotCommandFeedbackResultType BlockUntilArmArrives(
71+
::bosdyn::client::RobotCommandClient& robot_command_client, int cmd_id,
72+
::bosdyn::common::Duration timeout = std::chrono::seconds(0),
73+
::bosdyn::common::Duration poll_period = std::chrono::milliseconds(100));
74+
5275
/**
5376
* Blocks until the gripper achieves a finishing state for a ClawGripperCommand.
5477
*
@@ -65,9 +88,49 @@ RobotCommandFeedbackResultType BlockUntilArmArrives(
6588
* @return True if the gripper successfully reached the goal or is applying force on something,
6689
* False if the gripper failed to reach the goal.
6790
*/
68-
RobotCommandFeedbackResultType BlockUntilGripperArrives(
91+
[[deprecated]] RobotCommandFeedbackResultType BlockUntilGripperArrives(
6992
::bosdyn::client::RobotCommandClient& robot_command_client, int cmd_id, int timeout_sec = 0,
7093
int poll_period_msec = 100);
94+
95+
/**
96+
* Blocks until the gripper achieves a finishing state for a ClawGripperCommand.
97+
*
98+
* @param robot_command_client (bosdyn.client.RobotCommandClient): The robot command client, used to
99+
* request command feedback.
100+
* @param cmd_id (int): The command ID returned by the robot when the arm movement command was sent.
101+
* @param timeout (Duration): Duration after which we'll return no matter what the
102+
* robot's state is. If unset, 0, or negative, this function will never time out and only return
103+
* when there is finished command feedback.
104+
* @param poll_period (Duration): Duration to wait between requesting feedback updates. Default is
105+
* 100 ms.
106+
*
107+
* @return True if the gripper successfully reached the goal or is applying force on something,
108+
* False if the gripper failed to reach the goal.
109+
*/
110+
RobotCommandFeedbackResultType BlockUntilGripperArrives(
111+
::bosdyn::client::RobotCommandClient& robot_command_client, int cmd_id,
112+
::bosdyn::common::Duration timeout = std::chrono::seconds(0),
113+
::bosdyn::common::Duration poll_period = std::chrono::milliseconds(100));
114+
115+
/**
116+
* Blocks until the Robot complete StandCommand
117+
*
118+
* @param robot_command_client (bosdyn.client.RobotCommandClient): The robot command client, used to
119+
* request command feedback.
120+
* @param cmd_id (int): The command ID returned by the robot when the arm movement command was sent.
121+
* @param timeout (Duration): Duration after which we'll return no matter what the
122+
* robot's state is. If unset, 0, or negative, this function will never time out and only return
123+
* when there is finished command feedback.
124+
* @param poll_period (Duration): Duration to wait between requesting feedback updates. Default is
125+
* 100 ms.
126+
*
127+
* @return True if the robot successfully completed stand.
128+
* False if the robot failed to reach the stand pose.
129+
*/
130+
RobotCommandFeedbackResultType BlockUntilStandComplete(
131+
::bosdyn::client::RobotCommandClient& robot_command_client, int cmd_id,
132+
::bosdyn::common::Duration timeout = std::chrono::seconds(10),
133+
::bosdyn::common::Duration poll_period = std::chrono::milliseconds(100));
71134
} // namespace client
72135

73136
} // namespace bosdyn
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Copyright (c) 2023 Boston Dynamics, Inc. All rights reserved.
3+
*
4+
* Downloading, reproducing, distributing or otherwise using the SDK Software
5+
* is subject to the terms and conditions of the Boston Dynamics Software
6+
* Development Kit License (20191101-BDSDK-SL).
7+
*/
8+
9+
10+
#include "robot_command_streaming_client.h"
11+
12+
namespace bosdyn {
13+
14+
namespace client {
15+
16+
const char* RobotCommandStreamingClient::s_default_service_name = "robot-command-streaming";
17+
18+
const char* RobotCommandStreamingClient::s_service_type = "bosdyn.api.RobotCommandStreamingService";
19+
20+
JointControlStreamResultType RobotCommandStreamingClient::JointControlStream(
21+
const ::bosdyn::api::JointControlStreamRequest& request) {
22+
if (!m_request_writer) {
23+
m_request_writer = m_stub->JointControlStream(&m_context, &m_response);
24+
if (!m_request_writer) {
25+
return {::bosdyn::common::Status(JointControlStreamErrorCode::RequestWriterFailed),
26+
std::move(m_response)};
27+
}
28+
}
29+
30+
if (!m_request_writer->Write(request)) {
31+
return {::bosdyn::common::Status(JointControlStreamErrorCode::StreamingFailed),
32+
std::move(m_response)};
33+
}
34+
35+
return {::bosdyn::common::Status(JointControlStreamErrorCode::Success)};
36+
}
37+
38+
ServiceClient::QualityOfService RobotCommandStreamingClient::GetQualityOfService() const {
39+
return QualityOfService::NORMAL;
40+
}
41+
42+
void RobotCommandStreamingClient::SetComms(const std::shared_ptr<grpc::ChannelInterface>& channel) {
43+
m_stub.reset(new ::bosdyn::api::RobotCommandStreamingService::Stub(channel));
44+
}
45+
46+
} // namespace client
47+
48+
} // namespace bosdyn

0 commit comments

Comments
 (0)