GKD.RoboCtrl
RoboMaster Linux 电控:异步 IO、设备驱动与机器人控制
载入中...
搜索中...
未找到
protocol.hpp
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <bit>
6#include <cmath>
7#include <cstddef>
8#include <cstdint>
9#include <limits>
10#include <optional>
11#include <span>
12
13namespace roboctrl::device::motor_protocol {
14
15using frame = std::array<std::byte, 8>;
16
17inline uint8_t octet(std::span<const std::byte> data, size_t index) {
18 return std::to_integer<uint8_t>(data[index]);
19}
20
21inline uint16_t read_u16_le(std::span<const std::byte> data, size_t index) {
22 return static_cast<uint16_t>(octet(data, index) | uint16_t{octet(data, index + 1)} << 8);
23}
24
25inline int16_t read_i16_le(std::span<const std::byte> data, size_t index) {
26 return std::bit_cast<int16_t>(read_u16_le(data, index));
27}
28
29inline int16_t gated_current(float command, float scale, float limit, bool enabled, bool online) {
30 if (!enabled || !online || !std::isfinite(command) || !std::isfinite(scale)
31 || std::isnan(limit) || limit < 0.f) return 0;
32 const float bound = std::min(limit, 32767.f);
33 return static_cast<int16_t>(std::clamp(command * std::clamp(scale, 0.f, 1.f), -bound, bound));
34}
35
37 uint8_t temperature;
38 int16_t current_raw;
39 int16_t speed_raw;
40 uint16_t encoder;
41};
42
43inline std::optional<m9025_feedback> decode_m9025(std::span<const std::byte> data) {
44 if (data.size() != 8 || octet(data, 0) != 0xa0) return std::nullopt;
45 return m9025_feedback{octet(data, 1), read_i16_le(data, 2), read_i16_le(data, 4), read_u16_le(data, 6)};
46}
47
48inline frame encode_m9025_current(int16_t current) {
49 frame data{};
50 const auto raw = std::bit_cast<uint16_t>(current);
51 data[0] = std::byte{0xa0};
52 data[4] = static_cast<std::byte>(raw & 0xff);
53 data[5] = static_cast<std::byte>(raw >> 8);
54 return data;
55}
56
58 float position_max {12.5f};
59 float velocity_max {45.f};
60 float torque_max {20.f};
61};
62
64 uint8_t controller_id;
65 uint8_t status;
66 uint16_t position_raw;
67 float position_rad;
68 float velocity_rad_s;
69 float torque_nm;
70 uint8_t mos_temperature;
71 uint8_t rotor_temperature;
72};
73
74inline bool valid_ranges(const j6006_ranges& ranges) {
75 return std::isfinite(ranges.position_max) && ranges.position_max > 0.f
76 && std::isfinite(ranges.velocity_max) && ranges.velocity_max > 0.f
77 && std::isfinite(ranges.torque_max) && ranges.torque_max > 0.f;
78}
79
80inline std::optional<j6006_feedback> decode_j6006(
81 std::span<const std::byte> data, uint16_t id, const j6006_ranges& ranges) {
82 if (data.size() != 8 || (octet(data, 0) & 0x0f) != (id & 0x0f) || !valid_ranges(ranges))
83 return std::nullopt;
84 const auto status = static_cast<uint8_t>(octet(data, 0) >> 4);
85 if (status > 1 && (status < 8 || status > 14)) return std::nullopt;
86 const auto position = static_cast<uint16_t>(uint16_t{octet(data, 1)} << 8 | octet(data, 2));
87 const auto velocity = static_cast<uint16_t>(uint16_t{octet(data, 3)} << 4 | octet(data, 4) >> 4);
88 const auto torque = static_cast<uint16_t>((octet(data, 4) & 0x0f) << 8 | octet(data, 5));
89 return j6006_feedback{
90 static_cast<uint8_t>(octet(data, 0) & 0x0f), static_cast<uint8_t>(octet(data, 0) >> 4), position,
91 (2.f * static_cast<float>(position) / 65535.f - 1.f) * ranges.position_max,
92 (2.f * static_cast<float>(velocity) / 4095.f - 1.f) * ranges.velocity_max,
93 (2.f * static_cast<float>(torque) / 4095.f - 1.f) * ranges.torque_max,
94 octet(data, 6), octet(data, 7)};
95}
96
97inline std::array<std::byte, 4> encode_j6006_velocity(float velocity) {
98 static_assert(sizeof(float) == 4 && std::numeric_limits<float>::is_iec559);
99 std::array<std::byte, 4> data{};
100 const auto raw = std::bit_cast<uint32_t>(std::isfinite(velocity) ? velocity : 0.f);
101 for (size_t i = 0; i < 4; ++i) data[i] = static_cast<std::byte>((raw >> (8 * i)) & 0xff);
102 return data;
103}
104
105inline frame encode_j6006_enabled(bool enabled) {
106 frame data;
107 data.fill(std::byte{0xff});
108 data[7] = enabled ? std::byte{0xfc} : std::byte{0xfd};
109 return data;
110}
111
112inline float gated_j6006_velocity(float velocity, bool enabled, bool online, uint8_t status) {
113 return enabled && online && status == 1 && std::isfinite(velocity) ? velocity : 0.f;
114}
115
116} // namespace roboctrl::device::motor_protocol