halx_driver
読み取り中…
検索中…
一致する文字列を見つけられません
unitree_go.hpp
[詳解]
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <cmath>
6#include <cstddef>
7#include <cstdint>
8#include <numbers>
9#include <optional>
10#include <utility>
11
12#include <halx/peripheral/uart.hpp>
13
14namespace halx::driver {
15
16enum class UnitreeGoMode : uint8_t {
20};
21
29
31 uint8_t id;
33 float torque;
34 float radps;
35 float rad;
36 float kp;
37 float kd;
38};
39
41 uint8_t id;
43 float torque;
44 float radps;
45 float rad;
46 int8_t temp;
48 int16_t force;
49};
50
51class UnitreeGo {
52public:
53 UnitreeGo(peripheral::UartBase &uart) : uart_{uart} {}
54
55 std::optional<UnitreeGoFeedback> transmit(const UnitreeGoCommand &command) {
56 auto tx_buf = to_uart_buf(command);
57 std::array<uint8_t, 16> rx_buf;
58 uart_.flush();
59 if (!uart_.transmit(tx_buf.data(), tx_buf.size(), 10)) {
60 return std::nullopt;
61 }
62 if (!uart_.receive(rx_buf.data(), rx_buf.size(), 10)) {
63 return std::nullopt;
64 }
65 return to_unitree_go_feedback(rx_buf);
66 }
67
68private:
69 peripheral::UartBase &uart_;
70
71 static inline std::array<uint8_t, 17>
72 to_uart_buf(const UnitreeGoCommand &command) {
73 int16_t tau_set = std::clamp(command.torque, -127.99f, 127.99f) * 256.0f;
74 int16_t omega_set = std::clamp(command.radps, -804.0f, 804.0f) /
75 (2.0f * std::numbers::pi) * 256.0f;
76 int32_t theta_set = command.rad / (2.0f * std::numbers::pi) * 32768.0f;
77 int16_t k_pos = std::clamp(command.kp, 0.0f, 25.599f) * 1280.0f;
78 int16_t k_spd = std::clamp(command.kd, 0.0f, 25.599f) * 1280.0f;
79
80 std::array<uint8_t, 17> buf;
81 buf[0] = 0xFE;
82 buf[1] = 0xEE;
83 buf[2] = std::to_underlying(command.mode) << 4 | command.id;
84 buf[3] = tau_set & 0xFF;
85 buf[4] = (tau_set >> 8) & 0xFF;
86 buf[5] = omega_set & 0xFF;
87 buf[6] = (omega_set >> 8) & 0xFF;
88 buf[7] = theta_set & 0xFF;
89 buf[8] = (theta_set >> 8) & 0xFF;
90 buf[9] = (theta_set >> 16) & 0xFF;
91 buf[10] = (theta_set >> 24) & 0xFF;
92 buf[11] = k_pos & 0xFF;
93 buf[12] = (k_pos >> 8) & 0xFF;
94 buf[13] = k_spd & 0xFF;
95 buf[14] = (k_spd >> 8) & 0xFF;
96 uint16_t crc = crc16_ccitt(buf.data(), 15);
97 buf[15] = crc & 0xFF;
98 buf[16] = (crc >> 8) & 0xFF;
99 return buf;
100 }
101
102 static inline std::optional<UnitreeGoFeedback>
103 to_unitree_go_feedback(const std::array<uint8_t, 16> &buf) {
104 if (buf[0] != 0xFD || buf[1] != 0xEE) {
105 return std::nullopt;
106 }
107 uint16_t crc = (buf[15] << 8) | buf[14];
108 if (crc != crc16_ccitt(buf.data(), 14)) {
109 return std::nullopt;
110 }
111
112 UnitreeGoFeedback feedback;
113 feedback.id = buf[2] & 0x0F;
114 feedback.mode = static_cast<UnitreeGoMode>((buf[2] >> 4) & 0x07);
115 feedback.torque = static_cast<int16_t>((buf[4] << 8) | buf[3]) / 256.0f;
116 feedback.radps = static_cast<int16_t>((buf[6] << 8) | buf[5]) / 256.0f *
117 2.0f * std::numbers::pi;
118 feedback.rad = static_cast<int32_t>((buf[10] << 24) | (buf[9] << 16) |
119 (buf[8] << 8) | buf[7]) /
120 32768.0f * 2.0f * std::numbers::pi;
121 feedback.temp = buf[11];
122 feedback.error = static_cast<UnitreeGoError>(buf[12] & 0x07);
123 feedback.force = (buf[13] & 0x7F) | ((buf[12] >> 3) & 0x1F);
124 return feedback;
125 }
126
127 static inline uint16_t crc16_ccitt(const uint8_t *data, size_t size) {
128 uint16_t crc = 0;
129 for (size_t i = 0; i < size; ++i) {
130 crc ^= data[i];
131 for (uint8_t j = 0; j < 8; ++j) {
132 crc = crc & 1 ? (crc >> 1) ^ 0x8408 : crc >> 1;
133 }
134 }
135 return crc;
136 }
137};
138
139} // namespace halx::driver
UnitreeGo(peripheral::UartBase &uart)
Definition unitree_go.hpp:53
std::optional< UnitreeGoFeedback > transmit(const UnitreeGoCommand &command)
Definition unitree_go.hpp:55
Definition amt21.hpp:10
UnitreeGoMode
Definition unitree_go.hpp:16
@ FOC
Definition unitree_go.hpp:18
@ CALIBRATION
Definition unitree_go.hpp:19
@ LOCK
Definition unitree_go.hpp:17
UnitreeGoError
Definition unitree_go.hpp:22
@ NORMAL
Definition unitree_go.hpp:23
@ OVERCURRENT
Definition unitree_go.hpp:25
@ ENCODER_FAULT
Definition unitree_go.hpp:27
@ OVERVOLTAGE
Definition unitree_go.hpp:26
@ OVERHEATING
Definition unitree_go.hpp:24
Definition unitree_go.hpp:30
UnitreeGoMode mode
Definition unitree_go.hpp:32
float kp
Definition unitree_go.hpp:36
float rad
Definition unitree_go.hpp:35
uint8_t id
Definition unitree_go.hpp:31
float radps
Definition unitree_go.hpp:34
float torque
Definition unitree_go.hpp:33
float kd
Definition unitree_go.hpp:37
Definition unitree_go.hpp:40
uint8_t id
Definition unitree_go.hpp:41
UnitreeGoMode mode
Definition unitree_go.hpp:42
float rad
Definition unitree_go.hpp:45
int16_t force
Definition unitree_go.hpp:48
int8_t temp
Definition unitree_go.hpp:46
float radps
Definition unitree_go.hpp:44
float torque
Definition unitree_go.hpp:43
UnitreeGoError error
Definition unitree_go.hpp:47