我是靠谱客的博主 重要大米,最近开发中收集的这篇文章主要介绍Platinum Maestro运动控制器 —— PVT模式笔记0. 文章说明1. PVT说明2.PVT 插值模式3. 数据加载4. PVT 运动5.动态模式6.PVT在C++中的实现7.PVT 使用教程,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • 0. 文章说明
  • 1. PVT说明
  • 2.PVT 插值模式
    • 2.1 三次多项式插值(eCUBIC_POLYNOM)
    • 2.2 五次多项式插值(eQUINTIC_ON_CUBIC)
    • 2.3 七次样条多项式(eSEPTIC_ON_CUBIC)
    • 2.4 正弦插值
      • 2.4.1 三角正弦插值(eCYCLOID_VELOCITY_MODIFIED1)
      • 2.4.2 梯形正弦插值(eCYCLOID_VELOCITY_MODIFIED2)
      • 2.4.3 正弦速度插值(eCYCLOID_POSITION)
  • 3. 数据加载
  • 4. PVT 运动
  • 5.动态模式
    • 5.1 初始化列表
    • 5.2 加载数据
    • 5.3 循环模式(Cyclic Mode)
  • 6.PVT在C++中的实现
    • 6.1 PVT表初始化函数
    • 6.2 PVT数据点加载函数
    • 6.3 PVT移动函数
  • 7.PVT 使用教程
    • 7.1 使用方法
    • 7.2 例程

0. 文章说明

请忽略前面的扯淡内容,直接跳至3

1. PVT说明

详情参见API手册P783

       通常,PV/PVT运动由一组点定义,如果在当前位置之前提供了多个点,profiler可以构建一个三次多项式来计算下一个要下载到驱动器的位置。该路径是实时计算的,因此所有多项式系数的计算都在实时模块中进行。PV/PVT运动不需要执行完整的数据,只需要最少的点。
       与样条相似,输入表存储在共享内存中,但与样条不同的是,只存储坐标,而多项式系数在实时模块中计算。表可以通过文件加载,也可以通过用户提供的N x M数组加载。可以选择将一行或几行附加到表中,但要在合理的约束条件下;例如,不能将数据附加到当前段,分析器正在操作。PV/PVT函数块仅适用于NC循环/插补模式。
       用户提供的点多于3个,即可应用PVT插补。

2.PVT 插值模式

       对于PVT表的定义,遵循以下格式:
在这里插入图片描述
Ti为时间,有两种模式:两点之间的相对时间、各点分别对应的绝对时间。
轴的数量不受三个坐标轴的限制,最多可达16个坐标轴。

2.1 三次多项式插值(eCUBIC_POLYNOM)

三次多项式保证了位置和速度的连续性。它的缺点是在每一个连接点上都有加速度和加加速度(即簇动jerk)造成的不连续。
在这里插入图片描述

2.2 五次多项式插值(eQUINTIC_ON_CUBIC)

五次多项式保证了位置、速度和加速度的连续性。它的缺点是在每一个连接点上都有加加速度造成的不连续。
在这里插入图片描述

2.3 七次样条多项式(eSEPTIC_ON_CUBIC)

七次多项式保证了连续的位置,速度,加速度和加加速度。它的缺点是振幅变化比我们看到的低次多项式更高。这是在大多数情况下可以推荐的最通用的插值模式。
在这里插入图片描述

2.4 正弦插值

2.4.1 三角正弦插值(eCYCLOID_VELOCITY_MODIFIED1)

三角形正弦加速度-修正三角形加速度与AC(t)和DC(t)由正弦增加到某个最大值,然后下降到零。它保证连续的位置,速度,加速度和加加速度。
在这里插入图片描述
在这里插入图片描述

2.4.2 梯形正弦插值(eCYCLOID_VELOCITY_MODIFIED2)

梯形正弦加速度或修正梯形加速度通常由两部分组成:

  • 加速度随正弦曲线从0增加到ACmax,运动与ACmax(抛物线位置,线速度剖面)和加速度下降的正弦为零。
  • 由正弦波由零到-ACmax减速运动,由-ACmax减速运动(抛物线位置剖面,线速度剖面),由正弦波减速增加到零。

它保证连续的位置,速度,加速度和加加速度(如果所有的段定义与此插值模式)。
在这里插入图片描述
在这里插入图片描述

2.4.3 正弦速度插值(eCYCLOID_POSITION)

这种插补方式产生摆线位置和正弦速度插补。正弦速度是这种插值类型的一个优点,但它有两个明显的缺点。首先,它的开始和结束都伴随着最大的jerk。其次,它的应用具有局限性,当Y(i)≠0和Y(i+1)≠0时必须满足开始和结束导数服从条件△Y(i)=0.5(Y(i)+Y(i+1))△X(i)。(此处存疑) 因此,这种插补方式主要用于Y(i)≠0或者Y(i)=0的情况。

3. 数据加载

将每一行输入数据作为表存储在共享内存中,表示时间、位置、速度和向量位置。例如,我们在使用m个轴的情况下,表中第n行按如下格式生成:
在这里插入图片描述
用户可以通过以下几种方式提供数据:

  • 提供一个包含数据点的表的文件
  • 提供一个包含数据点的数组,这些数据点也可以附加到给定索引中的现有路径

当用户决定向现有路径添加点时,他必须知道:

  • 表的大小是有限的,应该知道它的最大大小
  • 仅对于dynamic Append(动态添加),当点的数量超过表的上限时,这些点将被附加到表的开头。
  • 不可能追加到当前段(目前,如果当前索引是X,用户只能从X + 3追加)。

在数据加载期间,从文件中读取这些点。然而,与样条不同的是,它们无需预先计算就可以插入共享内存。

禁止将数据附加到从文件加载的表中。如果T等于循环时间,应该使用一个简单的profiler。

4. PVT 运动

运动是使用一种特殊类型的函数块来执行的。当插入这个函数块类型时,应用一个特殊的轮廓仪来计算多项式系数并沿着计算的轨迹移动。

每一个循环下一段都向前计算。函数块包括指向当前选定路径数据起点的指针,包括所有路径常数数据,即维数、点数等。此外,函数块包含当前工作索引,因此如果用户希望添加点,系统将避免在当前工作索引中添加这些点。当PVT函数块处于运动状态时,只能通过STOP命令(类似于样条行为)以任何缓冲模式插入其他函数块。

5.动态模式

Maestro还支持动态地将数据加载到Maestro,即用户可以基于现有数据启动运动,剩余数据可以稍后添加。这个概念允许用户在考虑软件约束的情况下动态地更改路径。此时,实现了两种附加子模式:自动和手动。

  • 在自动模式下,大师将记住添加数据的最后一个索引,并将在下一次添加到该索引中。
  • 在手动模式下,用户必须提供索引,并在其中添加他希望添加的点。

实时模块使用计算出的点数来检查路径是否到达终点,即如果分配了2000个点数,而用户只插入了1000个点数,则不应遍历1000个点数的限制。此外,仅在动态模式下,当索引接近路径末尾时,才可以发送潜流事件。

5.1 初始化列表

在向表添加点之前,用户应该初始化它。这可以通过两种方式实现;通过从文件中加载一个表,或调用一个专用函数,该函数将初始化“常量”路径参数,如维度、最大点数等。

此外,用户应该选择附加操作是静态执行还是动态执行。如果选择动态附加,则用户应该选择下溢阀值。

5.2 加载数据

从数组中加载数据有两种模式——静态和动态。静态模式非常类似于从文件模式加载,当表中填充了最大值时,将加载表,并且不允许添加值。动态模式默认为循环模式,当超过潜流阀值时将生成实时事件。每次插入点的数量下降到预定义阈值以下时,就会向用户空间生成一个事件。使用现有的事件机制——用户根据需要处理溢出。

在向表中添加数据时,用户可以控制两个参数;是否附加在自动模式?如果没有,则第二个参数是要追加的索引。基于这两个参数,算法安全插入数据。

如果轴/向量在运动,则使用索引delta来维持计算出的路径(索引delta = 3)。如果当前索引与要追加的起始索引之差小于delta,则禁止插入。

在循环模式下,数据被附加到给定的索引(自动或手动),当数据到达PVT段的末尾时,数据被自动附加到开头。在非循环模式下,当数据到达PVT段的末尾时,返回一个错误。

文件中的数据被识别为double型,则对于m轴一行数据需要((M2 + 1) * size of(double)) bytes,分配的总内存将是(N * (M2 + 1) * size (double))
在这里插入图片描述

5.3 循环模式(Cyclic Mode)

为了支持循环模式,对循环缓冲区进行了管理。主要的限制是附加的缓冲区的大小不能超过表的大小,因为这样结束时将运行在开始时。此外,如果附加索引在当前索引之后,用户应该保持一个最小的增量: Abs(current – start) < 3
如果追加的索引在当前索引之前,则应保持以下内容:start + block size < current

6.PVT在C++中的实现

PVT (ECAM和样条,在将来)的基类是继承自CMMCMotionAxis的类CMMCAxis,即它包含所有CMMCAxis成员和方法。类CMMCMotionAxis函数在第8章中详细介绍:位置、速度、时间(PVT)运动。类CMMCMotionAxis保留了本文档中描述的用于C函数块的字段参数属性和值。
在这里插入图片描述
应该注意的是,私有和受保护的函数及其操作应该对用户透明,而不是供用户一般应用。

PVT和ECAM的基类CMMCMotionAxis继承自CMMCAxis,即它包含所有CMMCAxis成员和方法。

该方法继承自CMMCAxis类,但在CMMCMotionAxis类中重载,因为该方法不适合CMMCAxis实现的需求。而是使用BindAxis方法,InitAxisData只会抛出一个异常。

PVT包含以下方法:

函数说明
InitPVTTable该方法是MMC_InitTableCmd()命令的包装器。
LoadPVTTable该方法从文件中加载PVT表
AppendPointsToPVTTable此方法将点附加到当前PVT表(在自动模式下)
AppendPointsToPVTTable此方法将点附加到当前PVT表(在手动模式下)
MovePVT该方法插入PVT函数块
UnloadPVTTable卸载PVT表

详细请参考《Maestro Administrative and Motion API》手册第8章

6.1 PVT表初始化函数

// 初始化列表函数介绍
//此函数根据维度和点数在共享内存中分配内存段。
//应该注意的是,当使用这个函数时,没有加载任何数据。函数返回hMemHandle,它是唯一的路径ID(类似于样条)。
	virtual MC_PATH_REF InitPVTTable(unsigned long ulMaxPoints,
						   unsigned long ulUnderflowThreshold,
						   unsigned char ucIsCyclic,
						   unsigned char ucIsPosAbsolute,
						   unsigned short usDimension,
						   MC_COORD_SYSTEM_ENUM eCoordSystem,
						   NC_MOTION_TABLE_TYPE_ENUM eTableMode = eNC_TABLE_PVT_ARRAY) throw (CMMCException);

	/*
	 * 参数 ulMaxPoints - 表能够包含的最大点数(在非循环模式下),任何+ve值都可以接受。
	 * 参数 ulUnderflowThreshold - 如果当前索引和结束索引之间的点数低于此值,则将生成一个事件。值不能大于ulMaxPoints值。
	 * 参数 ucIsCyclic - 这个列表应该是循环的吗?也就是说,当索引到达表的末尾时,它会滚动并从头开始?。布尔值为0或1
	 * 参数 ucIsDynamic - 是否允许动态追加
	 * 参数 ucIsPosAbsolute - 是否是绝对位置,1为绝对位置,0为相对位置
	 * 参数 usDimension - PVT表的维度
	 * 参数 eSplineMode	- 定义样条函数的计算方法 (FT/VT/CV_DWELL)
	 * 参数 ConstVelocity	- 所有的线段都必须有恒定的速度
	 * 参数 FixedType	- 在所有段上强制使用常数时间(ms)
	 * 参数 eCoordSystem - 支持的坐标系类型
	 * 参数 eTableMode - 这个枚举用作这些函数的输入,以便区分ECAM和PVT.目前只能应用eNC_TABLE_PVT_FILE和eNC_TABLE_PVT_ARRAY(默认采用三次样条插补)。
	 *                   //对于插补这一点,可能不如PMAC。
	 * return void
	*/

6.2 PVT数据点加载函数

//自动添加
	void AppendPVTPoints(MC_PATH_REF hMemHandle,
							    double (&dTable)[NC_PVT_ECAM_MAX_ARRAY_SIZE],
							    unsigned long ulNumberOfPoints,
								unsigned char ucIsTimeAbsolute = 0,
								NC_MOTION_TABLE_TYPE_ENUM eTableType = eNC_TABLE_PVT_ARRAY) throw (CMMCException);
								
	/*
	 * brief 此函数将点追加到现有表
	 * 参数  hMemHandle - 指向共享内存指针所在的日志项的句柄
	 * 参数  dTable[NC_PVT_ECAM_MAX_ARRAY_SIZE] - 指向数组值表的指针,数组最大值限制为170。
	 * 参数  ulNumberOfPoints - 要追加的行中点数,任何+ve值都可以接受。
	 * 					例如:对于三轴,一个轨迹点即一行,有7个参数(T,Px,Vx,Py,Vy,Pz,Vz),要添加n个轨迹点,则数组中共有7n个点,此时ulNumberOfPoints为n
	 * 参数  ucIsTimeAbsolute - 时间是绝对的吗?
	 *                	0为绝对,每一个“时间”输入都被用作绝对时间,此时当前点将结束运动并到达所需位置。
	 *                  1为相对,每一个“时间”输入都被用作从以前的点移动到当前点结束所花费的时间。
	 * 参数  NC_MOTION_TABLE_TYPE_ENUM eTableType - 这个枚举用作这些函数的输入,以便区分ECAM和PVT.目前只能应用eNC_TABLE_PVT_FILE和eNC_TABLE_PVT_ARRAY。
	 * return void
	 */

//--------------------------------------------------------------------------------------------
//手动添加
	void AppendPVTPoints(MC_PATH_REF hMemHandle,
							    double (&dTable)[NC_PVT_ECAM_MAX_ARRAY_SIZE],
							    unsigned long ulNumberOfPoints,
							    unsigned long ulStartIndex,
							    unsigned char ucIsTimeAbsolute = 0,
								NC_MOTION_TABLE_TYPE_ENUM eTableType = eNC_TABLE_PVT_ARRAY) throw (CMMCException);

6.3 PVT移动函数

//PVT运动
	virtual void MovePVT(MC_PATH_REF hMemHandle, MC_COORD_SYSTEM_ENUM eCoordSystem) throw (CMMCException);

	/*
	 * brief  这个函数沿着PT/PVT表移动(在线样条)
	 * param hMemHandle - 表访问句柄
	 * param eCoordSystem - 坐标系设置 - 与单轴无关
	 * return 0 执行成功则返回0,否则执行错误
	 */
	 
//PT运动
	virtual int MovePT(MC_PATH_REF hMemHandle, MC_COORD_SYSTEM_ENUM eCoordSystem) throw (CMMCException);

7.PVT 使用教程

7.1 使用方法

三步走(数组方式静态加载):

  1. InitPVTTable()
  2. AppendPVTPoints() / AppendPointsToPVTTable()
  3. MovePVT()

7.2 例程

在这里插入图片描述

/*
 ================================================================================
 Name: 		pvt_motor.cpp
 Author:	Jack Soong
 Version:	1.00
 Description:	测试数组加载的PVT功能
 ================================================================================
 */
#include "mmc_definitions.h"
#include "mmcpplib.h"
#include <iostream>
#include <unistd.h>

using namespace std;

int giAxis1Status,giAxis2Status,giAxis3Status,giAxis4Status;

void TableUnderflow(unsigned short usAxisRef);
void Emergency_Received(unsigned short usAxisRef, short sEmcyCode);
int  CallbackFunc(unsigned char* recvBuffer, short recvBufferSize,void* lpsock);
void SetData();
//===========================================================================================
int main(int argc, char* argv[])
{
	CMMCConnection MyConnectionClass;
	unsigned int ui_conn_hndl;
	CMMCGroupAxis Group1;
	CMMCSingleAxis Axis1,Axis2,Axis3,Axis4;

	ui_conn_hndl = MyConnectionClass.ConnectIPCEx(0x7fffffff,(MMC_MB_CLBK)CallbackFunc);
	MyConnectionClass.GetVersion();
	MyConnectionClass.GetVersion_Ex();

	//关联轴
	Axis1.InitAxisData("a01",ui_conn_hndl);
	Axis2.InitAxisData("a02",ui_conn_hndl);
	Axis3.InitAxisData("a03",ui_conn_hndl);
	Axis4.InitAxisData("a04",ui_conn_hndl);

	//为特定类型回调注册事件回调
	MyConnectionClass.RegisterEventCallback(MMCPP_TABLE_UNDERFLOW,(void*)TableUnderflow);
	MyConnectionClass.RegisterEventCallback(MMCPP_EMCY, (void*)Emergency_Received);

	MMC_MOTIONPARAMS_GROUP	stVectorDefault ;
	stVectorDefault.fAcceleration	= 1000000;                             //加速度
	stVectorDefault.fDeceleration	= 1000000;                           //负加速度
	stVectorDefault.fJerk			= 20000000;                         //加加速度
	stVectorDefault.fVelocity		= 1000000;                          //速度
	stVectorDefault.eBufferMode		= MC_BUFFERED_MODE;             //定义轴的行为
	stVectorDefault.eTransitionMode	= MC_TM_NONE_MODE;                 //转换模式
	stVectorDefault.eCoordSystem	= MC_ACS_COORD;                //定义支持的坐标系统的类型
	stVectorDefault.m_uiExecDelayMs = 0;                             //执行下一个动作的延迟(以秒为单位)。任意+ve整数值
	stVectorDefault.ucSuperimposed 	= 0;                            //是否操作了叠加选项
	stVectorDefault.ucExecute		=1;                           //从上升边缘启动执行命令

	// Initialize Vctor names and default parameters.初始化Vctor名称和默认参数。
	Group1.InitAxisData("v01",ui_conn_hndl) ; //关联轴组
	Group1.SetDefaultParams(stVectorDefault); //更新轴组参数///

	giAxis1Status 	= Axis1.ReadStatus() ;
	if(giAxis1Status & NC_AXIS_ERROR_STOP_MASK)
	{
		Axis1.Reset() ;
		giAxis1Status 	= Axis1.ReadStatus() ;
	}

	giAxis2Status 	= Axis2.ReadStatus() ;
	if(giAxis2Status & NC_AXIS_ERROR_STOP_MASK)
	{
		Axis2.Reset() ;
		giAxis2Status 	= Axis2.ReadStatus() ;
	}

	giAxis3Status 	= Axis3.ReadStatus() ;
	if(giAxis3Status & NC_AXIS_ERROR_STOP_MASK)
	{
		Axis3.Reset() ;
		giAxis3Status 	= Axis3.ReadStatus() ;
	}

	giAxis4Status 	= Axis4.ReadStatus() ;
	if(giAxis4Status & NC_AXIS_ERROR_STOP_MASK)
	{
		Axis4.Reset() ;
		giAxis4Status 	= Axis4.ReadStatus() ;
	}

	/*-----------------------   All axis and group enable     ----------------------------*/
	Axis1.PowerOn();
	while (!(Axis1.ReadStatus() & NC_AXIS_STAND_STILL_MASK));
	Axis2.PowerOn();
	while (!(Axis2.ReadStatus() & NC_AXIS_STAND_STILL_MASK));
	Axis3.PowerOn();
	while (!(Axis3.ReadStatus() & NC_AXIS_STAND_STILL_MASK));
	Axis4.PowerOn();
	while (!(Axis4.ReadStatus() & NC_AXIS_STAND_STILL_MASK));

	cout<<"aaa"<<endl;
	Group1.GroupEnable();
	cout<<"bbb"<<endl;
	while (!(Group1.ReadStatus() & NC_GROUP_STANDBY_MASK));
	cout<<"ccc"<<endl;

	/*-----------------------    Go Home    ----------------------------*/
	/* All axis go back to absolute 0 position */
	//所有电机回零
	//两种写法,如果不用类,直接指定,则可以直接赋值,具体参考手册 Group移动部分
	//轴组回零有问题
	double db_pos[4] = {0,0,0,0};
	Group1.MoveLinearAbsolute(100000, db_pos); //参数1为最大的速度值,参数2为轴运动目标
	while (!(Group1.ReadStatus() & NC_GROUP_STANDBY_MASK));

	sleep(0.5);

	/*-----------------------    Set data table       ----------------------------*/
	/*-----------------------    PVT Table Setting    ----------------------------*/

	MC_PATH_REF PVTReference;
	double dTable[170]={
			0,	0,	0,	0,	0,	0,	0,	0,	0,
			1,	655360,	1000000,	655360,	1000000,	655360,	1000000,	655360,	1000000,
			0.2,	1310720,	1000000,	1310720,	1000000,	1310720,	1000000,	1310720,	1000000,
			0.2,	1966080,	1000000,	1966080,	1000000,	1966080,	1000000,	1966080,	1000000,
			0.2,	2621440,	1000000,	2621440,	1000000,	2621440,	1000000,	2621440,	1000000,
			0.2,	3276800,	1000000,	3276800,	1000000,	3276800,	1000000,	3276800,	1000000,
			0.2,	3932160,	1000000,	3932160,	1000000,	3932160,	1000000,	3932160,	1000000,
			0.2,	4587520,	1000000,	4587520,	1000000,	4587520,	1000000,	4587520,	1000000,
			0.2,	5242880,	1000000,	5242880,	1000000,	5242880,	1000000,	5242880,	1000000,
			0.2,	5898240,	1000000,	5898240,	1000000,	5898240,	1000000,	5898240,	1000000,
			1,	6553600,	0,	6553600,	0,	6553600,	0,	6553600,	0,
	};

	//
	/*-----------------------    PVT Motion    ----------------------------*/

	PVTReference = Group1.InitPVTTable(300,3,0,1,4,MC_ACS_COORD);
	Group1.AppendPVTPoints(PVTReference,dTable,11);//相对时间
	Group1.MovePVT(PVTReference,MC_ACS_COORD);



	int GroupStatus;
	while(!((GroupStatus = Group1.ReadStatus()) & NC_GROUP_STANDBY_MASK))
	{
		usleep(1000);
		cout << "Moving !!!" << endl;
	}

/*-----------------------    卸载PVT数据,Disable各轴及轴组      ----------------------------*/
	Group1.UnloadPVTTable(PVTReference);
	Group1.GroupDisable();
	Axis1.PowerOff();
	Axis2.PowerOff();
	Axis3.PowerOff();
	Axis4.PowerOff();
	MMC_CloseConnection(ui_conn_hndl);
	printf("Program finishedn");
	return 0;
}
//===========================================================================================


void TableUnderflow(unsigned short usAxisRef)
{
	cout << "usAxisRef = " << usAxisRef << endl;
	//bSendpoints = true;
	return;
}

void Emergency_Received(unsigned short usAxisRef, short sEmcyCode)
{
	printf("Emergency Message Received on Axis %d. Code: %xn",usAxisRef,sEmcyCode) ;
}

int CallbackFunc(unsigned char* recvBuffer, short recvBufferSize,void* lpsock)
{
	switch(recvBuffer[1])
	{
	case EMCY_EVT:
		printf("Emergency Event receivedrn") ;
		break ;
	case MOTIONENDED_EVT:
		printf("Motion Ended Event receivedrn") ;
		break ;
	case HBEAT_EVT:
		printf("H Beat Fail Event receivedrn") ;
		break ;
	case PDORCV_EVT:
		printf("PDO Received Event received - Updating Inputsrn") ;
		break ;
	case DRVERROR_EVT:
		printf("Drive Error Received Event receivedrn") ;
		break ;
	case HOME_ENDED_EVT:
		printf("Home Ended Event receivedrn") ;
		break ;
	case SYSTEMERROR_EVT:
		printf("System Error Event receivedrn") ;
		break ;
	}
	return 1 ;
}

在这里插入图片描述

最后

以上就是重要大米为你收集整理的Platinum Maestro运动控制器 —— PVT模式笔记0. 文章说明1. PVT说明2.PVT 插值模式3. 数据加载4. PVT 运动5.动态模式6.PVT在C++中的实现7.PVT 使用教程的全部内容,希望文章能够帮你解决Platinum Maestro运动控制器 —— PVT模式笔记0. 文章说明1. PVT说明2.PVT 插值模式3. 数据加载4. PVT 运动5.动态模式6.PVT在C++中的实现7.PVT 使用教程所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部