摩擦轮模块使用说明
![](https://img.shields.io/badge/version-0.9.0-green)
![](https://img.shields.io/badge/author-LouKaiyang-lightgrey)
1 前言
摩擦轮组件的代码架构和拨弹盘组件基本一致,不再赘述。
若对功能模块组件的代码架构存在疑问,建议结合源码阅读拨弹盘使用说明。
当前摩擦轮组件为基本版,仅有同级两个电机。
对于多级摩擦轮发射机构,每一级只有两个电机的情况,可以分别将每一级注册为独立的摩擦轮模块。
2 配置说明
摩擦轮所需配置参数如下
C++ |
---|
| struct FricConfig2Motor {
float default_spd_ref; // 摩擦轮期望速度预设值, >0, 无默认值, rad/s
float default_spd_ref_backward = -100.0f; // 摩擦轮反转目标速度, <0, 默认值 -100 rad/s, 反转模式是为了将卡在摩擦轮中间的弹丸回退出来,转速不易过快
float stuck_curr_thre = 14.0f; // 用于判断摩擦轮堵转的电流阈值, >0, 默认值 14 A
float spd_delta_thre = 10.0f; // 用于判断摩擦轮速度保持恒定的阈值, >0, 默认值 10 rad/s
float spd_err_thre = 5.0f; // 用于判断摩擦轮速度跟上期望转速的阈值, >0, 默认值 5 rad/s
float spd_stop_thre = 100.0f; // 摩擦轮Stop模式,转速小于该阈值后,停止控制电机, >0, 默认值 100 rad/s
/* 优化项,建议开启 */
bool opt_spd_same_pid_enabled = false; // 是否使用双摩擦轮同速PID(期望为0,反馈输入为两轮差速,输出分别正负作用到两个电机上)
BulletSpdClosedLoop opt_blt_spd_cl; // 弹速闭环优化
};
/* 优化项:弹速闭环 */
struct BulletSpdClosedLoop {
bool is_enabled = false; // 是否开启弹速闭环
float min_reasonable_blt_spd; // 最小合理弹丸速度, >0, 无默认值, m/s, 小于该值认为裁判系统反馈数据错误
float max_reasonable_blt_spd; // 最大合理弹丸速度, >0, 无默认值, m/s, 大于该值认为裁判系统反馈数据错误
float min_target_blt_spd; // 弹丸速度期望值区间下限, >0, 无默认值, m/s
float max_target_blt_spd; // 弹丸速度期望值区间上限, >0, 无默认值, m/s
float spd_gradient = 5.0f; // 摩擦轮转速调整梯度, >=0, 默认值 5 rad/s
};
|
配置参数结构体:
成员名称 |
默认值 |
说明 |
备注 |
default_spd_ref |
无 |
摩擦轮预设期望转速(rad/s) |
开启弹速闭环优化后,摩擦轮实际期望转速可能与default_spd_ref 不一致。 |
default_spd_ref_backward |
-100.0f |
摩擦轮反转时的期望转速(rad/s) |
摩擦轮反转模式是为了把卡在摩擦轮中的弹丸回退出来,转速不宜过快。 |
stuck_curr_thre |
14.0f |
用于判断摩擦轮是否堵转的电流阈值(A) |
默认值适用于3508电机。 |
spd_delta_thre |
10.0f |
用于判断摩擦轮转速波动的阈值(rad/s) |
若摩擦轮当前反馈转速与上一帧的反馈转速差的绝对值小于阈值,则认为摩擦轮转速稳定。 |
spd_err_thre |
5.0f |
用于判断摩擦轮转速与期望值差距的阈值(rad/s) |
若摩擦轮当前反馈转速与期望转速差的绝对值小于阈值,则认为摩擦轮转速达到期望。在复活模式下,若两摩擦轮转速稳定且达到期望,持续200ms后,进入正常工作模式。 |
spd_stop_thre |
100.0f |
摩擦轮停止模式下停止控制摩擦轮的临界转速(rad/s) |
摩擦轮由正常工作模式切换为停止模式后,若直接停止控制电机,受惯性影响,摩擦轮需要耗费极长时间才能完全停转;若始终控制电机转速为0 ,不便于机械队员用手转动摩擦轮做相关检查。 综合以上两种控制策略,当摩擦轮反馈转速大于等于spd_stop_thre 时,控制电机转速为0 ;当摩擦轮反馈转速小于spd_stop_thre 时,停止控制电机。 |
opt_spd_same_pid_enabled |
false |
是否使用双摩擦轮同速PID优化 |
两摩擦轮转速保持一致,比两摩擦轮的转速与期望值保持一致更重要。同速PID的参考值为0 ,输入为两摩擦轮的差速,输出分别加/减到两个摩擦轮转速PID的输出上。 若要开启同速PID优化,必须注册同速PID。同速PID参数不宜过大。 |
opt_blt_spd_cl |
无 |
弹速闭环优化 |
|
弹速闭环优化结构体:
成员名称 |
默认值 |
说明 |
备注 |
is_enabled |
false |
是否开启弹速闭环优化 |
|
min_reasonable_blt_spd |
无 |
最小合理弹丸速度(m/s) |
若反馈弹速低于该值,则认为反馈弹速不合理,不予以采用。 |
max_reasonable_blt_spd |
无 |
最大合理弹丸速度(m/s) |
若反馈弹速高于该值,则认为反馈弹速不合理,不予以采用。 |
min_target_blt_spd |
无 |
最小期望弹丸速度(m/s) |
若反馈弹速低于该值,则将摩擦轮实际期望转速加spd_gradient 。 |
max_target_blt_spd |
无 |
最大期望弹丸速度(m/s) |
若反馈弹速高于该值,则将摩擦轮实际期望转速减spd_gradient 。 |
spd_gradient |
5.0f |
摩擦轮调整梯度(rad/s) |
|
3 使用方法
3.1 摩擦轮的实例化与初始化
【建议】 自己写一对 ins_fric.hpp 和 ins_fric.cpp 文件,依照全局单例的设计思想,定义拨弹盘的全局单例,并给出接口函数抛出拨弹盘实例指针。
在其中包含fric_2motor.hpp
文件,并给出接口函数。
C++ |
---|
| #include "fric_2motor.hpp"
hello_world::module::Fric* CreateFric();
|
在其中包含ins_fric.hpp
,定义拨弹盘全局实例,注册PID
和电机指针,实现接口函数。
C++ |
---|
| #include "ins_fric.hpp"
/* 以下配置参数适用于25赛季初英雄机器人 */
hello_world::module::Fric::Config kFricConfig = {
.default_spd_ref = 640.0f, ///< 摩擦轮期望速度预设值 rad/s
.default_spd_ref_backward = -100.0f, ///< 摩擦轮反转目标速度
.stuck_curr_thre = 14.0f, ///< 用于判断摩擦轮堵转的电流阈值
.spd_delta_thre = 10.0f, ///< 用于判断摩擦轮速度保持恒定的阈值 rad/s
.spd_err_thre = 5.0f, ///< 用于判断摩擦轮速度跟上期望转速的阈值 rad/s
.opt_spd_same_pid_enabled = true,
.opt_blt_spd_cl = {
.is_enabled = true,
.min_reasonable_blt_spd = 14.0f,
.max_reasonable_blt_spd = 16.5f,
.min_target_blt_spd = 15.9f,
.max_target_blt_spd = 15.3f,
.spd_gradient = 5.0f,
}
};
hello_world::module::Fric unique_fric = hello_world::module::Fric(kFricConfig);
hello_world::module::Fric* CreateFric()
{
static bool is_fric_created = false;
if (!is_fric_created) {
unique_fric.registerMotor(CreateMotorFricLeft(), hello_world::module::Fric::MotorIdx::kFirst); // 注册第一个摩擦轮电机
unique_fric.registerMotor(CreateMotorFricRight(), hello_world::module::Fric::MotorIdx::kSecond); // 注册第二个摩擦轮电机
unique_fric.registerPid(CreatePidMotorFricLeft(), hello_world::module::Fric::PidIdx::kFirst); // 注册第一个摩擦轮电机PID
unique_fric.registerPid(CreatePidMotorFricRight(), hello_world::module::Fric::PidIdx::kSecond); // 注册第二个摩擦轮电机PID
/* 如果未开启同速PID优化,则无需注册同速PID */
unique_fric.registerPid(CreatePidFricSameSpd(), hello_world::module::Fric::PidIdx::kSameSpd); // 注册同速PID
is_fric_created = true;
}
return &unique_fric;
}
|
3.2 更新裁判系统数据
C++ |
---|
| void updateRfrData(const FricRfrInputData &inp_data);
// 用法:
hello_world::module::Fric* fric_ptr_ = CreateFric();
hello_world::module::Fric::RfrInputData fric_rfr_input_data;
/* 设置 rfr_input_data, fric_ok_flag, 略 */
fric_ptr_->updateRfrData(fric_rfr_input_data);
|
updateRfrData()
用于更新拨弹盘所需的裁判系统反馈数据,不更新时,采用用户上一次的更新值或者默认值。
裁判系统数据结构体如下:
C++ |
---|
| struct FricRfrInputData {
bool is_power_on = false; // 摩擦轮电源是否开启
float is_new_bullet_shot = false; // 是否有一颗新弹丸射出
float bullet_spd; // 发射机构检测到的弹丸速度, 无默认值, m/s
};
|
【注意】
- 裁判系统反馈数据完全用于弹速闭环优化。(如
is_new_bullet_shot
,bullet_spd
;is_power_on
不会用到,状态机内部根据是否与电机正常通信来判断是否上电。)因此,如果配置参数未开启弹速闭环优化,可以不更新裁判系统数据。
is_new_bullet_shot
的读取方式见拨弹盘使用说明 1.2节【注意】第2点
3.3 设定工作模式
用户需要根据自身需求设定工作模式。
C++ |
---|
| void setWorkingMode(WorkingMode mode) { working_mode_ = mode; }
// 用法:
hello_world::module::Fric* fric_ptr_ = CreateFric();
typedef hello_world::module::Fric::WorkingMode WorkingMode;
WorkingMode working_mode = WorkingMode::kStop; // 停止模式
WorkingMode working_mode = WorkingMode::kShoot; // 正常工作模式
WorkingMode working_mode = WorkingMode::kBackward; // 倒转模式(为了退出卡住的弹丸)
fric_ptr_->setWorkingMode(WorkingMode);
|
3.4 运行摩擦轮状态机
当主状态机处于Dead
或者Resurrection
状态时,如下运行摩擦轮状态机:
C++ |
---|
| hello_world::module::Fric *fric_ptr_ = CreateFric();
fric_ptr_->update();
fric_ptr_->standby();
|
【说明】
摩擦轮状态机的standby()
运行函数实现了快速停转+停转后不控制摩擦轮电机的效果。
考虑到关闭遥控器杀死主状态机后,主状态机在Dead
状态和Resurrection
状态反复运行,因此需要让主状态机在这两个状态下调用standby()
,保证关闭遥控器后摩擦轮快速停转,并且可以上手把玩。
当主状态机处于Working
状态时,如下运行摩擦轮状态机:
C++ |
---|
| hello_world::module::Fric *fric_ptr_ = CreateFric();
fric_ptr_->update();
fric_ptr_->run();
|
此外,摩擦轮状态机还提供了一个复位接口,以便于重置整个摩擦轮状态机:
C++ |
---|
| hello_world::module::Fric *fric_ptr_ = CreateFric();
fric_ptr_->reset();
|
3.5(补充) 读取摩擦轮状态机内部数据
除摩擦轮当前运行状态外,一般无需读取摩擦轮状态机的内部数据。平常调试时,可以通过Ozone直接查看实例的内部数据。
由于拨弹盘状态机需要摩擦轮运行状态,因此提供了相应接口:
C++ |
---|
| hello_world::module::Fric *fric_ptr_ = CreateFric();
bool is_fric_ready = fric_ptr_->getStatus();
|
此外,为了规范性,摩擦轮状态机还提供了以下接口:
C++ |
---|
| Config &getConfig() { return cfg_; }
const Config &getConfig() const { return cfg_; }
WorkingMode getWorkingMode() const { return working_mode_; }
|
附录
版本说明
版本号 |
发布日期 |
说明 |
贡献者 |
![](https://img.shields.io/badge/version-0.9.0-green) |
2025.02.07 |
2摩擦轮模块使用说明 |
娄开杨 |