13using namespace std::chrono_literals;
15using namespace roboctrl;
28constexpr fp32 _rpm_to_rad_s = 2.f *
Pi_f / 60.f;
29constexpr fp32 _ecd_8192_to_rad = 2.f *
Pi_f / 8192.f;
31static std::string __motor_tyep_to_string(dji_motor::type type){
33 case roboctrl::device::dji_motor::M2006:
35 case roboctrl::device::dji_motor::M3508:
37 case roboctrl::device::dji_motor::M6020:
47 std::fill(motors_.begin(),motors_.end(),
nullptr);
48 log_info(
"Dji Motor Group created on {}",info.can_name);
53 for(
auto m : motors_){
54 if(
m->can_pkg_id() ==
motor->can_pkg_id()){
60 motors_.push_back(
motor);
63std::pair<uint16_t, uint16_t> dji_motor::can_pkg_id()
const {
67 if (info_.id >= 1 && info_.id <= 4)
68 return {0x200,
static_cast<uint16_t>(info_.id - 1)};
69 else if (info_.id >= 5 && info_.id <= 8)
70 return {0x1ff,
static_cast<uint16_t>(info_.id - 5)};
72 log_error(
"invalid dji motor id: {}", info_.id);
76 if (info_.id >= 1 && info_.id <= 4)
77 return {0x1ff,
static_cast<uint16_t>(info_.id - 1)};
78 else if (info_.id >= 5 && info_.id <= 8)
79 return {0x2ff,
static_cast<uint16_t>(info_.id - 5)};
81 log_error(
"invalid gm6020 id: {}", info_.id);
88 std::array<std::byte,8> data{};
91 for (
auto motor : motors_) {
94 auto [
can_id, index] = motor->can_pkg_id();
96 auto cur = motor->current();
97 std::size_t
offset =
static_cast<std::size_t
>(index) * 2;
98 if (
offset + 1 >= data.size()) {
99 log_error(
"dji current index out of range: id={}, index={}", motor->info_.can_name, index);
115 co_await send_command(0x1ff);
116 co_await send_command(0x200);
117 co_await send_command(0x2ff);
125 pid_{info.pid_params},
129 log_debug(
"Dji \"{}\" motor {} created on can \"{}\" with pid(p={},i={},d={},max iout={},max out={})",
130 __motor_tyep_to_string(info.type_),
136 info.pid_params.max_iout,
137 info.pid_params.max_out
145 case dji_motor::M2006:
146 reduction_ratio_ = 1.f / 36.f;
149 case dji_motor::M3508:
150 reduction_ratio_ = 1.f / 19.f;
153 case dji_motor::M6020:
154 reduction_ratio_ = 1.f;
161 angle_speed_ = _rpm_to_rad_s *
static_cast<float>(
utils::make_i16(
pkg.speed_h,
pkg.speed_l)) * reduction_ratio_;
164 pid_.update(linear_speed());
165 current_ = pid_.state();
167 log_debug(
"angle:{}, speed:{}, torque:{} ,linear speed:{},target speed:{}",this->angle_,this->angle_speed_,this->torque_,linear_speed(),pid_.target());
171 group.register_motor(
this);
187 co_await wait_for(info_.control_time);
基于 Linux SocketCAN 的 CAN 总线封装。
dji_motor_group(info_type info)
构造分组。
awaitable< void > task()
与调度器协同的任务,负责读取反馈等。
void register_motor(dji_motor *motor)
注册单个电机到分组内。
awaitable< void > set(fp32 speed)
设置目标电流或速度(取决于电调模式)。
void log_error(std::format_string< Args... > fmt, Args &&...args) const
输出error日志
void log_debug(std::format_string< Args... > fmt, Args &&...args) const
输出debug日志
void log_info(std::format_string< Args... > fmt, Args &&...args) const
输出info日志
awaitable< void > wait_for(const duration &duration)
协程任务等待。
auto spawn(task_context::task_type &&task)
添加一个协程任务到全局任务上下文中执行。
asio::awaitable< T > awaitable
协程任务类型。
constexpr std::byte to_byte(std::integral auto v) noexcept
辅助将整数转换为 std::byte。
constexpr int16_t make_i16(int16_t high, int16_t low) noexcept
将高低字节组合成有符号 16 位整数。
constexpr uint16_t make_u16(uint16_t high, uint16_t low) noexcept
将高低字节组合成无符号 16 位整数。
T state() const
获取最新的控制输出。
void set_target(T target)
设置期望目标。
constexpr auto Pi_f
单精度浮点类型的 Pi 常量。