Platinum Maestro运动控制器 —— PVT模式笔记
发布日期:2021-07-01 04:03:58 浏览次数:5 分类:技术文章

本文共 9755 字,大约阅读时间需要 32 分钟。

文章目录

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 
#include
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"<

在这里插入图片描述

转载地址:https://miracle.blog.csdn.net/article/details/91128575 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Platinum Maestro运动控制器 —— 运动程序笔记
下一篇:运动控制 —— 强大的状态机工具

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月25日 17时04分50秒