skip duplicate torqueOn when already enabled

This commit is contained in:
xtkuang 2026-08-18 10:46:19 +08:00
parent d6997b03b1
commit e28a0a4381
3 changed files with 66 additions and 6 deletions

View File

@ -360,6 +360,20 @@ grpc::Status setControlDispatchFailure(
" dispatch"); " dispatch");
} }
grpc::Status setAlreadyEnabled(
api::CommandHeader_Feedback* response,
const std::string& device_id,
const char* rpc_name)
{
constexpr const char* kAlreadyEnabledMessage =
"RobotArm is already enabled";
CMVR_LOG(WARNING) << "[gRPCArmServiceImpl] (" << rpc_name
<< "): ignored because the device is already enabled, id="
<< device_id;
fillFeedback(response, true, kAlreadyEnabledMessage);
return grpc::Status::OK;
}
} // namespace } // namespace
gRPCArmServiceImpl::gRPCArmServiceImpl() gRPCArmServiceImpl::gRPCArmServiceImpl()
@ -423,6 +437,10 @@ grpc::Status gRPCArmServiceImpl::torqueOn(grpc::ServerContext* context,
if (!arm) { if (!arm) {
return setDeviceNotFound(response, device_id); return setDeviceNotFound(response, device_id);
} }
const auto state = arm->getRobotState();
if (state.powered_on) {
return setAlreadyEnabled(response, device_id, "torqueOn");
}
ScopedUnaryControlLease control_lease( ScopedUnaryControlLease control_lease(
device_id, "torqueOn"); device_id, "torqueOn");
if (!control_lease.acquired()) { if (!control_lease.acquired()) {

View File

@ -961,7 +961,9 @@ grpc::Status GrpcCommandTransaction::finish(
: dispatch_started_ ? safety::CommandLifecycle::Failed : dispatch_started_ ? safety::CommandLifecycle::Failed
: safety::CommandLifecycle::RejectedBeforeDispatch); : safety::CommandLifecycle::RejectedBeforeDispatch);
const std::string detail = success const std::string detail = success
? std::string{} ? feedback && !feedback->error_message().empty()
? feedback->error_message()
: std::string{}
: feedback && !feedback->error_message().empty() : feedback && !feedback->error_message().empty()
? feedback->error_message() ? feedback->error_message()
: operation_status.error_message(); : operation_status.error_message();
@ -1134,7 +1136,7 @@ void GrpcCommandTransaction::populateFeedback_(
feedback->set_error_message( feedback->set_error_message(
detail.empty() ? safety::toString(reason) : detail); detail.empty() ? safety::toString(reason) : detail);
} }
if (success) { if (success && feedback->error_message().empty()) {
feedback->clear_error_message(); feedback->clear_error_message();
} }
if (!feedback->has_timestamp()) { if (!feedback->has_timestamp()) {

View File

@ -1,5 +1,6 @@
#include "service/grpc/server/include/grpc_arm_service.h" #include "service/grpc/server/include/grpc_arm_service.h"
#include <atomic>
#include <chrono> #include <chrono>
#include <cstdio> #include <cstdio>
#include <condition_variable> #include <condition_variable>
@ -48,7 +49,16 @@ public:
device::RobotModel getRobotModel() const override { return {}; } device::RobotModel getRobotModel() const override { return {}; }
std::size_t getDof() const override { return 0U; } std::size_t getDof() const override { return 0U; }
device::ArmState getRobotState() const override { return {}; } device::ArmState getRobotState() const override
{
device::ArmState state;
state.connected = true;
state.powered_on = powered_on_.load();
state.robot_mode = state.powered_on
? device::RobotMode::Running
: device::RobotMode::PowerOff;
return state;
}
device::JointGroupState getJointState() const override { return {}; } device::JointGroupState getJointState() const override { return {}; }
device::CartesianPose getTcpPose( device::CartesianPose getTcpPose(
device::FrameType = device::FrameType::Base) const override device::FrameType = device::FrameType::Base) const override
@ -325,6 +335,11 @@ public:
return torque_on_calls_; return torque_on_calls_;
} }
void setPoweredOn(const bool powered_on)
{
powered_on_.store(powered_on);
}
bool lastTorqueOnHadCancellation() const bool lastTorqueOnHadCancellation() const
{ {
std::lock_guard lock(motion_mutex_); std::lock_guard lock(motion_mutex_);
@ -505,6 +520,7 @@ private:
bool last_torque_on_cancellation_requested_{false}; bool last_torque_on_cancellation_requested_{false};
bool last_motion_had_cancellation_{false}; bool last_motion_had_cancellation_{false};
bool last_motion_cancellation_requested_{false}; bool last_motion_cancellation_requested_{false};
std::atomic<bool> powered_on_{false};
}; };
class JsonCommandNonArmDevice final : public device::AbstractDevice { class JsonCommandNonArmDevice final : public device::AbstractDevice {
@ -641,13 +657,20 @@ protected:
return service_->torqueOff(&context, &request, &response); return service_->torqueOff(&context, &request, &response);
} }
MoveOutcome torqueOn(const std::string& device_id) grpc::Status torqueOn(
const std::string& device_id,
api::CommandHeader_Feedback& response)
{ {
api::CommandHeader_Request request; api::CommandHeader_Request request;
request.set_device_id(device_id); request.set_device_id(device_id);
api::CommandHeader_Feedback response;
grpc::ServerContext context; grpc::ServerContext context;
auto status = service_->torqueOn(&context, &request, &response); return service_->torqueOn(&context, &request, &response);
}
MoveOutcome torqueOn(const std::string& device_id)
{
api::CommandHeader_Feedback response;
auto status = torqueOn(device_id, response);
return { return {
std::move(status), std::move(status),
response.success(), response.success(),
@ -752,6 +775,23 @@ TEST_F(GrpcArmServiceTest,
EXPECT_EQ(left_arm_->execute_calls, 0); EXPECT_EQ(left_arm_->execute_calls, 0);
} }
TEST_F(GrpcArmServiceTest,
TorqueOnAlreadyEnabledArmReturnsOkWithoutDispatchingBackend)
{
aubo_arm_->setPoweredOn(true);
api::CommandHeader_Feedback response;
const auto status = torqueOn("aubo_arm", response);
ASSERT_TRUE(status.ok()) << status.error_message();
EXPECT_TRUE(response.success());
EXPECT_EQ(response.error_message(), "RobotArm is already enabled");
EXPECT_EQ(
response.reason_code(),
api::COMMAND_REASON_CODE_NONE);
EXPECT_EQ(aubo_arm_->torqueOnCalls(), 0);
}
TEST_F(GrpcArmServiceTest, TEST_F(GrpcArmServiceTest,
StopMotionRevokesBlockedMoveJLeaseBeforeMoveLReturns) StopMotionRevokesBlockedMoveJLeaseBeforeMoveLReturns)
{ {