restore json command interface for aubo io
This commit is contained in:
parent
ee08994f6e
commit
910e0c553d
@ -181,18 +181,6 @@ struct PayloadConfig {
|
|||||||
double cog_z{0.0};
|
double cog_z{0.0};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CabinetDigitalInputState {
|
|
||||||
std::uint32_t count{0};
|
|
||||||
bool value{false};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CabinetDigitalOutputState {
|
|
||||||
std::uint32_t count{0};
|
|
||||||
bool value{false};
|
|
||||||
std::string runstate;
|
|
||||||
int runstate_code{0};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MotionOptions {
|
struct MotionOptions {
|
||||||
double velocity{0.0};
|
double velocity{0.0};
|
||||||
double acceleration{0.0};
|
double acceleration{0.0};
|
||||||
|
|||||||
@ -31,6 +31,7 @@ target_link_libraries(aubo_arm
|
|||||||
cmvr_es::proto
|
cmvr_es::proto
|
||||||
PRIVATE
|
PRIVATE
|
||||||
glog
|
glog
|
||||||
|
jsoncpp
|
||||||
Threads::Threads
|
Threads::Threads
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -24,16 +24,8 @@ public:
|
|||||||
std::string typeName() const override { return "AuboARM"; }
|
std::string typeName() const override { return "AuboARM"; }
|
||||||
bool init() override;
|
bool init() override;
|
||||||
bool stop() override;
|
bool stop() override;
|
||||||
Result getCabinetDigitalInput(
|
bool executeJsonCommand(const std::string& request_json,
|
||||||
std::uint32_t index,
|
std::string& response_json) override;
|
||||||
CabinetDigitalInputState& state) const override;
|
|
||||||
Result getCabinetDigitalOutput(
|
|
||||||
std::uint32_t index,
|
|
||||||
CabinetDigitalOutputState& state) const override;
|
|
||||||
Result setCabinetDigitalOutput(
|
|
||||||
std::uint32_t index,
|
|
||||||
bool value,
|
|
||||||
CabinetDigitalOutputState& state) override;
|
|
||||||
|
|
||||||
RobotModel getRobotModel() const override { return model_; }
|
RobotModel getRobotModel() const override { return model_; }
|
||||||
std::size_t getDof() const override { return model_.dof; }
|
std::size_t getDof() const override { return model_.dof; }
|
||||||
|
|||||||
@ -2,7 +2,9 @@
|
|||||||
#include "devices/arm/aubo_arm/include/aubo_motion_result.h"
|
#include "devices/arm/aubo_arm/include/aubo_motion_result.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <cstring>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@ -10,6 +12,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "common/base/logging/logger.h"
|
#include "common/base/logging/logger.h"
|
||||||
|
#include <json/json.h>
|
||||||
|
|
||||||
#if defined(CMVR_HAS_AUBO_SDK)
|
#if defined(CMVR_HAS_AUBO_SDK)
|
||||||
#include "aubo_sdk/rpc.h"
|
#include "aubo_sdk/rpc.h"
|
||||||
@ -62,6 +65,98 @@ std::string vendorBrandName(const config::VendorRobotArmBrand brand)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class CabinetIoOperation {
|
||||||
|
GetDigitalInput,
|
||||||
|
GetDigitalOutput,
|
||||||
|
SetDigitalOutput,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string lowerString(std::string value)
|
||||||
|
{
|
||||||
|
std::transform(
|
||||||
|
value.begin(), value.end(), value.begin(), [](const unsigned char c) {
|
||||||
|
return static_cast<char>(std::tolower(c));
|
||||||
|
});
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseJsonCommand(const std::string& request_json,
|
||||||
|
Json::Value& root,
|
||||||
|
std::string& error)
|
||||||
|
{
|
||||||
|
Json::CharReaderBuilder builder;
|
||||||
|
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
||||||
|
return reader->parse(request_json.data(),
|
||||||
|
request_json.data() + request_json.size(),
|
||||||
|
&root,
|
||||||
|
&error);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string compactJson(const Json::Value& value)
|
||||||
|
{
|
||||||
|
Json::StreamWriterBuilder builder;
|
||||||
|
builder[std::string("indentation")] = "";
|
||||||
|
return Json::writeString(builder, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value& jsonMember(Json::Value& root, const char* name)
|
||||||
|
{
|
||||||
|
return *root.demand(name, name + std::strlen(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
const Json::Value* findJsonMember(const Json::Value& root, const char* name)
|
||||||
|
{
|
||||||
|
return root.find(name, name + std::strlen(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool requiredJsonString(const Json::Value& root,
|
||||||
|
const char* name,
|
||||||
|
std::string& value)
|
||||||
|
{
|
||||||
|
const Json::Value* member = findJsonMember(root, name);
|
||||||
|
if (!member || !member->isString() || member->asString().empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value = member->asString();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool requiredJsonInt(const Json::Value& root, const char* name, int& value)
|
||||||
|
{
|
||||||
|
const Json::Value* member = findJsonMember(root, name);
|
||||||
|
if (!member || !member->isInt()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value = member->asInt();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool requiredJsonBool(const Json::Value& root, const char* name, bool& value)
|
||||||
|
{
|
||||||
|
const Json::Value* member = findJsonMember(root, name);
|
||||||
|
if (!member || !member->isBool()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
value = member->asBool();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseCabinetIoOperation(const std::string& name,
|
||||||
|
CabinetIoOperation& operation)
|
||||||
|
{
|
||||||
|
const std::string normalized = lowerString(name);
|
||||||
|
if (normalized == "get_di") {
|
||||||
|
operation = CabinetIoOperation::GetDigitalInput;
|
||||||
|
} else if (normalized == "get_do") {
|
||||||
|
operation = CabinetIoOperation::GetDigitalOutput;
|
||||||
|
} else if (normalized == "set_do") {
|
||||||
|
operation = CabinetIoOperation::SetDigitalOutput;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CMVR_HAS_AUBO_SDK)
|
#if defined(CMVR_HAS_AUBO_SDK)
|
||||||
constexpr auto kAutoEnablePollInterval = std::chrono::milliseconds(100);
|
constexpr auto kAutoEnablePollInterval = std::chrono::milliseconds(100);
|
||||||
constexpr auto kAutoEnableReconnectInterval = std::chrono::milliseconds(500);
|
constexpr auto kAutoEnableReconnectInterval = std::chrono::milliseconds(500);
|
||||||
@ -356,224 +451,172 @@ bool AuboArm::stop()
|
|||||||
return stopMotion().ok();
|
return stopMotion().ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result AuboArm::getCabinetDigitalInput(
|
bool AuboArm::executeJsonCommand(const std::string& request_json,
|
||||||
const std::uint32_t index,
|
std::string& response_json)
|
||||||
CabinetDigitalInputState& state) const
|
|
||||||
{
|
{
|
||||||
state = {};
|
Json::Value response(Json::objectValue);
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
jsonMember(response, "success") = false;
|
||||||
const auto ready = ensureConnected_("getCabinetDigitalInput");
|
const auto fail = [&](const std::string& error_code,
|
||||||
if (!ready.ok()) {
|
const std::string& error_message) {
|
||||||
return ready;
|
jsonMember(response, "success") = false;
|
||||||
|
jsonMember(response, "error_code") = error_code;
|
||||||
|
jsonMember(response, "error_message") = error_message;
|
||||||
|
response_json = compactJson(response);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Json::Value root;
|
||||||
|
std::string parse_error;
|
||||||
|
if (!parseJsonCommand(request_json, root, parse_error)) {
|
||||||
|
return fail("invalid_json", "invalid json: " + parse_error);
|
||||||
|
}
|
||||||
|
if (!root.isObject()) {
|
||||||
|
return fail("invalid_json", "invalid json: root must be an object");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string command;
|
||||||
|
if (!requiredJsonString(root, "command", command)) {
|
||||||
|
return fail(
|
||||||
|
"invalid_argument",
|
||||||
|
"field 'command' is required and must be a non-empty string");
|
||||||
|
}
|
||||||
|
command = lowerString(command);
|
||||||
|
if (command != "cabinet_io") {
|
||||||
|
return fail("unsupported_command",
|
||||||
|
"unsupported json command: " + command);
|
||||||
|
}
|
||||||
|
jsonMember(response, "command") = command;
|
||||||
|
|
||||||
|
std::string operation_name;
|
||||||
|
if (!requiredJsonString(root, "operation", operation_name)) {
|
||||||
|
return fail(
|
||||||
|
"invalid_argument",
|
||||||
|
"field 'operation' is required and must be a non-empty string");
|
||||||
|
}
|
||||||
|
operation_name = lowerString(operation_name);
|
||||||
|
CabinetIoOperation operation{};
|
||||||
|
if (!parseCabinetIoOperation(operation_name, operation)) {
|
||||||
|
return fail("invalid_operation",
|
||||||
|
"unsupported cabinet_io operation: " + operation_name);
|
||||||
|
}
|
||||||
|
jsonMember(response, "operation") = operation_name;
|
||||||
|
|
||||||
|
int index = -1;
|
||||||
|
if (!requiredJsonInt(root, "index", index) || index < 0) {
|
||||||
|
return fail(
|
||||||
|
"invalid_argument",
|
||||||
|
"field 'index' is required and must be a non-negative JSON integer");
|
||||||
|
}
|
||||||
|
jsonMember(response, "index") = index;
|
||||||
|
|
||||||
|
bool output_value = false;
|
||||||
|
if (operation == CabinetIoOperation::SetDigitalOutput &&
|
||||||
|
!requiredJsonBool(root, "value", output_value)) {
|
||||||
|
return fail(
|
||||||
|
"invalid_argument",
|
||||||
|
"field 'value' is required for set_do and must be a JSON boolean");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CMVR_HAS_AUBO_SDK)
|
#if defined(CMVR_HAS_AUBO_SDK)
|
||||||
try {
|
|
||||||
const auto robot_names = sdk_->rpc_client->getRobotNames();
|
|
||||||
if (robot_names.empty()) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::RobotNotReady,
|
|
||||||
"[AuboArm] getCabinetDigitalInput failed: robot name list is empty");
|
|
||||||
}
|
|
||||||
auto robot_interface =
|
|
||||||
sdk_->rpc_client->getRobotInterface(robot_names.front());
|
|
||||||
if (!robot_interface || !robot_interface->getIoControl()) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::RobotNotReady,
|
|
||||||
"[AuboArm] getCabinetDigitalInput failed: IO interface is unavailable");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto io = robot_interface->getIoControl();
|
|
||||||
const int count = io->getStandardDigitalInputNum();
|
|
||||||
if (count < 0) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::CommandFailed,
|
|
||||||
"[AuboArm] getCabinetDigitalInput failed: invalid IO count=" +
|
|
||||||
std::to_string(count));
|
|
||||||
}
|
|
||||||
state.count = static_cast<std::uint32_t>(count);
|
|
||||||
if (index >= state.count) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::InvalidArgument,
|
|
||||||
"[AuboArm] getCabinetDigitalInput index out of range: index=" +
|
|
||||||
std::to_string(index) + ", count=" +
|
|
||||||
std::to_string(state.count));
|
|
||||||
}
|
|
||||||
state.value = io->getStandardDigitalInput(static_cast<int>(index));
|
|
||||||
return Result::success();
|
|
||||||
} catch (const arcs::common_interface::AuboException& e) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::CommandFailed,
|
|
||||||
"[AuboArm] getCabinetDigitalInput failed: " +
|
|
||||||
std::string(e.what()) + ", sdk ret=" +
|
|
||||||
std::to_string(e.code()));
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::CommandFailed,
|
|
||||||
"[AuboArm] getCabinetDigitalInput failed: " +
|
|
||||||
std::string(e.what()));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::UnsupportedCommand,
|
|
||||||
"[AuboArm] getCabinetDigitalInput failed: Aubo SDK is unavailable");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
Result AuboArm::getCabinetDigitalOutput(
|
|
||||||
const std::uint32_t index,
|
|
||||||
CabinetDigitalOutputState& state) const
|
|
||||||
{
|
|
||||||
state = {};
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
const auto ready = ensureConnected_("getCabinetDigitalOutput");
|
const auto ready = ensureConnected_("cabinet_io");
|
||||||
if (!ready.ok()) {
|
if (!ready.ok()) {
|
||||||
return ready;
|
return fail("not_connected", ready.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CMVR_HAS_AUBO_SDK)
|
|
||||||
try {
|
try {
|
||||||
const auto robot_names = sdk_->rpc_client->getRobotNames();
|
const auto robot_names = sdk_->rpc_client->getRobotNames();
|
||||||
if (robot_names.empty()) {
|
if (robot_names.empty()) {
|
||||||
return Result::failure(
|
return fail(
|
||||||
ArmErrorCode::RobotNotReady,
|
"robot_interface_unavailable",
|
||||||
"[AuboArm] getCabinetDigitalOutput failed: robot name list is empty");
|
"[AuboArm] cabinet_io failed: robot name list is empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto robot_interface =
|
auto robot_interface =
|
||||||
sdk_->rpc_client->getRobotInterface(robot_names.front());
|
sdk_->rpc_client->getRobotInterface(robot_names.front());
|
||||||
if (!robot_interface || !robot_interface->getIoControl()) {
|
if (!robot_interface) {
|
||||||
return Result::failure(
|
return fail(
|
||||||
ArmErrorCode::RobotNotReady,
|
"robot_interface_unavailable",
|
||||||
"[AuboArm] getCabinetDigitalOutput failed: IO interface is unavailable");
|
"[AuboArm] cabinet_io failed: robot interface is null");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto io = robot_interface->getIoControl();
|
auto io = robot_interface->getIoControl();
|
||||||
const int count = io->getStandardDigitalOutputNum();
|
if (!io) {
|
||||||
if (count < 0) {
|
return fail(
|
||||||
return Result::failure(
|
"io_interface_unavailable",
|
||||||
ArmErrorCode::CommandFailed,
|
"[AuboArm] cabinet_io failed: IO interface is null");
|
||||||
"[AuboArm] getCabinetDigitalOutput failed: invalid IO count=" +
|
|
||||||
std::to_string(count));
|
|
||||||
}
|
|
||||||
state.count = static_cast<std::uint32_t>(count);
|
|
||||||
if (index >= state.count) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::InvalidArgument,
|
|
||||||
"[AuboArm] getCabinetDigitalOutput index out of range: index=" +
|
|
||||||
std::to_string(index) + ", count=" +
|
|
||||||
std::to_string(state.count));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool is_input =
|
||||||
|
operation == CabinetIoOperation::GetDigitalInput;
|
||||||
|
const int count = is_input ? io->getStandardDigitalInputNum()
|
||||||
|
: io->getStandardDigitalOutputNum();
|
||||||
|
jsonMember(response, "count") = count;
|
||||||
|
if (count < 0) {
|
||||||
|
return fail(
|
||||||
|
"invalid_io_count",
|
||||||
|
"[AuboArm] cabinet_io failed: invalid IO count=" +
|
||||||
|
std::to_string(count));
|
||||||
|
}
|
||||||
|
if (index >= count) {
|
||||||
|
return fail(
|
||||||
|
"index_out_of_range",
|
||||||
|
"[AuboArm] cabinet_io index out of range: index=" +
|
||||||
|
std::to_string(index) + ", count=" +
|
||||||
|
std::to_string(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation == CabinetIoOperation::GetDigitalInput) {
|
||||||
|
jsonMember(response, "value") =
|
||||||
|
io->getStandardDigitalInput(index);
|
||||||
|
} else {
|
||||||
const auto runstate =
|
const auto runstate =
|
||||||
io->getStandardDigitalOutputRunstate(static_cast<int>(index));
|
io->getStandardDigitalOutputRunstate(index);
|
||||||
state.runstate = arcs::common_interface::toString(runstate);
|
jsonMember(response, "runstate") =
|
||||||
state.runstate_code = static_cast<int>(runstate);
|
arcs::common_interface::toString(runstate);
|
||||||
state.value =
|
jsonMember(response, "runstate_code") =
|
||||||
io->getStandardDigitalOutput(static_cast<int>(index));
|
static_cast<int>(runstate);
|
||||||
return Result::success();
|
|
||||||
} catch (const arcs::common_interface::AuboException& e) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::CommandFailed,
|
|
||||||
"[AuboArm] getCabinetDigitalOutput failed: " +
|
|
||||||
std::string(e.what()) + ", sdk ret=" +
|
|
||||||
std::to_string(e.code()));
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::CommandFailed,
|
|
||||||
"[AuboArm] getCabinetDigitalOutput failed: " +
|
|
||||||
std::string(e.what()));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::UnsupportedCommand,
|
|
||||||
"[AuboArm] getCabinetDigitalOutput failed: Aubo SDK is unavailable");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
Result AuboArm::setCabinetDigitalOutput(
|
if (operation == CabinetIoOperation::GetDigitalOutput) {
|
||||||
const std::uint32_t index,
|
jsonMember(response, "value") =
|
||||||
const bool value,
|
io->getStandardDigitalOutput(index);
|
||||||
CabinetDigitalOutputState& state)
|
} else {
|
||||||
{
|
|
||||||
state = {};
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
const auto ready = ensureConnected_("setCabinetDigitalOutput");
|
|
||||||
if (!ready.ok()) {
|
|
||||||
return ready;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CMVR_HAS_AUBO_SDK)
|
|
||||||
try {
|
|
||||||
const auto robot_names = sdk_->rpc_client->getRobotNames();
|
|
||||||
if (robot_names.empty()) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::RobotNotReady,
|
|
||||||
"[AuboArm] setCabinetDigitalOutput failed: robot name list is empty");
|
|
||||||
}
|
|
||||||
auto robot_interface =
|
|
||||||
sdk_->rpc_client->getRobotInterface(robot_names.front());
|
|
||||||
if (!robot_interface || !robot_interface->getIoControl()) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::RobotNotReady,
|
|
||||||
"[AuboArm] setCabinetDigitalOutput failed: IO interface is unavailable");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto io = robot_interface->getIoControl();
|
|
||||||
const int count = io->getStandardDigitalOutputNum();
|
|
||||||
if (count < 0) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::CommandFailed,
|
|
||||||
"[AuboArm] setCabinetDigitalOutput failed: invalid IO count=" +
|
|
||||||
std::to_string(count));
|
|
||||||
}
|
|
||||||
state.count = static_cast<std::uint32_t>(count);
|
|
||||||
if (index >= state.count) {
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::InvalidArgument,
|
|
||||||
"[AuboArm] setCabinetDigitalOutput index out of range: index=" +
|
|
||||||
std::to_string(index) + ", count=" +
|
|
||||||
std::to_string(state.count));
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto runstate =
|
|
||||||
io->getStandardDigitalOutputRunstate(static_cast<int>(index));
|
|
||||||
state.runstate = arcs::common_interface::toString(runstate);
|
|
||||||
state.runstate_code = static_cast<int>(runstate);
|
|
||||||
using arcs::common_interface::StandardOutputRunState;
|
using arcs::common_interface::StandardOutputRunState;
|
||||||
if (runstate != StandardOutputRunState::None) {
|
if (runstate != StandardOutputRunState::None) {
|
||||||
return Result::failure(
|
return fail(
|
||||||
ArmErrorCode::CommandRejected,
|
"output_managed_by_runstate",
|
||||||
"[AuboArm] setCabinetDigitalOutput rejected: output is "
|
"[AuboArm] cabinet_io set_do rejected: output is "
|
||||||
"managed by controller runstate; configure this channel as "
|
"managed by controller runstate; configure this "
|
||||||
"None before writing");
|
"channel as None before writing");
|
||||||
}
|
}
|
||||||
|
|
||||||
const int ret =
|
const int ret =
|
||||||
io->setStandardDigitalOutput(static_cast<int>(index), value);
|
io->setStandardDigitalOutput(index, output_value);
|
||||||
|
jsonMember(response, "sdk_return_code") = ret;
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
return Result::failure(
|
return fail(
|
||||||
ArmErrorCode::CommandFailed,
|
"sdk_command_failed",
|
||||||
"[AuboArm] setCabinetDigitalOutput failed: sdk ret=" +
|
"[AuboArm] cabinet_io set_do failed: sdk ret=" +
|
||||||
std::to_string(ret));
|
std::to_string(ret));
|
||||||
}
|
}
|
||||||
state.value = value;
|
jsonMember(response, "requested_value") = output_value;
|
||||||
return Result::success();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonMember(response, "success") = true;
|
||||||
|
response_json = compactJson(response);
|
||||||
|
return true;
|
||||||
} catch (const arcs::common_interface::AuboException& e) {
|
} catch (const arcs::common_interface::AuboException& e) {
|
||||||
return Result::failure(
|
jsonMember(response, "sdk_return_code") = e.code();
|
||||||
ArmErrorCode::CommandFailed,
|
return fail("sdk_exception",
|
||||||
"[AuboArm] setCabinetDigitalOutput failed: " +
|
std::string("[AuboArm] cabinet_io failed: ") + e.what());
|
||||||
std::string(e.what()) + ", sdk ret=" +
|
|
||||||
std::to_string(e.code()));
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
return Result::failure(
|
return fail("sdk_exception",
|
||||||
ArmErrorCode::CommandFailed,
|
std::string("[AuboArm] cabinet_io failed: ") + e.what());
|
||||||
"[AuboArm] setCabinetDigitalOutput failed: " +
|
|
||||||
std::string(e.what()));
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return Result::failure(
|
return fail("sdk_unavailable",
|
||||||
ArmErrorCode::UnsupportedCommand,
|
"[AuboArm] cabinet_io failed: Aubo SDK is unavailable");
|
||||||
"[AuboArm] setCabinetDigitalOutput failed: Aubo SDK is unavailable");
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -44,33 +44,12 @@ public:
|
|||||||
ArmErrorCode::UnsupportedCommand,
|
ArmErrorCode::UnsupportedCommand,
|
||||||
"ListTCPFrame is not supported by this robot arm");
|
"ListTCPFrame is not supported by this robot arm");
|
||||||
}
|
}
|
||||||
virtual Result getCabinetDigitalInput(
|
virtual bool executeJsonCommand(const std::string&,
|
||||||
std::uint32_t,
|
std::string& response_json)
|
||||||
CabinetDigitalInputState& state) const
|
|
||||||
{
|
{
|
||||||
state = {};
|
response_json =
|
||||||
return Result::failure(
|
R"({"success":false,"error_code":"unsupported_command","error_message":"JSON command unsupported"})";
|
||||||
ArmErrorCode::UnsupportedCommand,
|
return false;
|
||||||
"cabinet digital input is not supported by this robot arm");
|
|
||||||
}
|
|
||||||
virtual Result getCabinetDigitalOutput(
|
|
||||||
std::uint32_t,
|
|
||||||
CabinetDigitalOutputState& state) const
|
|
||||||
{
|
|
||||||
state = {};
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::UnsupportedCommand,
|
|
||||||
"cabinet digital output is not supported by this robot arm");
|
|
||||||
}
|
|
||||||
virtual Result setCabinetDigitalOutput(
|
|
||||||
std::uint32_t,
|
|
||||||
bool,
|
|
||||||
CabinetDigitalOutputState& state)
|
|
||||||
{
|
|
||||||
state = {};
|
|
||||||
return Result::failure(
|
|
||||||
ArmErrorCode::UnsupportedCommand,
|
|
||||||
"cabinet digital output is not supported by this robot arm");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Result torqueOn() = 0;
|
virtual Result torqueOn() = 0;
|
||||||
|
|||||||
@ -59,18 +59,10 @@ public:
|
|||||||
grpc::Status computeForwardKinematics(grpc::ServerContext* context,
|
grpc::Status computeForwardKinematics(grpc::ServerContext* context,
|
||||||
const api::ComputeForwardKinematics_Request* request,
|
const api::ComputeForwardKinematics_Request* request,
|
||||||
api::ComputeForwardKinematics_Response* response) override;
|
api::ComputeForwardKinematics_Response* response) override;
|
||||||
grpc::Status getCabinetDigitalInput(
|
grpc::Status ExecuteJsonCommand(
|
||||||
grpc::ServerContext* context,
|
grpc::ServerContext* context,
|
||||||
const api::CabinetDigitalInput_Request* request,
|
const api::JsonDeviceCommand_Request* request,
|
||||||
api::CabinetDigitalInput_Response* response) override;
|
api::JsonDeviceCommand_Feedback* response) override;
|
||||||
grpc::Status getCabinetDigitalOutput(
|
|
||||||
grpc::ServerContext* context,
|
|
||||||
const api::CabinetDigitalOutput_Request* request,
|
|
||||||
api::CabinetDigitalOutput_Response* response) override;
|
|
||||||
grpc::Status setCabinetDigitalOutput(
|
|
||||||
grpc::ServerContext* context,
|
|
||||||
const api::SetCabinetDigitalOutput_Request* request,
|
|
||||||
api::SetCabinetDigitalOutput_Response* response) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
device::DeviceManager& dmgr_;
|
device::DeviceManager& dmgr_;
|
||||||
|
|||||||
@ -588,10 +588,10 @@ grpc::Status gRPCArmServiceImpl::computeForwardKinematics(grpc::ServerContext*,
|
|||||||
return grpc::Status(grpc::StatusCode::UNIMPLEMENTED, "computeForwardKinematics is not implemented");
|
return grpc::Status(grpc::StatusCode::UNIMPLEMENTED, "computeForwardKinematics is not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
grpc::Status gRPCArmServiceImpl::getCabinetDigitalInput(
|
grpc::Status gRPCArmServiceImpl::ExecuteJsonCommand(
|
||||||
grpc::ServerContext*,
|
grpc::ServerContext*,
|
||||||
const api::CabinetDigitalInput_Request* request,
|
const api::JsonDeviceCommand_Request* request,
|
||||||
api::CabinetDigitalInput_Response* response)
|
api::JsonDeviceCommand_Feedback* response)
|
||||||
{
|
{
|
||||||
auto control_lease =
|
auto control_lease =
|
||||||
ControlCommandArbiter::instance().tryAcquireControl();
|
ControlCommandArbiter::instance().tryAcquireControl();
|
||||||
@ -606,85 +606,17 @@ grpc::Status gRPCArmServiceImpl::getCabinetDigitalInput(
|
|||||||
return setDeviceNotFound(response, device_id);
|
return setDeviceNotFound(response, device_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
device::CabinetDigitalInputState state;
|
std::string response_json;
|
||||||
const auto result =
|
const bool success = arm->executeJsonCommand(
|
||||||
arm->getCabinetDigitalInput(request->index(), state);
|
request->request_json(), response_json);
|
||||||
response->set_count(state.count);
|
fillFeedback(response->mutable_header(),
|
||||||
response->set_value(state.value);
|
success,
|
||||||
if (result.ok()) {
|
success ? "" : response_json);
|
||||||
logRpcSuccess("getCabinetDigitalInput", device_id);
|
response->set_response_json(response_json);
|
||||||
|
if (success) {
|
||||||
|
logRpcSuccess("ExecuteJsonCommand", device_id);
|
||||||
}
|
}
|
||||||
return setResponseResult(response, result);
|
return grpc::Status::OK;
|
||||||
} catch (const std::exception& e) {
|
|
||||||
fillFeedback(response->mutable_header(), false, e.what());
|
|
||||||
return grpc::Status(grpc::StatusCode::INTERNAL, e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
grpc::Status gRPCArmServiceImpl::getCabinetDigitalOutput(
|
|
||||||
grpc::ServerContext*,
|
|
||||||
const api::CabinetDigitalOutput_Request* request,
|
|
||||||
api::CabinetDigitalOutput_Response* response)
|
|
||||||
{
|
|
||||||
auto control_lease =
|
|
||||||
ControlCommandArbiter::instance().tryAcquireControl();
|
|
||||||
if (!control_lease) {
|
|
||||||
return setControlBusy(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const std::string device_id = request->header().device_id();
|
|
||||||
auto arm = dmgr_.getDevice<device::RobotArm>(device_id);
|
|
||||||
if (!arm) {
|
|
||||||
return setDeviceNotFound(response, device_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
device::CabinetDigitalOutputState state;
|
|
||||||
const auto result =
|
|
||||||
arm->getCabinetDigitalOutput(request->index(), state);
|
|
||||||
response->set_count(state.count);
|
|
||||||
response->set_value(state.value);
|
|
||||||
response->set_runstate(state.runstate);
|
|
||||||
response->set_runstate_code(state.runstate_code);
|
|
||||||
if (result.ok()) {
|
|
||||||
logRpcSuccess("getCabinetDigitalOutput", device_id);
|
|
||||||
}
|
|
||||||
return setResponseResult(response, result);
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
fillFeedback(response->mutable_header(), false, e.what());
|
|
||||||
return grpc::Status(grpc::StatusCode::INTERNAL, e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
grpc::Status gRPCArmServiceImpl::setCabinetDigitalOutput(
|
|
||||||
grpc::ServerContext*,
|
|
||||||
const api::SetCabinetDigitalOutput_Request* request,
|
|
||||||
api::SetCabinetDigitalOutput_Response* response)
|
|
||||||
{
|
|
||||||
auto control_lease =
|
|
||||||
ControlCommandArbiter::instance().tryAcquireControl();
|
|
||||||
if (!control_lease) {
|
|
||||||
return setControlBusy(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const std::string device_id = request->header().device_id();
|
|
||||||
auto arm = dmgr_.getDevice<device::RobotArm>(device_id);
|
|
||||||
if (!arm) {
|
|
||||||
return setDeviceNotFound(response, device_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
device::CabinetDigitalOutputState state;
|
|
||||||
const auto result = arm->setCabinetDigitalOutput(
|
|
||||||
request->index(), request->value(), state);
|
|
||||||
response->set_count(state.count);
|
|
||||||
response->set_requested_value(request->value());
|
|
||||||
response->set_runstate(state.runstate);
|
|
||||||
response->set_runstate_code(state.runstate_code);
|
|
||||||
if (result.ok()) {
|
|
||||||
logRpcSuccess("setCabinetDigitalOutput", device_id);
|
|
||||||
}
|
|
||||||
return setResponseResult(response, result);
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
fillFeedback(response->mutable_header(), false, e.what());
|
fillFeedback(response->mutable_header(), false, e.what());
|
||||||
return grpc::Status(grpc::StatusCode::INTERNAL, e.what());
|
return grpc::Status(grpc::StatusCode::INTERNAL, e.what());
|
||||||
|
|||||||
@ -319,76 +319,3 @@ message ComputeForwardKinematics {
|
|||||||
TransformMatrix4x4 matrix = 2;
|
TransformMatrix4x4 matrix = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 读取机械臂控制柜 Standard 数字输入(DI)。
|
|
||||||
message CabinetDigitalInput {
|
|
||||||
// 数字输入读取请求。
|
|
||||||
message Request {
|
|
||||||
// 通用请求头,包含目标设备 ID 和请求时间戳。
|
|
||||||
CommandHeader.Request header = 1;
|
|
||||||
// DI 通道索引,从 0 开始,无单位。
|
|
||||||
uint32 index = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数字输入读取结果。
|
|
||||||
message Response {
|
|
||||||
// 通用响应头,包含成功标志、错误信息和响应时间戳。
|
|
||||||
CommandHeader.Feedback header = 1;
|
|
||||||
// 控制柜可用 Standard DI 通道总数,无单位。
|
|
||||||
uint32 count = 2;
|
|
||||||
// 输入电平;true 为高电平,false 为低电平,无单位。
|
|
||||||
bool value = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取机械臂控制柜 Standard 数字输出(DO)。
|
|
||||||
message CabinetDigitalOutput {
|
|
||||||
// 数字输出读取请求。
|
|
||||||
message Request {
|
|
||||||
// 通用请求头,包含目标设备 ID 和请求时间戳。
|
|
||||||
CommandHeader.Request header = 1;
|
|
||||||
// DO 通道索引,从 0 开始,无单位。
|
|
||||||
uint32 index = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数字输出读取结果。
|
|
||||||
message Response {
|
|
||||||
// 通用响应头,包含成功标志、错误信息和响应时间戳。
|
|
||||||
CommandHeader.Feedback header = 1;
|
|
||||||
// 控制柜可用 Standard DO 通道总数,无单位。
|
|
||||||
uint32 count = 2;
|
|
||||||
// 当前输出电平;true 为高电平,false 为低电平,无单位。
|
|
||||||
bool value = 3;
|
|
||||||
// 控制器对该输出通道配置的运行状态名称,无单位。
|
|
||||||
string runstate = 4;
|
|
||||||
// 控制器输出运行状态枚举值,无单位。
|
|
||||||
int32 runstate_code = 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置机械臂控制柜 Standard 数字输出(DO)。
|
|
||||||
message SetCabinetDigitalOutput {
|
|
||||||
// 数字输出设置请求。
|
|
||||||
message Request {
|
|
||||||
// 通用请求头,包含目标设备 ID 和请求时间戳。
|
|
||||||
CommandHeader.Request header = 1;
|
|
||||||
// DO 通道索引,从 0 开始,无单位。
|
|
||||||
uint32 index = 2;
|
|
||||||
// 目标输出电平;true 为高电平,false 为低电平,无单位。
|
|
||||||
bool value = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 数字输出设置结果。
|
|
||||||
message Response {
|
|
||||||
// 通用响应头,包含成功标志、错误信息和响应时间戳。
|
|
||||||
CommandHeader.Feedback header = 1;
|
|
||||||
// 控制柜可用 Standard DO 通道总数,无单位。
|
|
||||||
uint32 count = 2;
|
|
||||||
// SDK 已接受的目标输出电平,不代表已经回读确认,无单位。
|
|
||||||
bool requested_value = 3;
|
|
||||||
// 写入前该输出通道的控制器运行状态名称,无单位。
|
|
||||||
string runstate = 4;
|
|
||||||
// 写入前该输出通道的控制器运行状态枚举值,无单位。
|
|
||||||
int32 runstate_code = 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -39,10 +39,6 @@ service ArmService {
|
|||||||
rpc getPoseMatrix(GetPoseMatrix.Request) returns (GetPoseMatrix.Response);
|
rpc getPoseMatrix(GetPoseMatrix.Request) returns (GetPoseMatrix.Response);
|
||||||
// 根据关节角计算正运动学矩阵;输入角度 rad,输出平移元素 m。
|
// 根据关节角计算正运动学矩阵;输入角度 rad,输出平移元素 m。
|
||||||
rpc computeForwardKinematics(ComputeForwardKinematics.Request) returns (ComputeForwardKinematics.Response);
|
rpc computeForwardKinematics(ComputeForwardKinematics.Request) returns (ComputeForwardKinematics.Response);
|
||||||
// 读取控制柜 Standard DI;通道索引从 0 开始,电平为布尔值。
|
// 执行机械臂厂商扩展 JSON 命令;当前用于 AUBO 控制柜 Standard DI/DO。
|
||||||
rpc getCabinetDigitalInput(CabinetDigitalInput.Request) returns (CabinetDigitalInput.Response);
|
rpc ExecuteJsonCommand(JsonDeviceCommand.Request) returns (JsonDeviceCommand.Feedback);
|
||||||
// 读取控制柜 Standard DO 及其控制器运行状态;通道索引从 0 开始。
|
|
||||||
rpc getCabinetDigitalOutput(CabinetDigitalOutput.Request) returns (CabinetDigitalOutput.Response);
|
|
||||||
// 设置控制柜 Standard DO;仅允许写入未被控制器运行状态管理的通道。
|
|
||||||
rpc setCabinetDigitalOutput(SetCabinetDigitalOutput.Request) returns (SetCabinetDigitalOutput.Response);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,14 +59,21 @@ message ConfigParam {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设备厂商扩展 JSON 命令;JSON 内容及字段单位由具体设备命令定义。
|
||||||
message JsonDeviceCommand {
|
message JsonDeviceCommand {
|
||||||
|
// JSON 命令请求。
|
||||||
message Request {
|
message Request {
|
||||||
|
// 通用请求头,包含目标设备 ID 和请求时间戳。
|
||||||
CommandHeader.Request header = 1;
|
CommandHeader.Request header = 1;
|
||||||
|
// JSON 格式的设备命令字符串,无单位。
|
||||||
string request_json = 2;
|
string request_json = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JSON 命令响应。
|
||||||
message Feedback {
|
message Feedback {
|
||||||
|
// 通用响应头,包含成功标志、错误信息和响应时间戳。
|
||||||
CommandHeader.Feedback header = 1;
|
CommandHeader.Feedback header = 1;
|
||||||
|
// JSON 格式的设备响应字符串,无单位。
|
||||||
string response_json = 2;
|
string response_json = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user