资讯详情

视觉伺服控制工具Visual Servoing Platform---VISP(7)----vpServo这个看懂了就会用VISP了,很简单

这一类是整个VISP核心部分,因为所有现有算法都可以替换其他部分,但是这个vpServo和另一个姿态估计类是真的好用,是无法替换的。

在vpServo有几种方法:两个大方向是eye in hand和eye to hand。基于这两类,开发人员开发了其他方法

  1. NONE
  2. EYEINHAND_CAMERA
  3. EYEINHAND_L_cVe_eJe
  4. EYETOHAND_L_cVe_eJe
  5. EYETOHAND_L_cVf_fVe_eJe
  6. EYETOHAND_L_cVf_fJe

每种方法的具体意义可参考此连接,简洁明了

一. vpServo的调用方法

vpServo task; 

然后具体设置这个类中的每个方法

task.setServo(vpServo::EYEINHAND_CAMERA);//设置为eye in hand视觉伺服模式 task.setInteractionMatrixType(vpServo::CURRENT);///交互矩阵的计算方法是根据当前图像计算 task.setLambda(0.5);///增益参数lambda设为0.5 

关于 task.setServo()这种方法,我们有很多调用模式,比如基于图像的视觉伺服也分为eye in hand和eye to hand.也就是说,相机固定在机械臂上,相机固定在空间中。

task.setServo(vpServo::EYEINHAND_CAMERA);//设置为eye in hand视觉伺服模式 task.setServo(vpServo::EYEINHAND_L_cVe_eJe); ///每种方法的具体功能可参考上述链接 task.setServo(vpServo::EYETOHAND_L_cVe_eJe); task.setServo(vpServo::EYETOHAND_L_cVf_fVe_eJe); task.setServo(vpServo::EYETOHAND_L_cVf_fJe); 

关于vpServo::vpServoIteractionMatrixType()这种方法也有很多调用方法

task.setInteractionMatrixType(vpServo::CURRENT);///交互矩阵的计算方法是根据当前图像计算 task.setInteractionMatrixType(vpServo::DESIRED); task.setInteractionMatrixType(vpServo::MEAN); task.setInteractionMatrixType(vpServo::USER_DEFINED);

一些相关的方法

void vpServo::addFeature(vpBasicFeature & s_cur,
		                 vpBasicFeature & s_star,
		const unsigned int select = vpBasicFeature::FEATURE_ALL 
	) 	

在任务中添加一组新特征 s \bf s s和 s ∗ {\bf s}^* s∗。 参数 s_cur:表示为 s \bf s s的当前视觉特征。 s_star:表示为 s ∗ {\bf s}^* s∗的所需视觉特征。 select:特征选择器。默认情况下,使用s和s_star中的所有特征,但可以指定在多个特征的情况下使用哪一个。 以下示例代码解释了如何使用此方法添加视觉要素点 ( x , y ) (x,y) (x,y):

vpFeaturePoint s, s_star;
...
vpServo task;
task.addFeature(s, s_star);

例如,要仅使用 x x x视觉特征,前面的代码将变为:

vpFeaturePoint s, s_star;
...
vpServo task;
task.addFeature(s, s_star, vpFeaturePoint::selectX());

void vpServo::addFeature(vpBasicFeature & s_cur,
		const unsigned int  	select = vpBasicFeature::FEATURE_ALL 
	) 	

在任务中添加新功能 s \bf s s。表示为 s ∗ {\bf s}^* s∗的所需视觉功能等于零。 参数 s_cur:表示为 s \bf s s的当前视觉特征。 select:特征选择器。默认情况下,将使用s中的所有特征,但可以指定在多个特征的情况下使用哪个特征。 以下示例代码解释了如何使用此方法添加 θ u = ( θ u x , θ u y , θ u z ) \theta {\bf u} =(\theta u_x, \theta u_y, \theta u_z) θu=(θux​,θuy​,θuz​) 特征:

vpFeatureThetaU s(vpFeatureThetaU::cRcd);
...
vpServo task;
task.addFeature(s);

例如,要仅使用 θ u x \theta u_x θux​特征,前面的代码变为:

vpFeatureThetaU s(vpFeatureThetaU::cRcd);
...
vpServo task;
task.addFeature(s, vpFeatureThetaU::selectTUx);

计算控制率是该类的一个主要方法

vpColVector vpServo::computeControlLaw() 	

使用setServo()计算指定的控制律。 控制法的一般形式如下: 在这里插入图片描述 其中: q ˙ {\bf\dot q} q˙​是应用于机器人的结果速度命令。控制律的符号取决于eye in hand or eye to hand的配置。 J \bf J J是任务的雅可比矩阵。它是交互矩阵和机器人雅可比矩阵的函数。 e = ( s − s ∗ ) \bf e=(s-s^*) e=(s−s∗)是要调节的误差。 为确保连续排序,可使用computeControlLaw(双精度)功能。它将确保计算的速度是连续的。

vpColVector vpServo::computeControlLaw(double t) 	

使用setServo()计算指定的控制律。 对于computeControlLaw()中给出的控制律的一般形式,我们在这里添加了一个附加项。这个附加项允许通过避免命令中的突然变化来计算连续速度。 此处考虑的控制法形式如下: 其中: q ˙ {\bf\dot q} q˙​是应用于机器人的连续速度命令。控制律的符号取决于手对眼或手对眼的配置。 J \bf J J是任务的雅可比矩阵。它是交互矩阵和机器人雅可比矩阵的函数。 e = ( s − s ∗ ) \bf e=(s-s^*) e=(s−s∗)是要调节的误差。 t t t是作为此方法参数给定的时间。 μ \mu μ是默认设置为4的增益,可以使用setMu()进行修改。 J ^ e ( 0 ) + e ( 0 ) {\bf \widehat J}_{e(0)}^+ {\bf e}(0) J e(0)+​e(0) 是 t = 0 t=0 t=0时 J ^ e + e {\bf \widehat J}_e^+ {\bf e} J e+​e 的值。此值在第一次调用此方法时,或当t参数设置为0时,在内部存储。 参数 t:时间是秒。设置为零时, J ^ e ( 0 ) + e ( 0 ) { {\bf \widehat J}_{e(0)}}^+ { {\bf e}(0)} J e(0)​+e(0)在内部刷新。

vpColVector vpServo::computeControlLaw(double t,const vpColVector & e_dot_init) 	

参数 t:时间是秒。设置为零时, J ^ e ( 0 ) + e ( 0 ) { {\bf \widehat J}_{e(0)}}^+ { {\bf e}(0)} J e(0)​+e(0)在内部刷新。 e_dot_init: e ˙ ( 0 ) {\bf \dot e}(0) e˙(0)的初始值。.

二. 一个基于位置的视觉伺服的例子

为了避免潜在的内存泄漏,可以显式调用kill()函数来销毁任务。否则,析构函数~vpServo()将启动异常vpServoException::notkilled。 下面的示例显示了如何从3D视觉特征 s = ( c ∗ t c , θ u ) s=(_{}^{c^*}\textrm{t}_{c}, \theta u) s=(c∗​tc​,θu)构建。在这种情况下,我们有 s ∗ = 0 s^*=0 s∗=0。 让我们用 θ u \theta u θu表示旋转分量 c ∗ R c _{}^{c^*}\textrm{R}_{c} c∗​Rc​的角度/轴参数化。此外, c ∗ t c _{}^{c^*}\textrm{t}_{c} c∗​tc​和 c ∗ R c _{}^{c^*}\textrm{R}_{c} c∗​Rc​分别表示期望相机坐标系和通过姿势估计(参考这个连接)获得的当前坐标系之间的平移和旋转(请参见vpPose类)。

#include <visp/vpColVector.h>
#include <visp/vpFeatureThetaU.h>
#include <visp/vpFeatureTranslation.h>
#include <visp/vpHomogeneousMatrix.h>
#include <visp/vpMatrix.h>
#include <visp/vpServo.h>
int main()
{ 
        
  // 创建齐次矩阵,该矩阵表示相机从期望相机坐标系和当前相机坐标系移动期望的位移 
  vpHomogeneousMatrix cdMc;
  // ... 这里的cdMc是姿势估计的结果
  // 创建当前视觉特征s=(c*\u t\u c,ThetaU)
  vpFeatureTranslation s_t(vpFeatureTranslation::cdMc);
  vpFeatureThetaU s_tu(vpFeatureThetaU::cdRc);
  // Set the initial values of the current visual feature s = (c*_t_c, ThetaU)
  s_t.buildFrom(cdMc);
  s_tu.buildFrom(cdMc);
  // 设置当前视觉特征的初始值s=(c*\u t\u c,ThetaU)
  vpFeatureTranslation s_star_t(vpFeatureTranslation::cdMc); // 默认初始化为零 
  vpFeatureThetaU s_star_tu(vpFeatureThetaU::cdRc);// 默认初始化为零 
  vpColVector v; // Camera velocity相机速度
  double error;  // Task error 人物误差
  //创建一个视觉伺服任务,
  vpServo task;//实例化视觉任务为task
  // Visual servo task initialization初始化视觉伺服任务
  // -摄像机安装在机器人末端执行器上,并在摄像机坐标系中计算速度
  task.setServo(vpServo::EYEINHAND_CAMERA); 
  // - 交互矩阵由当前视觉特征s计算得出,当然你也可以设置为其他的方法,下面有讲
  task.setInteractionMatrixType(vpServo::CURRENT); 
  // - 设置增益为1
  task.setLambda(1);
  // - 添加当前和期望的平移特征
  task.addFeature(s_t, s_star_t); 
  // - 添加当前和期望的旋转特征
  task.addFeature(s_tu, s_star_tu); 
  // 视觉伺服回路。这里的目标是更新视觉特征s=(c*\u t\u c,ThetaU),计算控制律并将其应用于机器人
  do { 
        
    // ... 这里的cdMc是姿势估计的结果
    // 更新当前视觉特征s
    s_t.buildFrom(cdMc);  // 更新平移视觉特征
    s_tu.buildFrom(cdMc); // 更新旋转视觉特征
    v = task.computeControlLaw(); // Compute camera velocity skew计算相机速度螺杆
    error =  ( task.getError() ).sumSquare(); // error = s^2 - s_star^2
  } while (error > 0.0001); // 当当前和期望的视觉特征关闭时停止任务
  // A call to kill() is requested here to destroy properly the current
  // and desired feature lists.
  task.kill();
}

三. 一个基于图像的视觉伺服的例子

上面的例子不是一个完整的例子,这个例子是比较真实的例子。在下一章,我们还会更新一个控制实际机械比的例子。总是,看懂代码才行。

#include <visp3/gui/vpDisplayGDI.h>
#include <visp3/gui/vpDisplayOpenCV.h>
#include <visp3/gui/vpDisplayX.h>
#include <visp3/io/vpImageIo.h>
#include <visp3/robot/vpImageSimulator.h>
#include <visp3/robot/vpSimulatorCamera.h>
#include <visp3/visual_features/vpFeatureBuilder.h>
#include <visp3/vs/vpServo.h>
#include <visp3/vs/vpServoDisplay.h>
void display_trajectory(const vpImage<unsigned char> &I, const std::vector<vpDot2> &dot);
class vpVirtualGrabber//用于计算在不同位置处目标物体在相机坐标系下的成像,
//具体过程可以参见博客:[ViSP学习笔记(七):平面图像投影](https://blog.csdn.net/qq_36104364/article/details/113881985)
{ 
        
public:
  vpVirtualGrabber(const std::string &filename, const vpCameraParameters &cam) : sim_(), target_(), cam_()
  { 
        
    // 目标是一个20厘米乘20厘米的正方形 
    // 初始化目标角点的三维坐标
    for (int i = 0; i < 4; i++)
      X_[i].resize(3);
    // Top left Top right Bottom right Bottom left
    X_[0][0] = -0.1;
    X_[1][0] = 0.1;
    X_[2][0] = 0.1;
    X_[3][0] = -0.1;
    X_[0][1] = -0.1;
    X_[1][1] = -0.1;
    X_[2][1] = 0.1;
    X_[3][1] = 0.1;
    X_[0][2] = 0;
    X_[1][2] = 0
        标签: 16zs矩形连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台