作用:

该工具可用来对/me/head坐标系进行短期(在osvr server运行期间)校准,将头部的方向校正为正前方。它主要是为只有orientation数据的追踪器准备的;而带有完整pose信息的追踪器就不需要这个工具了,它们一般都会带有外部固定的已知位置的地标或者摄像头,而由于已知位置就能够建立一个不变的期望的坐标系。

如何使用:

在运行OSVR reset yaw之前,OSVR server应该先运行并且能正常接受到追踪数据。应用程序也在运行。

1.开启Reset Yaw应用程序。它会连接上OSVR Server并随后在提醒继续操作之前会获取追踪数据

2.应用程序会提示“将你的设备放置在零点方位并按下enter键”:这时头显应该朝向想要的成为正前方的方位,随后按下enter键

3.该应用程序会记录按下enter键这一刻的方位信息,然后再计算这个方位和一个默认方位间关于Y轴的相对旋转信息,随后给OSVR server发生一条信息以更新它的节点/me/head,该节点路径包含一个变形转换层可对头部坐标系进行转换操作,因此可使新的方位变为/me/head的有效正前方。

4.当所有的计算以及服务通信都完成时,应用程序会提醒再次按下enter键退出reset yaw程序,改变将会立即生效。

若是不满意,可再次运行该程序;新创建的校正数据将会刷掉旧的校正数据,所有正在运行的OSVR应用程序将会立即刷新以显示新校正数据的转换结果。

缺陷:

1.该校正数据只在当前服务进程操作时会被保存,其他任何地方都无法保存,因此当关闭OSVR server时,它们就会丢失。(大多数IMU设备在这一点上设计成在每个阶段都需要这这样的校正操作,这样才是合理的操作模式)

2.该操作只对/me/head生效,而对那些即使在同一坐标系中的追踪器或摄像头都不会起到效果。(这也是为什么说它最适合在仅仅有方位追踪器的系统中使用的原因)

3.正如名字所提示的,它只能校准偏航角yaw/heading:地平面假设正确。如果追踪被混合进它的转换中而不仅仅只是去校正它的yaw角,使用该工具也会出现错误。

代码分析:

{namespace po = boost::program_options;// clang-format offpo::options_description desc("Options");desc.add_options()("help", "produce help message")("path", po::value<std::string>()->default_value("/me/head"), "path to reset-yaw on")("no-wait", "headless mode - immediately resets yaw without waiting");// clang-format onpo::variables_map vm;po::store(po::command_line_parser(argc, argv).options(desc).run(), vm);po::notify(vm);const bool noWait = vm.count("no-wait");{/// Deal with command line errors or requests for helpbool usage = false;if (vm.count("help")) {cout << "Usage: osvr_reset_yaw [options]" << endl;cout << desc << "\n";return 1;}}osvr::clientkit::ClientContext ctx("com.osvr.bundled.resetyaw");std::string const path = vm["path"].as<std::string>();// Get the interface associated with the destination route we// are looking for.osvr::clientkit::Interface iface = ctx.getInterface(path);{ClientMainloopThread client(ctx);cout << "Running client mainloop briefly to start up..." << endl;client.loopForDuration(boost::chrono::seconds(2));cout << "Removing any previous yaw-reset transforms..." << endl;// Get the alias element corresponding to the desired path, if possible.auto elt = getAliasElement(ctx, path);if (!elt) {// No luck, sorry.cerr << "Couldn't get the alias at " << path << endl;return -1;}// Get a reference to the source associated with the portion// of the tree that has this destination.  Then clean out// any prior instance of our meddling by checking for an// entry that has our flag key in it.  Then replace the// original source tree with the cleaned tree.  Send this// cleaned alias back to the server.osvr::common::ParsedAlias origAlias{elt->getSource()};if (!origAlias.isValid()) {cerr << "Couldn't parse the alias!" << endl;return -1;}cout << "Original transform: "<< origAlias.getAliasValue().toStyledString() << "\n" << endl;osvr::common::GeneralizedTransform xforms{origAlias.getAliasValue()};osvr::common::remove_if(xforms, [](Json::Value const ¤t) {return current.isMember(FLAG_KEY) && current[FLAG_KEY].isBool() &&current[FLAG_KEY].asBool();});cout << "Cleaned transform: "<< xforms.get(origAlias.getLeaf()).toStyledString() << "\n"<< endl;elt->setSource(osvr::common::jsonToCompactString(xforms.get(origAlias.getLeaf())));ctx.get()->sendRoute(createJSONAlias(path, *elt));cout << "Sent cleaned transform, starting again and waiting a few ""seconds for startup..."<< endl;client.start();boost::this_thread::sleep(SETTLE_TIME);if (!noWait) {cout << "\n\nPlease place your device for " << path<< " in its 'zero' orientation and press enter." << endl;std::cin.ignore();}OSVR_OrientationState state;OSVR_TimeValue timestamp;OSVR_ReturnCode ret;{/// briefly interrupt the client mainloop so we can get stuff done/// with the client state.ClientMainloopThread::lock_type lock(client.getMutex());ret = osvrGetOrientationState(iface.get(), ×tamp, &state);if (ret != OSVR_RETURN_SUCCESS) {cerr << "Sorry, no orientation state available for this path - ""are you sure you have a device plugged in and your ""path correct?"<< endl;if (!noWait) {std::cin.ignore();}return -1;}auto q = osvr::util::eigen_interop::map(state);auto yaw = osvr::util::extractYaw(q);cout << "Correction: " << -yaw << " radians about Y" << endl;Json::Value newLayer(Json::objectValue);newLayer["postrotate"]["radians"] = -yaw;newLayer["postrotate"]["axis"] = "y";newLayer[FLAG_KEY] = true;xforms.wrap(newLayer);cout << "New source: "<< xforms.get(origAlias.getLeaf()).toStyledString() << endl;elt->setSource(osvr::common::jsonToCompactString(xforms.get(origAlias.getLeaf())));ctx.get()->sendRoute(createJSONAlias(path, *elt));boost::this_thread::sleep(SETTLE_TIME / 2);}boost::this_thread::sleep(SETTLE_TIME);if (!noWait) {cout << "Press enter to exit.";std::cin.ignore();}}return 0;
}

整个过程为:通过path: /me/head 获取接口,通过接口再获取四元数,通过四元数再获取欧拉角的yaw角。创建一个json对象用来存储欧拉角yaw值,再进行几何变形转换。再将该Json 写入path对应的文件。
输出:

OSVR Reset Yaw相关推荐

  1. 飞控简析-从入门到跑路 第二章PX4的位置控制(1)

    一.前言 首先,我们要清楚的我们的需求,PX4的位置控制需要完成什么样的工作.位置控制需要完成的是,从期望位置得到期望姿态的一个过程,然后把期望姿态传递给姿态控制模块,所以位置控制的输入是期望位置,输 ...

  2. PX4模块设计之三十五:MulticopterAttitudeControl模块

    PX4模块设计之三十五:MulticopterAttitudeControl模块 1. MulticopterAttitudeControl模块简介 2. 模块入口函数 2.1 主入口mc_att_c ...

  3. Kerloud 飞车在线控制C++教程

    Kerloud 飞车在线控制C++教程 产品简介 基于ROS C++ API的Offboard控制 (1)环境设置 (2)代码讲解 订阅.发布.服务的声明 服务指令构建 陆地车.多旋翼模式下的航路点坐 ...

  4. pixhawk mc_pos_control.cpp源码解读

    好久没跟新blog了,这段时期边调试边看程序,所以有点慢.要开始着手调试了.. 这篇blog是顺着上一篇pixhawk 整体架构的认识写的,接下来看程序的话,打算把各个功能模块理解一遍,先从mc_po ...

  5. PixHawk学习笔记 之 源码浅析——mc_pos_control.cpp——task_main

    注意:基于"Firmware-1.6.0rc1" 献上固件源码分享链接:https://pan.baidu.com/s/1kUPocmF 密码:j55a 自己边学边写的,一定有错, ...

  6. PX4多旋翼姿态控制程序分析mc_att_control

    PX4多旋翼姿态控制程序分析mc_att_control 1. 程序流程图 原图大小太大,无法上传(在我主页下载里面找) 2.PX4主程序梳理:建议对照上图 PX4程序的基本流程如下: int Mul ...

  7. git clean和git reset结合用法

    git clean命令用来从你的工作目录中删除所有没有tracked过的文件 git clean经常和git reset --hard一起结合使用. 记住reset只影响被track过的文件, 所以需 ...

  8. VS Code go 插件安装失败 r.declReader.Reset undefined

    在安装完 VS Code 后开始安装 go 的插件发现有如下错误 wohu@wohu:~/GoCode/src$ go install github.com/nsf/gocode # github.c ...

  9. form表单的reset

    form表单的reset 重置表单(把表单的所有输入元素重置为它们的默认值.): 1.使用reset按钮,条件reset按钮必须在form表单内部. 2. <input id="But ...

最新文章

  1. C# 运算符的优先级
  2. 2021年必读的10 个计算机视觉论文总结
  3. R语言亚组分析 (Subgroup Analysis)及森林图绘制实战
  4. rapidminer员工离职分析_HR如何做好离职分析?
  5. RxJava Rxandroid 结合 Retrofit 使用
  6. 相同的字符串哈希值一样吗_关于哈希,来看这里!
  7. mybatis-plus自动生成文件
  8. angular的html引入js,在AngularJS中的文件夹中加载JavaScript和CSS文件
  9. 上传书籍进度信息到服务器...,使用HttpWebRequest实现大文件上传资料.pdf
  10. Runtime消息动态解析与转发流程
  11. 蚂蚁金服 Service Mesh 大规模落地系列 - 运维篇
  12. Visual studio2012密钥 vs2012密钥 本人亲测 真实有效
  13. idea导入项目后,没有项目结构
  14. 用计算机配置打印机IP,如何修改打印机IP地址?
  15. CSAPP第九章家庭作业参考答案
  16. reg文件编写方法整理
  17. cad图纸问号怎么转换文字_打开cad2016图纸字体和符号显示问号怎么办?
  18. 当前网络安全风险及举例
  19. java 大小写_java中如何进行大小写字母转换?
  20. 闲鱼双11端侧实践总结

热门文章

  1. Windows 如何锁定文件
  2. Redis存储缓存工具类简单封装
  3. 组员组长mysql_第10组 Beta冲刺 (1/5)(组长)
  4. C语言计算水仙花数的两种方法
  5. 为什么uzi排到古手羽就秒_为什么uzi排到古手羽就秒退看一下直播间里的弹幕就清楚了!...
  6. raft java实现_raft-java
  7. 删除另一个计算机用户权限,如何解除电脑用户权限
  8. 阿里巴巴内网宣布将取消“361”制度!却遭员工质疑:换汤不换药?
  9. 迎接“万物互联”时代:当5G遇上智能终端、物联网
  10. 【电商经验】之商品下单减库存方案