GKD.RoboCtrl
RoboMaster Linux 电控:异步 IO、设备驱动与机器人控制
载入中...
搜索中...
未找到
referee.cpp
1#include "device/referee/referee.h"
2#include "io/serial.h"
3#include <stdexcept>
4
5using namespace roboctrl;
6using namespace roboctrl::device;
7
8bool referee::init(const info_type& info) {
9 if (configured_) throw std::logic_error("referee already initialized");
10 if (info.serial_name.empty() || info.offline_timeout <= std::chrono::steady_clock::duration::zero() ||
11 info.ui_period < std::chrono::milliseconds{100})
12 throw std::invalid_argument("referee needs serial, positive timeout and UI period >= 100 ms");
13 info_ = info;
14 configured_ = true;
15 return true;
16}
17void referee::connect() {
18 if (connected_) return;
19 if (!configured_) throw std::logic_error("referee connect before init");
20 serial_ = &get<io::serial>(info_.serial_name);
21 serial_->on_raw_data([this](io::byte_span data) { receive(data); });
22 connected_ = true;
23}
24void referee::start() {
25 if (started_) return;
26 if (!connected_) throw std::logic_error("referee start before connect");
27 started_ = true;
28 if (info_.ui_enabled) spawn(task());
29}
30bool referee::offline() const {
31 const auto now = referee_protocol::clock::now();
32 return !configured_ || !received_at_ || now < *received_at_ || now - *received_at_ > info_.offline_timeout;
33}
34void referee::receive(referee_protocol::bytes data) {
35 parser_.feed(data, [this](const auto& frame) {
36 const auto now = referee_protocol::clock::now();
37 if (state_.accept(frame, now)) received_at_ = now;
38 if (frame_callback_) frame_callback_(frame);
39 });
40}
41std::optional<std::pair<std::uint16_t, std::uint16_t>> referee::ui_addresses() const {
42 if (!connected_ || !info_.ui_enabled ||
43 !state_.robot.fresh(referee_protocol::clock::now(), info_.offline_timeout)) return std::nullopt;
44 const std::uint16_t sender = state_.robot.value.robot_id;
45 const auto receiver = info_.ui_receiver_id != 0 ? std::optional{info_.ui_receiver_id} : referee_protocol::client_id(sender);
46 if (!receiver) return std::nullopt;
47 return std::pair{sender, *receiver};
48}
49awaitable<void> referee::send_graphics(std::span<const referee_protocol::graphic> items) {
50 if (const auto addresses = ui_addresses()) {
51 const auto frame = referee_protocol::encode_graphics(items, addresses->first, addresses->second, sequence_++);
52 co_await serial_->send_raw(frame);
53 }
54}
55awaitable<void> referee::send_text(referee_protocol::graphic item, std::string_view text) {
56 if (const auto addresses = ui_addresses()) {
57 const auto frame = referee_protocol::encode_text(item, text, addresses->first, addresses->second, sequence_++);
58 co_await serial_->send_raw(frame);
59 }
60}
61awaitable<void> referee::delete_graphics(std::uint8_t operation, std::uint8_t layer) {
62 if (const auto addresses = ui_addresses()) {
63 const auto frame = referee_protocol::encode_delete(operation, layer, addresses->first, addresses->second, sequence_++);
64 co_await serial_->send_raw(frame);
65 }
66}
67awaitable<void> referee::task() {
69 while (true) {
70 if (const auto addresses = ui_addresses()) {
71 const auto graphics = referee_protocol::status_graphics(ui_status_, refresh.add_required(*addresses));
72 // Use the same validated address for planning and encoding. Traffic
73 // without fresh robot identity must not consume the initial Add.
74 const auto frame = referee_protocol::encode_graphics(
75 graphics, addresses->first, addresses->second, sequence_++);
76 co_await serial_->send_raw(frame);
77 refresh.submitted(*addresses);
78 } else {
79 refresh.reset();
80 }
81 co_await wait_for(info_.ui_period);
82 }
83}
void receive(referee_protocol::bytes data)
Definition referee.cpp:34
void on_raw_data(callback_fn< byte_span > auto fn)
Definition serial.h:66
std::span< const std::byte > byte_span
只读 byte span。
Definition base.hpp:45
awaitable< void > wait_for(const duration &duration)
协程任务等待。
Definition async.hpp:262
auto spawn(task_context::task_type &&task)
添加一个协程任务到全局任务上下文中执行。
Definition async.hpp:191
asio::awaitable< T > awaitable
协程任务类型。
Definition async.hpp:46
auto now()
记录程序启动后的纳秒级时间戳。
Definition utils.hpp:158
串口裸 IO 封装。