fix aubo system emergency stop recovery
This commit is contained in:
parent
aac719a932
commit
9c9b412d91
@ -106,9 +106,11 @@ cmake --install build
|
|||||||
`RobotModeType` 和硬件急停来源;首次有效样本前、监控断线或样本过期时,
|
`RobotModeType` 和硬件急停来源;首次有效样本前、监控断线或样本过期时,
|
||||||
所有 Move、Speed、Servo 和程序启动请求均按不安全状态拒绝;
|
所有 Move、Speed、Servo 和程序启动请求均按不安全状态拒绝;
|
||||||
- 硬件急停会立即使当前运动 generation 失效,并在急停输入有效期间保持锁存。
|
- 硬件急停会立即使当前运动 generation 失效,并在急停输入有效期间保持锁存。
|
||||||
检测到硬件急停输入消失且控制器重新报告 `Normal`/`ReducedMode` 后,后端应
|
AUBO SDK 将示教器/控制柜急停报告为 `RobotEmergencyStop`,将控制器系统急停
|
||||||
自动执行 `poweron()` 和 `startup()`,恢复到 `Running` 后再完成安全确认并开放新的
|
(外部系统急停输入)报告为 `SystemEmergencyStop`;两者在本后端都属于硬件急停。
|
||||||
gRPC 控制指令;防护停机和 Safety Fault/Violation 仍保持显式恢复语义;
|
检测到任一硬件急停输入消失且控制器重新报告 `Normal`/`ReducedMode` 后,后端自动
|
||||||
|
执行 `poweron()` 和 `startup()`,恢复到 `Running` 后再完成安全确认并开放新的 gRPC
|
||||||
|
控制指令;防护停机和 Safety Fault/Violation 仍保持显式恢复语义;
|
||||||
- `emergencyStop()` 使用独立的 `SoftwareEmergencyStop` 锁存。即使软件急停在真实
|
- `emergencyStop()` 使用独立的 `SoftwareEmergencyStop` 锁存。即使软件急停在真实
|
||||||
硬件急停有效期间触发,后续硬件采样也不能覆盖该锁存,释放硬件急停开关不会
|
硬件急停有效期间触发,后续硬件采样也不能覆盖该锁存,释放硬件急停开关不会
|
||||||
自动清除软件急停;它只能通过显式安全恢复流程解除;
|
自动清除软件急停;它只能通过显式安全恢复流程解除;
|
||||||
|
|||||||
@ -470,7 +470,7 @@ void publishSafetySample(
|
|||||||
monitor->servo_mode_select.store(servo_mode_select);
|
monitor->servo_mode_select.store(servo_mode_select);
|
||||||
monitor->last_sample_ns.store(monotonicNowNs());
|
monitor->last_sample_ns.store(monotonicNowNs());
|
||||||
|
|
||||||
if (emergency_stop_source != 0) {
|
if (aubo_internal::isHardwareEmergencyStop(condition)) {
|
||||||
const bool first_sample_for_event =
|
const bool first_sample_for_event =
|
||||||
!monitor->hardware_emergency_stop_latched.exchange(true);
|
!monitor->hardware_emergency_stop_latched.exchange(true);
|
||||||
if (first_sample_for_event) {
|
if (first_sample_for_event) {
|
||||||
@ -875,8 +875,7 @@ bool hardwareEmergencyStopRecoveryCurrent(
|
|||||||
monitor->emergency_stop_source.load() == 0 && snapshot.latched &&
|
monitor->emergency_stop_source.load() == 0 && snapshot.latched &&
|
||||||
snapshot.recovery_in_progress && snapshot.epoch == token.epoch &&
|
snapshot.recovery_in_progress && snapshot.epoch == token.epoch &&
|
||||||
!snapshot.software_emergency_stop_latched &&
|
!snapshot.software_emergency_stop_latched &&
|
||||||
snapshot.latched_reason ==
|
aubo_internal::isHardwareEmergencyStop(snapshot.latched_reason) &&
|
||||||
aubo_internal::SafetyCondition::RobotEmergencyStop &&
|
|
||||||
aubo_internal::isMotionSafe(snapshot.observed);
|
aubo_internal::isMotionSafe(snapshot.observed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3899,13 +3898,16 @@ Result AuboArm::ensureMotionReady_(
|
|||||||
" rejected: hardware safety state is unavailable or stale");
|
" rejected: hardware safety state is unavailable or stale");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monitor->emergency_stop_source.load() != 0) {
|
const auto sampled_condition =
|
||||||
|
aubo_internal::effectiveSafetyCondition(
|
||||||
|
safetyConditionFromSdk(static_cast<SafetyModeType>(
|
||||||
|
monitor->safety_mode.load())),
|
||||||
|
monitor->emergency_stop_source.load());
|
||||||
|
if (aubo_internal::isHardwareEmergencyStop(sampled_condition)) {
|
||||||
const auto previous = monitor->safety_state->snapshot();
|
const auto previous = monitor->safety_state->snapshot();
|
||||||
monitor->safety_state->observe(
|
monitor->safety_state->observe(sampled_condition);
|
||||||
aubo_internal::SafetyCondition::RobotEmergencyStop);
|
|
||||||
if (!previous.latched ||
|
if (!previous.latched ||
|
||||||
previous.observed !=
|
previous.observed != sampled_condition) {
|
||||||
aubo_internal::SafetyCondition::RobotEmergencyStop) {
|
|
||||||
cancelForSafetyTransition(monitor);
|
cancelForSafetyTransition(monitor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3935,8 +3937,7 @@ Result AuboArm::ensureMotionReady_(
|
|||||||
}
|
}
|
||||||
std::string recovery_instruction =
|
std::string recovery_instruction =
|
||||||
"; clear the hardware condition and perform explicit recovery";
|
"; clear the hardware condition and perform explicit recovery";
|
||||||
if (condition ==
|
if (aubo_internal::isHardwareEmergencyStop(condition) &&
|
||||||
aubo_internal::SafetyCondition::RobotEmergencyStop &&
|
|
||||||
monitor->auto_power_on_after_hardware_estop_release &&
|
monitor->auto_power_on_after_hardware_estop_release &&
|
||||||
!monitor->automatic_recovery_suppressed.load()) {
|
!monitor->automatic_recovery_suppressed.load()) {
|
||||||
recovery_instruction =
|
recovery_instruction =
|
||||||
|
|||||||
@ -29,10 +29,23 @@ inline bool isMotionSafe(const SafetyCondition condition) noexcept
|
|||||||
condition == SafetyCondition::Reduced;
|
condition == SafetyCondition::Reduced;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isHardwareEmergencyStop(
|
||||||
|
const SafetyCondition condition) noexcept
|
||||||
|
{
|
||||||
|
return condition == SafetyCondition::SystemEmergencyStop ||
|
||||||
|
condition == SafetyCondition::RobotEmergencyStop;
|
||||||
|
}
|
||||||
|
|
||||||
inline SafetyCondition effectiveSafetyCondition(
|
inline SafetyCondition effectiveSafetyCondition(
|
||||||
const SafetyCondition reported_condition,
|
const SafetyCondition reported_condition,
|
||||||
const int robot_emergency_stop_source) noexcept
|
const int robot_emergency_stop_source) noexcept
|
||||||
{
|
{
|
||||||
|
// The source bitmask describes robot-side inputs such as the control box
|
||||||
|
// and teach pendant. Keep the SDK's SystemEmergencyStop classification for
|
||||||
|
// the separate external system-emergency input.
|
||||||
|
if (reported_condition == SafetyCondition::SystemEmergencyStop) {
|
||||||
|
return SafetyCondition::SystemEmergencyStop;
|
||||||
|
}
|
||||||
if (robot_emergency_stop_source < 0) {
|
if (robot_emergency_stop_source < 0) {
|
||||||
return SafetyCondition::Unknown;
|
return SafetyCondition::Unknown;
|
||||||
}
|
}
|
||||||
@ -89,7 +102,7 @@ inline bool shouldAutoRecoverHardwareEmergencyStop(
|
|||||||
hardware_emergency_stop_was_observed && snapshot.latched &&
|
hardware_emergency_stop_was_observed && snapshot.latched &&
|
||||||
!snapshot.recovery_in_progress &&
|
!snapshot.recovery_in_progress &&
|
||||||
!snapshot.software_emergency_stop_latched &&
|
!snapshot.software_emergency_stop_latched &&
|
||||||
snapshot.latched_reason == SafetyCondition::RobotEmergencyStop &&
|
isHardwareEmergencyStop(snapshot.latched_reason) &&
|
||||||
isMotionSafe(snapshot.observed) &&
|
isMotionSafe(snapshot.observed) &&
|
||||||
current_emergency_stop_source == 0;
|
current_emergency_stop_source == 0;
|
||||||
}
|
}
|
||||||
@ -116,7 +129,7 @@ public:
|
|||||||
|
|
||||||
const bool preserve_hardware_estop_latch =
|
const bool preserve_hardware_estop_latch =
|
||||||
condition == SafetyCondition::Unknown && latched_ &&
|
condition == SafetyCondition::Unknown && latched_ &&
|
||||||
latched_reason_ == SafetyCondition::RobotEmergencyStop &&
|
isHardwareEmergencyStop(latched_reason_) &&
|
||||||
!software_emergency_stop_latched_;
|
!software_emergency_stop_latched_;
|
||||||
if (!latched_ || recovery_in_progress_ ||
|
if (!latched_ || recovery_in_progress_ ||
|
||||||
(changed && !preserve_hardware_estop_latch)) {
|
(changed && !preserve_hardware_estop_latch)) {
|
||||||
@ -199,7 +212,7 @@ public:
|
|||||||
if (!token.valid() || token.epoch != epoch_ || !latched_ ||
|
if (!token.valid() || token.epoch != epoch_ || !latched_ ||
|
||||||
!recovery_in_progress_ ||
|
!recovery_in_progress_ ||
|
||||||
software_emergency_stop_latched_ ||
|
software_emergency_stop_latched_ ||
|
||||||
latched_reason_ != SafetyCondition::RobotEmergencyStop ||
|
!isHardwareEmergencyStop(latched_reason_) ||
|
||||||
!isMotionSafe(observed_) || !robot_running || !controller_idle ||
|
!isMotionSafe(observed_) || !robot_running || !controller_idle ||
|
||||||
!cancellation_confirmed) {
|
!cancellation_confirmed) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -28,9 +28,10 @@
|
|||||||
认证或 TLS 模式会启动失败,不会静默回退。匿名部署的恢复默认关闭,只有显式配置
|
认证或 TLS 模式会启动失败,不会静默回退。匿名部署的恢复默认关闭,只有显式配置
|
||||||
`RECOVERY_LOCAL_ONLY`、服务端确认实际 peer 为 loopback/Unix socket 且持久审计可写时才可开放。
|
`RECOVERY_LOCAL_ONLY`、服务端确认实际 peer 为 loopback/Unix socket 且持久审计可写时才可开放。
|
||||||
|
|
||||||
AUBO 另有一条设备内硬件语义:真实硬件急停曾有效、随后输入消失且控制器重新报告
|
AUBO 另有一条设备内硬件语义:示教器/控制柜 `RobotEmergencyStop` 或外部系统输入
|
||||||
`Normal/ReducedMode` 时,驱动会自动上电到 `Idle`、清理旧队列、执行 `startup()`,并在
|
`SystemEmergencyStop` 曾有效、随后输入消失且控制器重新报告 `Normal/ReducedMode` 时,
|
||||||
`Running` 下再次确认 quiescent 后解除该硬件锁存,使新的 gRPC 指令可以重新准入;
|
驱动会自动上电到 `Idle`、清理旧队列、执行 `startup()`,并在 `Running` 下再次确认
|
||||||
|
quiescent 后解除该硬件锁存,使新的 gRPC 指令可以重新准入;
|
||||||
软件 `emergencyStop()` 使用独立 `SoftwareEmergencyStop` 锁存,即使它与硬件急停重叠也绝不被
|
软件 `emergencyStop()` 使用独立 `SoftwareEmergencyStop` 锁存,即使它与硬件急停重叠也绝不被
|
||||||
硬件输入释放自动清除。自动流程不 resume、不重放旧目标;显式 Stop/PowerOff 会取消本轮自动上电。
|
硬件输入释放自动清除。自动流程不 resume、不重放旧目标;显式 Stop/PowerOff 会取消本轮自动上电。
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user