GKD.RoboCtrl
RoboMaster Linux 电控:异步 IO、设备驱动与机器人控制
载入中...
搜索中...
未找到
state.hpp
1#pragma once
2
3#include "device/referee/protocol.hpp"
4#include <array>
5#include <bit>
6#include <chrono>
7#include <cmath>
8#include <optional>
9
10namespace roboctrl::device::referee_protocol {
11
12using clock = std::chrono::steady_clock;
13template<typename T> struct timed_value {
14 T value {};
15 std::optional<clock::time_point> received_at;
16 bool fresh(clock::time_point now, clock::duration timeout) const {
17 return received_at && now >= *received_at && now - *received_at <= timeout;
18 }
19 void set(T next, clock::time_point now) { value = next; received_at = now; }
20};
22 std::uint8_t game_type {}, progress {};
23 std::uint16_t remaining_seconds {};
24 std::uint64_t timestamp {};
25};
27 std::uint8_t robot_id {}, level {};
28 std::uint16_t hp {}, max_hp {}, cooling_rate {}, cooling_limit {}, chassis_power_limit {};
29 bool gimbal_power {}, chassis_power {}, shooter_power {};
30};
31struct power_heat {
32 std::uint16_t buffer_energy {}, heat_17_1 {}, heat_17_2 {}, heat_42 {};
33};
34struct bullet_allowance { std::uint16_t bullets_17 {}, bullets_42 {}, coins {}; };
35struct robot_position { float x {}, y {}, yaw {}; };
36struct shot_data { std::uint8_t caliber {}, shooter_id {}, frequency {}; float speed {}; };
37struct referee_warning { std::uint8_t level {}, robot_id {}, count {}; };
38
42struct state {
52
53 bool accept(const frame& input, clock::time_point now) {
54 const bytes p{input.payload};
55 switch (input.command) {
56 case 0x0001:
57 if (p.size() != 11 || (u8(p[0]) >> 4) > 5) return false;
58 game.set({static_cast<std::uint8_t>(u8(p[0]) & 0x0f),
59 static_cast<std::uint8_t>(u8(p[0]) >> 4), u16(p, 1),
60 u32(p, 3) | (std::uint64_t{u32(p, 7)} << 32)}, now);
61 return true;
62 case 0x0002:
63 if (p.size() != 1 || u8(p[0]) > 2) return false;
64 winner.set(u8(p[0]), now);
65 return true;
66 case 0x0003: {
67 if (p.size() != 32) return false;
68 std::array<std::uint16_t, 16> hp{};
69 for (std::size_t i = 0; i < hp.size(); ++i) hp[i] = u16(p, i * 2);
70 robot_hp.set(hp, now);
71 return true;
72 }
73 case 0x0104:
74 if (p.size() != 3) return false;
75 warning.set({u8(p[0]), u8(p[1]), u8(p[2])}, now);
76 return true;
77 case 0x0201: {
78 if (p.size() != 13 || u8(p[0]) == 0 || (u8(p[12]) & 0xf8)) return false;
79 robot.set({u8(p[0]), u8(p[1]), u16(p, 2), u16(p, 4), u16(p, 6),
80 u16(p, 8), u16(p, 10), bool(u8(p[12]) & 1), bool(u8(p[12]) & 2),
81 bool(u8(p[12]) & 4)}, now);
82 return true;
83 }
84 case 0x0202:
85 if (p.size() != 16) return false;
86 power.set({u16(p, 8), u16(p, 10), u16(p, 12), u16(p, 14)}, now);
87 return true;
88 case 0x0203: {
89 if (p.size() != 12) return false;
90 const robot_position next{std::bit_cast<float>(u32(p, 0)),
91 std::bit_cast<float>(u32(p, 4)), std::bit_cast<float>(u32(p, 8))};
92 if (!std::isfinite(next.x) || !std::isfinite(next.y) || !std::isfinite(next.yaw)) return false;
93 position.set(next, now);
94 return true;
95 }
96 case 0x0207: {
97 if (p.size() != 7) return false;
98 const auto speed = std::bit_cast<float>(u32(p, 3));
99 if (!std::isfinite(speed) || speed < 0 || u8(p[0]) < 1 || u8(p[0]) > 2) return false;
100 shot.set({u8(p[0]), u8(p[1]), u8(p[2]), speed}, now);
101 return true;
102 }
103 case 0x0208:
104 if (p.size() != 6) return false;
105 ammunition.set({u16(p, 0), u16(p, 2), u16(p, 4)}, now);
106 return true;
107 default:
108 return false;
109 }
110 }
111};
112} // namespace roboctrl::device::referee_protocol