restore json command interface for aubo io

This commit is contained in:
xtkuang 2026-09-21 13:46:25 +08:00
parent ee08994f6e
commit 910e0c553d
10 changed files with 265 additions and 408 deletions

View File

@ -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};

View File

@ -31,6 +31,7 @@ target_link_libraries(aubo_arm
cmvr_es::proto cmvr_es::proto
PRIVATE PRIVATE
glog glog
jsoncpp
Threads::Threads Threads::Threads
) )

View File

@ -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; }

View File

@ -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) {
return fail(
"io_interface_unavailable",
"[AuboArm] cabinet_io failed: IO interface is null");
}
const bool is_input =
operation == CabinetIoOperation::GetDigitalInput;
const int count = is_input ? io->getStandardDigitalInputNum()
: io->getStandardDigitalOutputNum();
jsonMember(response, "count") = count;
if (count < 0) { if (count < 0) {
return Result::failure( return fail(
ArmErrorCode::CommandFailed, "invalid_io_count",
"[AuboArm] getCabinetDigitalOutput failed: invalid IO count=" + "[AuboArm] cabinet_io failed: invalid IO count=" +
std::to_string(count)); std::to_string(count));
} }
state.count = static_cast<std::uint32_t>(count); if (index >= count) {
if (index >= state.count) { return fail(
return Result::failure( "index_out_of_range",
ArmErrorCode::InvalidArgument, "[AuboArm] cabinet_io index out of range: index=" +
"[AuboArm] getCabinetDigitalOutput index out of range: index=" +
std::to_string(index) + ", count=" + 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);
state.value =
io->getStandardDigitalOutput(static_cast<int>(index));
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(
const std::uint32_t index,
const bool value,
CabinetDigitalOutputState& state)
{
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)); std::to_string(count));
} }
state.count = static_cast<std::uint32_t>(count);
if (index >= state.count) { if (operation == CabinetIoOperation::GetDigitalInput) {
return Result::failure( jsonMember(response, "value") =
ArmErrorCode::InvalidArgument, io->getStandardDigitalInput(index);
"[AuboArm] setCabinetDigitalOutput index out of range: index=" + } else {
std::to_string(index) + ", count=" + const auto runstate =
std::to_string(state.count)); io->getStandardDigitalOutputRunstate(index);
jsonMember(response, "runstate") =
arcs::common_interface::toString(runstate);
jsonMember(response, "runstate_code") =
static_cast<int>(runstate);
if (operation == CabinetIoOperation::GetDigitalOutput) {
jsonMember(response, "value") =
io->getStandardDigitalOutput(index);
} else {
using arcs::common_interface::StandardOutputRunState;
if (runstate != StandardOutputRunState::None) {
return fail(
"output_managed_by_runstate",
"[AuboArm] cabinet_io set_do rejected: output is "
"managed by controller runstate; configure this "
"channel as None before writing");
}
const int ret =
io->setStandardDigitalOutput(index, output_value);
jsonMember(response, "sdk_return_code") = ret;
if (ret != 0) {
return fail(
"sdk_command_failed",
"[AuboArm] cabinet_io set_do failed: sdk ret=" +
std::to_string(ret));
}
jsonMember(response, "requested_value") = output_value;
}
} }
const auto runstate = jsonMember(response, "success") = true;
io->getStandardDigitalOutputRunstate(static_cast<int>(index)); response_json = compactJson(response);
state.runstate = arcs::common_interface::toString(runstate); return true;
state.runstate_code = static_cast<int>(runstate);
using arcs::common_interface::StandardOutputRunState;
if (runstate != StandardOutputRunState::None) {
return Result::failure(
ArmErrorCode::CommandRejected,
"[AuboArm] setCabinetDigitalOutput rejected: output is "
"managed by controller runstate; configure this channel as "
"None before writing");
}
const int ret =
io->setStandardDigitalOutput(static_cast<int>(index), value);
if (ret != 0) {
return Result::failure(
ArmErrorCode::CommandFailed,
"[AuboArm] setCabinetDigitalOutput failed: sdk ret=" +
std::to_string(ret));
}
state.value = value;
return Result::success();
} 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
} }

View File

@ -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;

View File

@ -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_;

View File

@ -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());

View File

@ -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;
}
}

View File

@ -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);
} }

View File

@ -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;
} }
} }