3#include "device/referee/referee.h"
7using namespace roboctrl::ctrl;
14 return std::isfinite(current) && std::isfinite(rpm) &&
15 std::fabs(current) > current_threshold && std::fabs(rpm) < speed_threshold;
18bool trigger_feed_allowed(
bool firing,
bool friction_enabled,
bool friction_ready,
19 bool motors_online,
bool jam_hold_active)
21 return firing && friction_enabled && friction_ready && motors_online && !jam_hold_active;
24bool referee_allows_feed(
unsigned caliber)
26 auto& referee = roboctrl::get<roboctrl::device::referee>();
27 if (!referee.configured() || referee.offline())
return false;
28 const auto& data = referee.data();
29 const auto now = std::chrono::steady_clock::now();
30 const auto timeout = referee.timeout();
31 if (!data.game.fresh(now, timeout) || !data.robot.fresh(now, timeout) ||
32 !data.ammunition.fresh(now, timeout))
return false;
33 return data.game.value.progress == 4 && data.robot.value.hp != 0 &&
34 data.robot.value.shooter_power &&
35 (caliber == 42 ? data.ammunition.value.bullets_42 : data.ammunition.value.bullets_17) > 0;
42 return init(info, roboctrl::get<device::dji_motor>(info.left_friction_motor),
43 roboctrl::get<device::dji_motor>(info.right_friction_motor),
44 roboctrl::get<device::dji_motor>(info.trigger_motor));
50 if (initialized_)
throw std::logic_error(
"shoot already initialized");
51 if (&left == &right || &left == &trigger || &right == &trigger ||
52 !std::isfinite(info.friction_params.acc) || info.friction_params.acc < 0 ||
53 !std::isfinite(info.friction_max_speed) || info.friction_max_speed <= 0 ||
54 !std::isfinite(info.trigger_speed) || !std::isfinite(info.friction_ready_speed) ||
55 info.friction_ready_speed <= 0 || info.friction_ready_speed > info.friction_max_speed ||
56 !std::isfinite(info.jam_current) || info.jam_current < 0 ||
57 !std::isfinite(info.jam_speed) || info.jam_speed < 0 ||
58 info.control_time <= std::chrono::steady_clock::duration::zero() ||
59 info.jam_release_time < std::chrono::steady_clock::duration::zero() ||
60 (info.bullet_caliber != 17 && info.bullet_caliber != 42))
61 throw std::invalid_argument(
"invalid shoot parameters/bindings");
64 left_friction_motor_ = &left;
65 right_friction_motor_ = &right;
66 trigger_motor_ = &trigger;
76 if (!initialized_)
throw std::logic_error(
"shoot start before init");
84 enabled_ = enabled && initialized_;
87 friction_enabled_ =
false;
88 fire_permitted_ =
false;
89 friction_ramp_.
reset();
92 for (
auto* motor : {left_friction_motor_, right_friction_motor_, trigger_motor_})
93 if (motor) motor->set_enabled(enabled_);
98 firing_ = enabled_ && state;
103 friction_enabled_ = enabled_ && state;
104 if (!friction_enabled_) firing_ =
false;
109 if (!initialized_)
return false;
111 const auto right = right_friction_motor_->
linear_speed();
112 return std::isfinite(left) && std::isfinite(right) &&
113 std::fabs(left) >= info_.friction_ready_speed &&
114 std::fabs(right) >= info_.friction_ready_speed;
117bool shoot::fire_allowed()
const
119 if (!enabled_ || !fire_permitted_ || !initialized_ ||
120 !std::isfinite(trigger_motor_->
angle_speed()) || !std::isfinite(trigger_motor_->current_feedback_raw()))
return false;
121 const bool motors_online = !left_friction_motor_->
offline() &&
123 return trigger_feed_allowed(firing_, friction_enabled_,
friction_ready(), motors_online,
124 std::chrono::steady_clock::now() < jam_release_at_) &&
125 (!info_.enforce_referee || referee_allows_feed(info_.bullet_caliber));
130 if (!initialized_)
co_return;
131 const bool motors_online = !left_friction_motor_->
offline() &&
133 if (!enabled_ || !motors_online) {
134 friction_ramp_.
reset();
135 co_await left_friction_motor_->
set(0);
136 co_await right_friction_motor_->
set(0);
138 jam_release_at_ = {};
142 if (!std::isfinite(dt) || dt < 0 || dt > std::chrono::duration<fp32>(info_.control_time * 5).count()) dt = 0;
143 friction_ramp_.
update(friction_enabled_ ? info_.friction_max_speed : 0.0f, dt);
144 co_await left_friction_motor_->
set(-friction_ramp_.
state());
145 co_await right_friction_motor_->
set(friction_ramp_.
state());
147 const auto now = std::chrono::steady_clock::now();
149 trigger_jammed(trigger_motor_->current_feedback_raw(), trigger_motor_->
rpm(), info_.jam_current, info_.jam_speed) &&
150 now >= jam_release_at_) {
151 jam_release_at_ = now + info_.jam_release_time;
152 log_warn(
"Trigger jam detected; pausing feed");
154 co_await trigger_motor_->
set_angle_speed(fire_allowed() ? info_.trigger_speed : 0.0f);
159 auto previous = std::chrono::steady_clock::time_point{};
161 const auto now = std::chrono::steady_clock::now();
162 const auto dt = previous == std::chrono::steady_clock::time_point{} ? 0.f :
163 std::chrono::duration<fp32>(now - previous).count();
bool friction_ready() const
判断摩擦轮是否达到可发射的准备速度。
void set_firing(bool state)
请求开始或停止拨弹。
roboctrl::awaitable< void > task()
周期更新摩擦轮和拨弹电机输出。
bool init(const info_type &info)
绑定发射器所需电机并初始化内部状态。
void set_friction_enabled(bool state)
请求启用或停止摩擦轮。
void set_enabled(bool enabled)
roboctrl::awaitable< void > update(fp32 dt)
void log_warn(std::format_string< Args... > fmt, Args &&...args) const
输出warn日志
void log_info(std::format_string< Args... > fmt, Args &&...args) const
输出info日志
void update(T target, T dt) noexcept
更新输出值
state_type state() const noexcept
获取当前输出状态
void reset() noexcept
清零输出值
awaitable< void > wait_for(const duration &duration)
协程任务等待。
auto spawn(task_context::task_type &&task)
添加一个协程任务到全局任务上下文中执行。
asio::awaitable< T > awaitable
协程任务类型。
bool shutdown_requested()
查询全局任务上下文是否已经进入停机流程。
auto now()
记录程序启动后的纳秒级时间戳。
bool offline() const
判断设备是否离线
virtual awaitable< void > set_angle_speed(fp32 target)
fp32 linear_speed() const
获取电机线速度(单位为m/s)
virtual awaitable< void > set(fp32 target)=0
fp32 angle_speed() const
获取电机角速度(单位为rad/s)
fp32 rpm() const
获取电机转速(单位为rpm)