开发环境:Ubuntu 18.04 LTS + ROS Melodic + ViSP 3.3.1
文章内容主要参考ViSP官方教学文档:https://visp-doc.inria.fr/doxygen/visp-daily/tutorial_mainpage.html

  本文主要介绍了如何使用ViSP实现轮式移动机器人的视觉伺服仿真,控制对象是一个轮式机器人拥有两个自由度:竖直方向y上的旋转自由度和水平方向x上的移动自由度,相机固定在机器人上,视觉伺服选择的特征信息是x方向上的距离xxx和z方向上的当前深度和期望深度比例的对数log(Z/Zd)log(Z/Z_d)log(Z/Zd​),采用的视觉伺服控制律计算方法为

  本文主要参考了robot/pioneer中的tutorial-simu-pioneer.cpp例程。首先要获取这个例程文件并编译它

svn export https://github.com/lagadic/visp.git/trunk/tutorial/robot/pioneer
cd pioneer/
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DVISP_DIR=$VISP_WS/visp-build
make

  执行例程,查看效果

./tutorial-simu-pioneer

  分别显示了速度(vxv_xvx​和wzw_zwz​)、特征误差和深度距离随时间的变化过程

  下面介绍一下代码实现过程

#include <iostream>
#include <visp3/core/vpHomogeneousMatrix.h>
#include <visp3/core/vpVelocityTwistMatrix.h>
#include <visp3/gui/vpPlot.h>
#include <visp3/robot/vpSimulatorPioneer.h>
#include <visp3/visual_features/vpFeatureBuilder.h>
#include <visp3/visual_features/vpFeatureDepth.h>
#include <visp3/visual_features/vpFeaturePoint.h>
#include <visp3/vs/vpServo.h>
int main()
{try {vpHomogeneousMatrix cdMo; //新建在期望位置出目标物体和相机之间的坐标变换单应性矩阵cdMo[1][3] = 1.2;//y方向位置cdMo[2][3] = 0.5;//z方向位置vpHomogeneousMatrix cMo; //新建在初始位置出目标物体和相机之间的坐标变换单应性矩阵cMo[0][3] = 0.3;//x方向位置cMo[1][3] = cdMo[1][3];//y方向位置cMo[2][3] = 1.;//z方向位置vpRotationMatrix cRo(0, atan2(cMo[0][3], cMo[1][3]), 0);//根据位置关系计算旋转矩阵cMo.insert(cRo);//将旋转矩阵添加到单应性矩阵中vpSimulatorPioneer robot;//新建仿真机器人robot.setSamplingTime(0.04);//设置仿真采样时间vpHomogeneousMatrix wMc, wMo;//新建相机和目标物体与世界坐标之间的单应性矩阵robot.getPosition(wMc);//获取相机(机器人)的初始位置坐标wMo = wMc * cMo;//计算目标物体初始位置坐标vpPoint point(0, 0, 0);//设置目标特征点在物体坐标系中的坐标point.track(cMo);//计算目标特征点在相机坐标系中的坐标vpServo task;//实例化视觉伺服任务task.setServo(vpServo::EYEINHAND_L_cVe_eJe);//设置视觉伺服计算方法task.setInteractionMatrixType(vpServo::DESIRED, vpServo::PSEUDO_INVERSE);//设置交互矩阵类型task.setLambda(0.2);//设置增益参数vpVelocityTwistMatrix cVe;//新建机器人和相机之间的速度变换矩阵cVe = robot.get_cVe();//从仿真机器人实例中获取cVe矩阵task.set_cVe(cVe);//添加到视觉伺服任务中vpMatrix eJe;//新建机器人雅可比矩阵robot.get_eJe(eJe);//从仿真机器人实例中获取eJe矩阵task.set_eJe(eJe);//添加到视觉伺服任务中vpFeaturePoint s_x, s_xd;//新建特征点的当前x坐标和期望x坐标vpFeatureBuilder::create(s_x, point);//根据目标特征点的坐标更新当前x坐标s_xd.buildFrom(0, 0, cdMo[2][3]);//根据期望位置更新期望x坐标task.addFeature(s_x, s_xd, vpFeaturePoint::selectX());//把x坐标作为特征之一添加到视觉伺服任务中vpFeatureDepth s_Z, s_Zd;//新建特征点的Z方向特征(比值的对数)double Z = point.get_Z();//获取特征点当前z方向坐标double Zd = cdMo[2][3];//获取特征点期望z方向坐标s_Z.buildFrom(s_x.get_x(), s_x.get_y(), Z, log(Z / Zd));//计算特征点当前z方向特征s_Zd.buildFrom(0, 0, Zd, 0);//计算特征点期望z方向特征task.addFeature(s_Z, s_Zd);//将Z方向特征添加到视觉伺服任务中
#ifdef VISP_HAVE_DISPLAY// Create a window (800 by 500) at position (400, 10) with 3 graphicsvpPlot graph(3, 800, 500, 400, 10, "Curves...");//创建图像用于显示曲线// Init the curve plottergraph.initGraph(0, 2);graph.initGraph(1, 2);graph.initGraph(2, 1);graph.setTitle(0, "Velocities");graph.setTitle(1, "Error s-s*");graph.setTitle(2, "Depth");graph.setLegend(0, 0, "vx");graph.setLegend(0, 1, "wz");graph.setLegend(1, 0, "x");graph.setLegend(1, 1, "log(Z/Z*)");graph.setLegend(2, 0, "Z");
#endifint iter = 0;for (;;) {robot.getPosition(wMc);//更新相机(机器人)当前位置cMo = wMc.inverse() * wMo;//更新目标与相机之间坐标关系point.track(cMo);//更新目标特征点在相机坐标系下的坐标vpFeatureBuilder::create(s_x, point);//更新x方向特征Z = point.get_Z();s_Z.buildFrom(s_x.get_x(), s_x.get_y(), Z, log(Z / Zd));//更新z方向特征robot.get_cVe(cVe);task.set_cVe(cVe);robot.get_eJe(eJe);task.set_eJe(eJe);vpColVector v = task.computeControlLaw();//计算控制律robot.setVelocity(vpRobot::ARTICULAR_FRAME, v);//执行控制律
#ifdef VISP_HAVE_DISPLAYgraph.plot(0, iter, v);               // plot velocities applied to the robotgraph.plot(1, iter, task.getError()); // plot error vectorgraph.plot(2, 0, iter, Z);            // plot the depth
#endifiter++;if (task.getError().sumSquare() < 0.0001) {std::cout << "Reached a small error. We stop the loop... " << std::endl;break;}}
#ifdef VISP_HAVE_DISPLAYgraph.saveData(0, "./v2.dat");graph.saveData(1, "./error2.dat");const char *legend = "Click to quit...";vpDisplay::displayText(graph.I, (int)graph.I.getHeight() - 60, (int)graph.I.getWidth() - 150, legend, vpColor::red);vpDisplay::flush(graph.I);vpDisplay::getClick(graph.I);
#endif// Kill the servo tasktask.print();} catch (const vpException &e) {std::cout << "Catch an exception: " << e << std::endl;}
}

如果大家对于深度学习与计算机视觉领域感兴趣,希望获得更多的知识分享与最新的论文解读,欢迎关注我的个人公众号“深视”。

ViSP学习笔记(二十六):基于轮式移动机器人的视觉伺服仿真相关推荐

  1. JVM 学习笔记二十六、JVM监控及诊断工具-GUI篇

    二十六.JVM监控及诊断工具-GUI篇 1.工具概述 使用上一张命令行工具或组合能帮您获取目标Java应用性能相关的基础信息,但他们存在下列局限: (1)无法获取方法级别的分析数据,如方法间的调用关系 ...

  2. Jenkins 持续集成 概念(学习笔记二十六)

    持续集成:提交.测试.构建.测试.部署 前不久接触了持续集成(Continuous Integration,CI). 一.持续集成是什么 首先说说"集成"的概念.在实际的软件开发中 ...

  3. 立创eda学习笔记二十六:手把手教你使用立创eda的官方教程

    可以通过以下办法找到教程: 1,在软件界面点帮助-使用教程 2,在网站首页-帮助-教程进入 如何使用教程: 这里是一级目录,其实对新手最有用的是前面3个部分,后面的仿真先不看. 常见问题里面不光是讲的 ...

  4. ViSP学习笔记(十六):运动的边缘跟踪

    开发环境:Ubuntu 18.04 LTS + ROS Melodic + ViSP 3.3.1 文章内容主要参考ViSP官方教学文档:https://visp-doc.inria.fr/doxyge ...

  5. [傅里叶变换及其应用学习笔记] 二十六. 高维傅里叶变换的推导

    高维意味着函数中有多个变量,典型的高维傅里叶应用为图像处理. 一个二维图像的亮度(灰度)可以用$f(x_1,x_2)$来表示,以lena为例,图像平面作为$x_1,x_2$平面,灰度作为$z$轴,形成 ...

  6. Java学习笔记二十六:Java多态中的引用类型转换

    Java多态中的引用类型转换 引用类型转换: 1.向上类型转换(隐式/自动类型转换),是小类型到大类型的转换: 2.向下类型转换(强制类型转换),是大类型到小类型的转换: 3.instanceof运算 ...

  7. OpenCV学习笔记(十六)——CamShift研究 OpenCV学习笔记(十七)——运动分析和物体跟踪Video OpenCV学习笔记(十八)——图像的各种变换(cvtColor*+)imgproc

    OpenCV学习笔记(十六)--CamShift研究 CamShitf算法,即Continuously Apative Mean-Shift算法,基本思想就是对视频图像的多帧进行MeanShift运算 ...

  8. python数据挖掘学习笔记】十六.逻辑回归LogisticRegression分析鸢尾花数据

    但是很多时候数据是非线性的,所以这篇文章主要讲述逻辑回归及Sklearn机器学习包中的LogisticRegression算法 #2018-03-28 16:57:56 March Wednesday ...

  9. python分析鸢尾花数据_python数据挖掘学习笔记】十六.逻辑回归LogisticRegression分析鸢尾花数据...

    但是很多时候数据是非线性的,所以这篇文章主要讲述逻辑回归及Sklearn机器学习包中的LogisticRegression算法 #2018-03-28 16:57:56 March Wednesday ...

最新文章

  1. 第1章 Java语言概述
  2. 在电影里看到的一个小故事
  3. Spring+SpringMVC +MyBatis整合配置文件案例66666
  4. android的线程管理器,[Android开源]:一款安全、轻巧、简单的线程池管理器EasyThread...
  5. 怎样为ubuntu eclipse 添加 GBK字符集
  6. respondsToSelector的相关使用
  7. 集成直流稳压电源设计报告_线性直流稳压电源结构,线性直流电源技术指标
  8. 免费 Python 学习资源大全,你想要都在这里啦(持续更新,欢迎收藏关注点赞加评论哦)
  9. [原创]BizTalk 开发系列
  10. pyhton2 and python3 生成随机数字、字母、符号字典(用于撞库测试/验证码等)
  11. 史上最全IT技能学习大全公众号
  12. 学李炎恢老师的PHP第一季 笔记 多用户留言系统-TestGuest0.2
  13. ubuntu18.04截图快捷键
  14. cpci检索太慢_了解CPCI检索,对自己的好处
  15. 从零開始学习制作H5应用——V5.0:懊悔机制,整理文件夹,压缩,模板化
  16. python人脸识别门禁系统生产厂家_人脸识别门禁硬件生产厂家
  17. BP神经网络隐藏层的作用,bp神经网络输出层函数
  18. allegro导出3D文件
  19. PTA 天梯赛习题集 L2-001 城市间紧急救援
  20. 浙江省计算机二级高级技术,浙江省计算机二级办公软件高级的应用技术上机考试的技巧解析.doc...

热门文章

  1. 辰光php客服系统源码_仿伊对梵高相亲交友系统产品特性以及构成基础,你了解吗?...
  2. 什么是display:inline?
  3. Python预测——多元线性回归
  4. 50个高质量Java开发人员博客
  5. Java毕设项目疫情期间中小学生作业线上管理系统设计与实现(java+VUE+Mybatis+Maven+Mysql)
  6. 新突破 PsiQuantum和奔驰利用容错光量子计算模拟化学电池
  7. React+SpringBoot通过WebSocket实时统计在线人数
  8. 启动Tomcat闪退的问题
  9. 认识联合体(共用体)以及联合体大小的计算方法
  10. 在gitee码云上用 git 新建分支