问题现象
第一批买的ROS手柄存在问题:
1.不能自动关机,导致耗电量大,一天1充/2充
2.不同手柄一致性不一样,右摇杆上下方向,键值不一样
之前用过北通游戏手柄,感觉比较好用,项目中买一个无线版测试,验证.
遇到问题
1.问题1: 开发板无法识别input设备, /dev/input/jsx 枚举失败.
解决方法:ubuntu/linux 北通无线游戏手柄不识别
2.问题2: 北通游戏手柄 左右摇杆 灵敏度/频率过高
实测: 左右摇杆输出频率达到100Hz
rosrun joy joy_node
rostopic hz /joy
subscribed to [/joy]
average rate: 152.672
min: 0.001s max: 0.107s std dev: 0.01296s window: 81
average rate: 162.566
min: 0.001s max: 0.107s std dev: 0.01199s window: 241
average rate: 131.580
min: 0.001s max: 0.247s std dev: 0.02013s window: 308
尝试解决方案
1.咨询北通官方技术支持,修改灵敏度. --NG, 本款手柄不支持修改灵敏度.
2.修改joy_node参数 --OK
3.修改源码 --OK
方法1:修改joy_node参数
<launch>
<!--手柄控制-->
<node pkg="joy" name="joy_node" type="joy_node" output = "screen">
<param name="coalesce_interval" value="0.2" type="double"/>
</node>
</launch>
代码原理:
github搜索: joystick_drivers joy github代码链接
joy_node.cpp
nh_param.param<double>("coalesce_interval", coalesce_interval_, 0.001); #launch 修改此参数
bool publish_now = false;
bool publish_soon = false;
int select_out = select(joy_fd+1, &set, nullptr, nullptr, &tv);
if (read(joy_fd, &event, sizeof(js_event)) == -1 && errno != EAGAIN)
{
break; // Joystick is probably closed. Definitely occurs.
}
if (publish_now)
{
// Assume that all the JS_EVENT_INIT messages have arrived already.
// This should be the case as the kernel sends them along as soon as
// the device opens.
joy_msg.header.stamp = ros::Time().now();
joy_msg.header.frame_id = joy_dev_.c_str();
pub_.publish(joy_msg);
publish_now = false;
tv_set = false;
publication_pending = false;
publish_soon = false;
pub_count_++;
}
if (!publication_pending && publish_soon)
{
tv.tv_sec = trunc(coalesce_interval_);
tv.tv_usec = (coalesce_interval_ - tv.tv_sec) * 1e6;
publication_pending = true;
tv_set = true;
}
逻辑概要:
话题发布频率 --> select超时 -->
tv_set —> publication_pending --> publish_now --> 话题发布pub_.publish(joy_msg)
逻辑有点复杂,我是通过vscode + gdb调试, 在变量变化处加断点, 才理清逻辑.
实测结果:
rostopic hz /joy
rostopic hz /joy
average rate: 9.589
min: 0.102s max: 0.110s std dev: 0.00286s window: 6
average rate: 9.558
min: 0.101s max: 0.115s std dev: 0.00433s window: 10
average rate: 6.923
min: 0.101s max: 0.833s std dev: 0.16693s window: 19
频率限制到10Hz
方法2.其它参数尝试
修改autorepeat_rate
<launch>
<node pkg="joy_test" name="joy_node" type="joy_node">
<param name="autorepeat_rate" value="0.1" type="doble"/>
</node>
</launch>
nh_param.param<double>("autorepeat_rate", autorepeat_rate_, 0);
实测结果: --NG
输出频率是10Hz, 不过由于input缓冲区问题, 停止拨动手柄摇杆, 依旧会继续输出,10s之后才停止.
方法3.自己修改源码
joy_node.cpp gitee修改代码
核心代码实现
bool check_publish_time()
{
double now_time = ros::Time::now().toSec();
if ((now_time - pub_time_) > pub_delay_)
{
pub_time_ = now_time;
return true;
}
return false;
}
main()
{
read_joy:
if (read(joy_fd, &event, sizeof(js_event)) == -1 && errno != EAGAIN)
{
break; // Joystick is probably closed. Definitely occurs.
}
if (check_publish_time() == false)
goto read_joy;
}
通过函数 check_publish_time() 检查发布时间,如果时间差小于0.1s, 继续read (清空缓冲区)
注意事项:
一定要继续read(), 清空input buffer缓冲区, 不然会出现 方法2 一样的现象, 停止拨动手柄摇杆, 继续输出.
xbox360 ps2/3模式切换方法
长按北通Logo 切换模式
总结:
- 目前只是限制ros topic 发布频率, 没有从根本上解决问题, 后面尝试添加sys节点, 从kernel限制频率.
- 运到问题,大部分还是得从源码方面解决问题, 定制需求.
我是一名ROS机器人,嵌入式开发工程师