【AI解析】一个简单的 C 库,用于控制工业机器人源码注释(三)
·
RSVG.h RSVG.c
RSVG.h 文件
#ifndefR_SVG_H // 如果宏 R_SVG_H 未被定义
#defineR_SVG_H// 则定义宏 R_SVG_H,这是标准的头文件保护宏,防止头文件被重复包含
#include"RobControl.h"// 包含机器人控制相关的头文件
#include"constants.h"// 包含项目自定义的常量定义头文件
#include"PathPlanner.h"// 包含路径规划器相关的头文件
#include<math.h>// 包含标准数学库头文件
/* Declaration of set value generator datatype and function block */// 注释块:声明设定值生成器的数据类型和功能块
typedefstructRSVG_Type// 定义一个名为 RSVG_Type 的结构体,代表一个实时速度生成器实例
{// 结构体开始
double TargetPosition;// 目标位置
double StartPosition;// 起始位置
double StartSpeed;// 起始速度
double EndSpeed;// 结束速度
double StartAcc;// 起始加速度
structRobot_Parameter_JointLimits_Type DynamicLimits;// 动力学限制参数(最大值)
structRobot_Parameter_JointLimits_Type DynamicValues;// 动力学设定值(用于当前运动)
double Cycletime;// 周期时间
double Override;// 速度倍率
double Position;// 当前计算出的位置(输出)
double Speed;// 当前计算出的速度(输出)
double Acceleration;// 当前计算出的加速度(输出)
unsignedshort Status;// 功能块的状态(错误码或OK)
unsignedchar State;// 内部状态机的当前状态
unsignedchar Phase;// 运动的阶段(加速、匀速、减速)
signedchar moveDirection;// 运动方向(1 或 -1)
double beginPosition;// 运动开始时的实际位置
double beginSpeed;// 运动开始时的实际速度
double beginAcc;// 运动开始时的实际加速度
double endPosition;// 运动结束时的实际位置
double elapsedTime;// 运动已经过的时间
double ds;// 当前周期内的位移
double dt[7];// 7段式速度曲线的各个时间段的结束时间点
double delta;// 匀速段的长度
double epsilon;// (可能未使用或已废弃)
double v;// 达到的最大速度或匀速段速度
double v1;// 加速段结束时的速度
double v2;// 匀加速段结束时的速度
double a0;// 加速段的最大加速度
double a1;// 减速段的最大加速度
double j;// 加加速度(Jerk)
double astart_up;// 加速段的起始加速度
double astart_down;// 减速段的起始加速度
unsignedshort Enable;// 使能输入
unsignedshort Start;// 开始命令输入
unsignedshort Stop;// 停止命令输入
unsignedshort EStop;// 紧急停止命令输入
unsignedshort Done;// 运动完成输出标志
unsignedshort endLimits;// 标记目标位置是否被限位截断
double RedFactor;// 减速因子,用于优化运动时限制速度
} RSVG_Type;// 结构体定义结束
voidRSVG(structRSVG_Type* inst);// 声明实时速度生成器的主函数
#endif// 结束 #ifndef R_SVG_H 的宏定义条件块
RSVG.c 文件
#include"RSVG.h"// 包含此源文件对应的头文件 "RSVG.h"
#include"RobControl.h"// 包含机器人控制相关的头文件
#include"constants.h"// 包含项目自定义的常量定义头文件
#include"PathPlanner.h"// 包含路径规划器相关的头文件
#include<math.h>// 包含标准数学库头文件
#definesign(a)((a<0)?-1:1)// 定义一个宏函数 sign,返回一个数的符号(-1, 0, 或 1)
#defineSTATE_STANDSTILL0// 定义宏 STATE_STANDSTILL,表示静止状态
#defineSTATE_MOVING1// 定义宏 STATE_MOVING,表示运动中状态
#defineSTATE_STOPPING2// 定义宏 STATE_STOPPING,表示正在停止状态
#defineSTATE_ESTOPPING3// 定义宏 STATE_ESTOPPING,表示正在紧急停止状态
#defineSTATE_ERROR4// 定义宏 STATE_ERROR,表示错误状态
/* Set-value generator */// 注释块:设定值生成器
voidRSVG(structRSVG_Type* inst)// 定义实时速度生成器的主函数
{// 函数体开始
if(!inst->Enable)// 如果使能输入为假
{// if块开始
inst->Status = ERR_DISABLED;// 设置状态为“已禁用”
inst->State = STATE_STANDSTILL;// 将内部状态机设为静止
inst->Start =0;// 清除开始命令
inst->Stop =0;// 清除停止命令
inst->EStop =0;// 清除急停命令
inst->Speed =0;// 输出速度为0
inst->Acceleration =0;// 输出加速度为0
return;// 提前返回,不执行后续代码
}// if块结束
elseif(inst->Status == ERR_DISABLED)// 如果使能输入为真,且之前状态是“已禁用”
{// reset status at enable positive edge // 注释:在使能信号的上升沿复位状态
inst->Status = STATUS_OK;// 将状态复位为“OK”
}// else if块结束
double oldPosition,oldSpeed;// 声明变量用于存储上一周期的位置和速度
double v,a0,a1,j,t,d;// 声明用于运动学计算的局部变量
double astart_up, astart_down;// 声明用于加减速的起始加速度
oldPosition = inst->Position;// 备份当前周期的位置
oldSpeed = inst->Speed;// 备份当前周期的速度
/*************** simplify variable notations ***************/// 注释块:简化变量符号
v = inst->v;// 将结构体内部变量赋给局部变量以方便使用
a0 = inst->a0;// ...
a1 = inst->a1;// ...
j = inst->j;// ...
astart_up = inst->astart_up;// ...
astart_down = inst->astart_down;// ...
double cycletime = inst->Cycletime * inst->RedFactor;//this is the magic of optimized motion (limited speed only) // 周期时间乘以减速因子
if(cycletime <0)// 如果计算出的周期时间为负
{// if块开始
cycletime =0;// 设为0
inst->Status = ERR_SPG_CYCLETIME;// 设置周期时间错误
}// if块结束
doubleoverride= inst->Override;// 获取速度倍率
if(override<0)// 如果倍率为负
{// if块开始
override=0;// 设为0
inst->Status = ERR_SPG_OVERRIDE;// 设置倍率错误
}// if块结束
/*************** evaluate INPUT commands ***************/// 注释块:评估输入命令
if((inst->Start)&&(inst->State == STATE_STANDSTILL))//currently only works from standstill // 如果有开始命令且当前处于静止状态
{// if块开始
inst->Start =0;// 清除开始命令
inst->Status = STATUS_OK;// 设置状态为OK
/* new movement? -> set start position */// 注释:新的运动?-> 设置起始位置
if(inst->State == STATE_STANDSTILL)// 如果当前是静止状态
{// if块开始
inst->Position = inst->StartPosition;// 将当前位置设为指定的起始位置
inst->beginPosition = inst->StartPosition;// 记录运动开始时的位置
oldPosition = inst->Position;// 更新旧位置
}// if块结束
else// 否则(从运动中启动新运动,当前代码逻辑不会进入此分支)
{// start from current position // 注释:从当前位置开始
inst->beginPosition = inst->Position;// 记录运动开始时的位置
}// else块结束
/* determine moving direction */// 注释:确定运动方向
inst->moveDirection =sign(inst->TargetPosition - inst->Position);// 根据目标位置和当前位置计算运动方向
/* simplify variable notations */// 注释:简化变量符号
if(inst->moveDirection >0)// 如果是正向运动
{//positive move // 注释:正向移动
v = inst->DynamicValues.VelocityPos;// 使用正向动力学参数
a0 = inst->DynamicValues.AccelerationPos;// ...
a1 = inst->DynamicValues.AccelerationPos;// ...
j = inst->DynamicValues.JerkPos;// ...
//check that given movement parameters are within dynamic limits // 注释:检查给定的运动参数是否在动力学限制内
if((v<=0)||(v>inst->DynamicLimits.VelocityPos))// 如果速度无效或超限
{// if块开始
inst->Status = ERR_SPG_LIMIT_VEL;// 设置速度超限错误
}// if块结束
if((a0<=0)||(a0>inst->DynamicLimits.AccelerationPos)||(a1<=0)||(a1>inst->DynamicLimits.AccelerationPos))// 如果加速度无效或超限
{// if块开始
inst->Status = ERR_SPG_LIMIT_ACC;// 设置加速度超限错误
}// if块结束
if((j<=0)||(j>inst->DynamicLimits.JerkPos))// 如果加加速度无效或超限
{// if块开始
inst->Status = ERR_SPG_LIMIT_JERK;// 设置加加速度超限错误
}// if块结束
}// if块结束
else// 如果是负向运动
{//negative move // 注释:负向移动
v = inst->DynamicValues.VelocityNeg;// 使用负向动力学参数
a0 = inst->DynamicValues.AccelerationNeg;// ...
a1 = inst->DynamicValues.AccelerationNeg;// ...
j = inst->DynamicValues.JerkNeg;// ...
//check that given movement parameters are within dynamic limits // 注释:检查给定的运动参数是否在动力学限制内
if((v<=0)||(v>inst->DynamicLimits.VelocityNeg))// 如果速度无效或超限
{// if块开始
inst->Status = ERR_SPG_LIMIT_VEL;// 设置速度超限错误
}// if块结束
if((a0<=0)||(a0>inst->DynamicLimits.AccelerationNeg)||(a1<=0)||(a1>inst->DynamicLimits.AccelerationNeg))// 如果加速度无效或超限
{// if块开始
inst->Status = ERR_SPG_LIMIT_ACC;// 设置加速度超限错误
}// if块结束
if((j<=0)||(j>inst->DynamicLimits.JerkNeg))// 如果加加速度无效或超限
{// if块开始
inst->Status = ERR_SPG_LIMIT_JERK;// 设置加加速度超限错误
}// if块结束
}
/* limit end speed to max speed */// 注释:将结束速度限制在最大速度内
if(inst->EndSpeed > v)// 如果指定的结束速度大于最大速度
inst->EndSpeed = v;// 将结束速度限制为最大速度
/* check static limits for start position */// 注释块:检查起始位置的静态限制
if(inst->DynamicLimits.PositionNeg >= inst->DynamicLimits.PositionPos)// 如果负向位置限位大于等于正向限位
{// if块开始
inst->Status = ERR_SPG_LIMIT_POS;// 设置位置限位错误
}// if块结束
if((inst->beginPosition > inst->DynamicLimits.PositionPos)||(inst->beginPosition < inst->DynamicLimits.PositionNeg))// 如果起始位置超出限位
{// if块开始
inst->Status = ERR_SPG_LIMIT_POS;//start position error // 设置位置限位错误
}// if块结束
/* check static limits for target position */// 注释块:检查目标位置的静态限制
if(inst->TargetPosition > inst->DynamicLimits.PositionPos)// 如果目标位置超过正向限位
{// if块开始
inst->endPosition = inst->DynamicLimits.PositionPos;// 将实际结束位置设为正向限位
inst->endLimits =1;// 标记目标被限位截断
}// if块结束
elseif(inst->TargetPosition < inst->DynamicLimits.PositionNeg)// 如果目标位置低于负向限位
{// else if块开始
inst->endPosition = inst->DynamicLimits.PositionNeg;// 将实际结束位置设为负向限位
inst->endLimits =1;// 标记目标被限位截断
}// else if块结束
else// 否则
{// else块开始
inst->endPosition = inst->TargetPosition;// 实际结束位置等于目标位置
inst->endLimits =0;// 未被截断
}// else块结束
/* absolute value of total movement distance */// 注释:总运动距离的绝对值
d =(inst->endPosition - inst->Position)*inst->moveDirection;// 计算总距离
if((inst->Status == STATUS_OK)&&(inst->State == STATE_STANDSTILL))//currently only works from standstill // 如果状态正常且处于静止
{//start movement // 注释:开始运动
inst->Done =0;// 清除完成标志
inst->State = STATE_MOVING;// 切换到运动中状态
inst->elapsedTime =0.0;// 重置已用时间
// numerical computation of dynamic values // 注释:动态值的数值计算
double tmp =MaxMovementDynamics(d,a0,j,v,inst->StartSpeed,inst->EndSpeed,inst->StartAcc,&v,&a0,&a1,&inst->delta);// 调用函数计算实际能达到的最大速度、加减速度和匀速段长度
if(tmp != STATUS_OK)// 如果计算失败
{// if块开始
inst->Status = ERR_SPG_DYNCALC;// 设置动力学计算错误
inst->State = STATE_ERROR;// 切换到错误状态
}// if块结束
/* calculate curve time zones according to previously calculated a and v */// 注释块:根据先前计算的a和v计算曲线的时间区域
inst->dt[0]=0;// 初始化时间段
inst->dt[1]=0;// ...
inst->dt[2]=0;// ...
inst->dt[3]=0;// ...
inst->dt[4]=0;// ...
inst->dt[5]=0;// ...
inst->dt[6]=0;// ...
if(a0!=0)// 如果有加速段
{// if块开始
a0 =fabs(a0);//note that a0 is negative if v_start > v // 取加速度绝对值
inst->StartAcc =fabs(inst->StartAcc);// 取起始加速度绝对值
inst->dt[0]=(a0-inst->StartAcc)/j;// 计算第一段(加加速)时间
inst->dt[1]= inst->dt[0]+1/a0 *(fabs(v-inst->StartSpeed)-0.5*a0*a0/j -inst->StartAcc*(a0-inst->StartAcc)/j -0.5*(a0-inst->StartAcc)*(a0-inst->StartAcc)/j);// 计算第二段(匀加速)的结束时间点
inst->dt[2]= inst->dt[1]+ a0/j;// 计算第三段(减加速)的结束时间点
//speed at end of dt[0] // 注释:dt[0]结束时的速度
inst->v1 = inst->StartSpeed +(inst->StartAcc * inst->dt[0]+0.5*j *inst->dt[0]*inst->dt[0])*sign(v-inst->StartSpeed);// 计算v1
inst->v2 = inst->v1 + a0*(inst->dt[1]-inst->dt[0])*sign(v-inst->StartSpeed);// 计算v2
}// if块结束
if(v!=0)// 如果有匀速段
{// if块开始
inst->dt[3]= inst->dt[2]+ inst->delta/v;// 计算第四段(匀速)的结束时间点
}// if块结束
else// 否则
{// else块开始
inst->dt[3]= inst->dt[2];// 第四段时间为0
}// else块结束
if(a1!=0)// 如果有减速段
{//note that a1 cannot be negative because v_end is always smaller than v // 注释:注意a1不能为负,因为v_end总是小于v
inst->dt[4]= inst->dt[3]+ a1/j;// 计算第五段(加减速)的结束时间点
inst->dt[5]= inst->dt[4]+(v-inst->EndSpeed)/a1-a1/j;// 计算第六段(匀减速)的结束时间点
inst->dt[6]= inst->dt[5]+ a1/j;// 计算第七段(减减速)的结束时间点
}// if块结束
else// 否则
{// else块开始
inst->dt[4]= inst->dt[3];// 减速段时间为0
inst->dt[5]= inst->dt[3];// ...
inst->dt[6]= inst->dt[3];// ...
}// else块结束
}// if块结束
elseif(inst->Status != STATUS_OK)// 如果状态不为OK
{// else if块开始
inst->State = STATE_ERROR;// 切换到错误状态
}// else if块结束
}// if块结束
if(inst->Stop)// 如果有停止命令
{// if块开始
inst->Stop =0;// 清除停止命令
if((inst->State != STATE_STOPPING)&&(inst->State != STATE_ESTOPPING))//stop all movements (that are not already stopping) // 如果当前不是正在停止或急停
{// if块开始
if(inst->State == STATE_STANDSTILL)//continue stopping from previous block // 如果当前静止(可能是上一个块的停止延续)
{// if块开始
inst->beginPosition = inst->StartPosition;// 设置开始位置
oldPosition = inst->beginPosition;// 更新旧位置
inst->endPosition = inst->TargetPosition;// 设置结束位置
}// if块结束
else// 否则
{// stop current block // 注释:停止当前块
inst->beginPosition = inst->Position;// 从当前位置开始停止
}// else块结束
inst->Done =0;// 清除完成标志
inst->State = STATE_STOPPING;// 切换到正在停止状态
if(override>0)// 如果倍率大于0
inst->beginSpeed = inst->Speed * inst->RedFactor /override;//added RedFactor here so that movements that are slowed down already stop quickly // 计算用于停止规划的起始速度
else// 否则
inst->beginSpeed =0;// 起始速度为0
inst->beginAcc =fabs(inst->Acceleration);// 起始加速度为当前加速度的绝对值
inst->elapsedTime =0;// 重置已用时间
if(inst->Phase <1)// 如果当前处于加速阶段
{// movement is accelerating -> need to bring acceleration to zero first // 注释:运动正在加速 -> 需要先将加速度降到零
inst->dt[0]= inst->beginAcc/j;// 计算将加速度降到零的时间
v = inst->beginSpeed +(inst->beginAcc * inst->dt[0]-0.5* j *inst->dt[0]*inst->dt[0]);//speed reached at the end of the first section // 计算该阶段结束时的速度
astart_up = inst->beginAcc;// ...
astart_down =0;// ...
// rest of the movement uses default acceleration // 注释:运动的其余部分使用默认加速度
a0 = inst->DynamicValues.AccelerationPos;// 使用默认加速度
v =fabs(v);// 取速度绝对值
inst->dt[2]=(v/a0)-(a0/j);// 计算匀减速时间
if(inst->dt[2]<=0)// 如果没有匀减速段
{// if块开始
a0 =sqrt(v*j);// 重新计算最大减速度
}// if块结束
if((a0!=0)&&(v!=0))// 如果参数有效
{// if块开始
inst->dt[1]= inst->dt[0]+ a0/j;// 计算时间段
inst->dt[2]= inst->dt[1]+ v/a0-a0/j;// ...
inst->dt[3]= inst->dt[2]+ a0/j;// ...
inst->v1 = v -0.5*a0*a0/j;// 计算中间速度
inst->v2 = inst->v1 - v + a0*a0/j;// ...
}// if块结束
else// 否则
{// else块开始
inst->dt[1]=0;// 时间段为0
inst->dt[2]=0;// ...
inst->dt[3]=0;// ...
inst->v1 =0;// 中间速度为0
inst->v2 =0;// ...
}// else块结束
}// if块结束
elseif(inst->Phase ==1)// 如果当前处于匀速阶段
{// movement is running at constant speed -> decelerate with default acceleration // 注释:运动在匀速运行 -> 以默认加速度减速
inst->dt[0]=0;// 第一段时间为0
astart_up =0;// ...
astart_down =0;// ...
a0 = inst->DynamicValues.AccelerationPos;// 使用默认加速度
v =fabs(inst->beginSpeed);// 取速度绝对值
inst->dt[2]=(v/a0)-(a0/j);// 计算匀减速时间
if(inst->dt[2]<=0)// 如果没有匀减速段
{// if块开始
a0 =sqrt(v*j);// 重新计算最大减速度
}// if块结束
if((a0!=0)&&(v!=0))// 如果参数有效
{// if块开始
inst->dt[1]= inst->dt[0]+ a0/j;// 计算时间段
inst->dt[2]= inst->dt[1]+ v/a0-a0/j;// ...
inst->dt[3]= inst->dt[2]+ a0/j;// ...
inst->v1 = v -0.5*a0*a0/j;// 计算中间速度
inst->v2 = inst->v1 - v + a0*a0/j;// ...
}// if块结束
else// 否则
{// else块开始
inst->dt[1]=0;// 时间段为0
inst->dt[2]=0;// ...
inst->dt[3]=0;// ...
inst->v1 =0;// 中间速度为0
inst->v2 =0;// ...
}// else块结束
}// else if块结束
elseif(inst->Phase >1)// 如果当前处于减速阶段
{// movement is decelerating already -> find out what deceleration is needed to reach zero // 注释:运动已在减速 -> 找出到达零速需要何种减速度
inst->dt[0]=0;// 第一段时间为0
v =fabs(inst->beginSpeed);// 取速度绝对值
astart_up =0;// ...
astart_down = inst->beginAcc;// ...
a0 =sqrt(j*v+0.5*inst->beginAcc*inst->beginAcc);// 计算最大减速度
if(a0<inst->beginAcc) a0=inst->beginAcc;// 限制
if(a0 > inst->DynamicValues.AccelerationPos) a0 = inst->DynamicValues.AccelerationPos;// 限制
if(a0!=0)// 如果不为0
{// if块开始
inst->dt[1]=(a0-inst->beginAcc)/j;// 计算时间段
inst->dt[2]= inst->dt[1]+1/a0 *(v -0.5*a0*a0/j -inst->beginAcc*(a0-inst->beginAcc)/j -0.5*(a0-inst->beginAcc)*(a0-inst->beginAcc)/j);// ...
inst->dt[3]= inst->dt[2]+ a0/j;// ...
inst->v1 = v -(astart_down*inst->dt[1]+0.5*j * inst->dt[1]*inst->dt[1]);// 计算中间速度
inst->v2 = inst->v1 - a0*(inst->dt[2]- inst->dt[1]);// ...
}// if块结束
else// 否则
{// else块开始
inst->dt[1]=0;// 时间段为0
inst->dt[2]=0;// ...
inst->dt[3]=0;// ...
inst->v1 =0;// 中间速度为0
inst->v2 =0;// ...
}// else块结束
}// else if块结束
}// if块结束
}// if块结束
if(inst->EStop)// 如果有急停命令
{// if块开始
if(inst->State == STATE_STANDSTILL)//continue stopping from previous block // 如果当前静止
{// if块开始
inst->beginPosition = inst->StartPosition;// 设置开始位置
oldPosition = inst->beginPosition;// 更新旧位置
inst->endPosition = inst->TargetPosition;// 设置结束位置
}// if块结束
else// 否则
{// stop current block // 注释:停止当前块
inst->beginPosition = inst->Position;// 从当前位置开始停止
}// else块结束
inst->Done =0;// 清除完成标志
inst->EStop =0;// 清除急停命令
inst->State = STATE_ESTOPPING;// 切换到正在急停状态
inst->elapsedTime =0;// 重置已用时间
if(override>0)// 如果倍率大于0
v = inst->Speed /override;//path speed always positive // 计算用于急停规划的速度
else// 否则
v =0;// 速度为0
a0 =-inst->DynamicLimits.AccelerationPos;//e-stop acceleration always negative // 急停加速度为负的最大加速度
inst->dt[0]=-v/a0;// 计算急停时间
}// if块结束
/*************** STATE MACHINE ***************/// 注释块:状态机
switch(inst->State)// 根据当前状态
{// switch块开始
case STATE_STANDSTILL:// 情况:静止
inst->Status = STATUS_OK;// 状态为OK
inst->Acceleration =0;// 加速度为0
break;// 结束
case STATE_MOVING:// 情况:运动中
inst->Status =1;// 状态为1(表示正在运行)
inst->elapsedTime +=(cycletime *override);// 累加已用时间
if(inst->elapsedTime > inst->dt[6])// 如果已用时间超过总时间
{//movement completed // 注释:运动完成
inst->Status = STATUS_OK;// 状态为OK
inst->Done =1;// 设置完成标志
if(inst->endLimits)// 如果目标被限位截断
{// if块开始
inst->Status = ERR_SPG_LIMITS_REACHED;// 设置到达限位错误
}// if块结束
}// if块结束
elseif(inst->elapsedTime > inst->dt[5])// 如果在第七段(减减速)
{// else if块开始
inst->Phase =2;// 阶段为减速
t = inst->dt[0];// ... (以下为各阶段位移的累加计算)
inst->ds =(inst->StartSpeed * t +(j * t*t*t /6.0+0.5* inst->StartAcc * t*t)*sign(v-inst->StartSpeed));
t = inst->dt[1]-inst->dt[0];
inst->ds +=(inst->v1 * t +(0.5* a0 * t*t)*sign(v-inst->StartSpeed));
t = inst->dt[2]-inst->dt[1];
inst->ds +=(inst->v2*t +(0.5* a0 * t*t - j * t*t*t /6.0)*sign(v-inst->StartSpeed));
t = inst->dt[3]-inst->dt[2];
inst->ds +=(v*t);
t = inst->dt[4]-inst->dt[3];
inst->ds +=(v*t -(j * t*t*t /6.0));
t = inst->dt[5]-inst->dt[4];
inst->ds +=(v*t -(0.5* a1 *t*t +0.5* a1*a1/j * t));
t = inst->elapsedTime - inst->dt[5];
inst->ds +=(v*t -(-j *t*t*t /6.0+0.5* a1* t*t + t*((v-inst->EndSpeed)-0.5*a1*a1/j)));
inst->Acceleration =-(a1 - j*t);// 计算当前加速度
}// else if块结束
elseif(inst->elapsedTime > inst->dt[4])// 如果在第六段(匀减速)
{// else if块开始
inst->Phase =2;// 阶段为减速
t = inst->dt[0];// ... (位移累加)
inst->ds =(inst->StartSpeed * t +(j * t*t*t /6.0+0.5* inst->StartAcc * t*t)*sign(v-inst->StartSpeed));
t = inst->dt[1]-inst->dt[0];
inst->ds +=(inst->v1 * t +(0.5* a0 * t*t)*sign(v-inst->StartSpeed));
t = inst->dt[2]-inst->dt[1];
inst->ds +=(inst->v2*t +(0.5* a0 * t*t - j * t*t*t /6.0)*sign(v-inst->StartSpeed));
t = inst->dt[3]-inst->dt[2];
inst->ds +=(v*t);
t = inst->dt[4]-inst->dt[3];
inst->ds +=(v*t -(j * t*t*t /6.0));
t = inst->elapsedTime - inst->dt[4];
inst->ds +=(v*t -(0.5* a1 *t*t +0.5* a1*a1/j * t));
inst->Acceleration =-a1;// 加速度为-a1
}// else if块结束
elseif(inst->elapsedTime > inst->dt[3])// 如果在第五段(加减速)
{// else if块开始
inst->Phase =2;// 阶段为减速
t = inst->dt[0];// ... (位移累加)
inst->ds =(inst->StartSpeed * t +(j * t*t*t /6.0+0.5* inst->StartAcc * t*t)*sign(v-inst->StartSpeed));
t = inst->dt[1]-inst->dt[0];
inst->ds +=(inst->v1 * t +(0.5* a0 * t*t)*sign(v-inst->StartSpeed));
t = inst->dt[2]-inst->dt[1];
inst->ds +=(inst->v2*t +(0.5* a0 * t*t - j * t*t*t /6.0)*sign(v-inst->StartSpeed));
t = inst->dt[3]-inst->dt[2];
inst->ds +=(v*t);
t = inst->elapsedTime - inst->dt[3];
inst->ds +=(v*t -(j * t*t*t /6.0));
inst->Acceleration =-j * t;// 计算当前加速度
}// else if块结束
elseif(inst->elapsedTime > inst->dt[2])// 如果在第四段(匀速)
{// else if块开始
inst->Phase =1;// 阶段为匀速
t = inst->dt[0];// ... (位移累加)
inst->ds =(inst->StartSpeed * t +(j * t*t*t /6.0+0.5* inst->StartAcc * t*t)*sign(v-inst->StartSpeed));
t = inst->dt[1]-inst->dt[0];
inst->ds +=(inst->v1 * t +(0.5* a0 * t*t)*sign(v-inst->StartSpeed));
t = inst->dt[2]-inst->dt[1];
inst->ds +=(inst->v2*t +(0.5* a0 * t*t - j * t*t*t /6.0)*sign(v-inst->StartSpeed));
t = inst->elapsedTime - inst->dt[2];
inst->ds +=(v*t);
inst->Acceleration =0;// 加速度为0
}// else if块结束
elseif(inst->elapsedTime > inst->dt[1])// 如果在第三段(减加速)
{// else if块开始
inst->Phase =0;// 阶段为加速
t = inst->dt[0];// ... (位移累加)
inst->ds =(inst->StartSpeed * t +(j * t*t*t /6.0+0.5* inst->StartAcc * t*t)*sign(v-inst->StartSpeed));
t = inst->dt[1]-inst->dt[0];
inst->ds +=(inst->v1 * t +(0.5* a0 * t*t)*sign(v-inst->StartSpeed));
t = inst->elapsedTime - inst->dt[1];
inst->ds +=(inst->v2*t +(0.5* a0 * t*t - j * t*t*t /6.0)*sign(v-inst->StartSpeed));
inst->Acceleration =(a0 - j * t)*sign(v-inst->StartSpeed);// 计算当前加速度
}// else if块结束
elseif(inst->elapsedTime > inst->dt[0])// 如果在第二段(匀加速)
{// else if块开始
inst->Phase =0;// 阶段为加速
t = inst->dt[0];// ... (位移累加)
inst->ds =(inst->StartSpeed * t +(j * t*t*t /6.0+0.5* inst->StartAcc * t*t)*sign(v-inst->StartSpeed));
t = inst->elapsedTime - inst->dt[0];
inst->ds +=(inst->v1 * t +(0.5* a0 * t*t)*sign(v-inst->StartSpeed));
inst->Acceleration = a0 *sign(v-inst->StartSpeed);// 加速度为a0
}// else if块结束
else// 如果在第一段(加加速)
{// else块开始
inst->Phase =0;// 阶段为加速
t = inst->elapsedTime;// ... (位移计算)
inst->ds =(inst->StartSpeed * t +(j * t*t*t /6.0+0.5* inst->StartAcc * t*t)*sign(v-inst->StartSpeed));
inst->Acceleration =(inst->StartAcc + j * t)*sign(v-inst->StartSpeed);// 计算当前加速度
}// else块结束
inst->Position = inst->beginPosition +(inst->ds * inst->moveDirection);// 根据位移和方向计算当前位置
if(inst->Done)// 如果已完成
{// if块开始
inst->Position = inst->endPosition;// 将位置强制设为目标位置
}// if块结束
//check if movement has completed already but speed and acceleration have not reached zero yet -> movement must continue in next tangential block! // 注释:检查运动是否已完成,但速度和加速度尚未达到零 -> 运动必须在下一个相切块中继续!
//moveDirection negative is needed for manual jogging in negative direction! // 注释:负向运动方向是手动负向点动所必需的!
if((!inst->Done)&&(((inst->Position >= inst->endPosition)&&(inst->moveDirection >0))||((inst->Position <= inst->endPosition)&&(inst->moveDirection <0))))// 如果未完成但已越过目标
{// if块开始
inst->Status = STATUS_ABORT;// 设置状态为中止(用于过渡)
inst->Done =1;// 设置完成标志
}// if块结束
break;// 结束处理
case STATE_STOPPING:// 情况:正在停止
inst->Status =1;// 状态为1
inst->elapsedTime +=(cycletime *override);// 累加时间
//movement already stopped by zero override // 注释:运动已被零倍率停止
if(override==0)// 如果倍率为0
{// if块开始
inst->Status = STATUS_OK;// 状态OK
inst->Done =1;// 完成
}// if块结束
if(inst->elapsedTime > inst->dt[3])// 如果已用时间超过总停止时间
{//movement completed // 注释:运动完成
//used to increase precision in case dt[0] is shorter than one cycle time // 注释:用于提高精度,以防dt[0]短于一个周期时间
t = inst->dt[0];// ... (位移累加)
inst->ds =(fabs(inst->beginSpeed)* t +0.5* astart_up * t*t - j * t*t*t /6.0);
t = inst->dt[1]-inst->dt[0];
inst->ds +=(v*t -(j * t*t*t /6.0)-0.5* astart_down * t*t);
t = inst->dt[2]-inst->dt[1];
inst->ds +=(inst->v1 *t -(0.5* a0 *t*t));
t = inst->dt[3]- inst->dt[2];
inst->ds +=(inst->v2 * t -(-j *t*t*t /6.0+0.5* a0* t*t));
inst->Acceleration =0;// 加速度为0
inst->Status = STATUS_OK;// 状态OK
inst->Done =1;// 完成
}// if块结束
elseif(inst->elapsedTime > inst->dt[2])// 如果在第四段
{// else if块开始
inst->Phase =2;// 阶段为减速
t = inst->dt[0];// ... (位移累加)
inst->ds =(fabs(inst->beginSpeed)* t +0.5* astart_up * t*t - j * t*t*t /6.0);
t = inst->dt[1]-inst->dt[0];
inst->ds +=(v*t -(j * t*t*t /6.0)-0.5* astart_down * t*t);
t = inst->dt[2]-inst->dt[1];
inst->ds +=(inst->v1 *t -(0.5* a0 *t*t));
t = inst->elapsedTime - inst->dt[2];
inst->ds +=(inst->v2 * t -(-j *t*t*t /6.0+0.5* a0* t*t));
inst->Acceleration =-(a0-j*t);// 计算加速度
}// else if块结束
elseif(inst->elapsedTime > inst->dt[1])// 如果在第三段
{// else if块开始
inst->Phase =2;// 阶段为减速
t = inst->dt[0];// ... (位移累加)
inst->ds =(fabs(inst->beginSpeed)* t +0.5* astart_up * t*t - j * t*t*t /6.0);
t = inst->dt[1]-inst->dt[0];
inst->ds +=(v*t -(j * t*t*t /6.0)-0.5* astart_down * t*t);
t = inst->elapsedTime - inst->dt[1];
inst->ds +=(inst->v1 *t -(0.5* a0 *t*t));
inst->Acceleration =-a0;// 加速度为-a0
}// else if块结束
elseif(inst->elapsedTime > inst->dt[0])// 如果在第二段
{// else if块开始
inst->Phase =2;// 阶段为减速
t = inst->dt[0];// ... (位移累加)
inst->ds =(fabs(inst->beginSpeed)* t +0.5* astart_up * t*t - j * t*t*t /6.0);
t = inst->elapsedTime - inst->dt[0];
inst->ds +=(v*t -(j * t*t*t /6.0)-0.5* astart_down * t*t);
inst->Acceleration =-j * t - astart_down;// 计算加速度
}// else if块结束
else// 如果在第一段
{// else块开始
inst->Phase =0;// 阶段为加速(实际是减小加速度)
t = inst->elapsedTime;// ... (位移计算)
inst->ds =(fabs(inst->beginSpeed)* t +0.5* astart_up * t*t - j * t*t*t /6.0);
inst->Acceleration = astart_up - j * t;// 计算加速度
}// else块结束
inst->Position = inst->beginPosition +(inst->ds * inst->moveDirection);// 计算当前位置
//check if movement has completed already but speed has not reached zero yet -> movement must stop in next tangential block! // 注释:检查运动是否已完成,但速度尚未达到零 -> 运动必须在下一个相切块中停止!
//moveDirection negative is needed for manual jogging in negative direction! // 注释:同上
if((!inst->Done)&&(((inst->Position >= inst->endPosition)&&(inst->moveDirection >0))||((inst->Position <= inst->endPosition)&&(inst->moveDirection <0))))// 如果未完成但已越过目标
{// if块开始
inst->Status = STATUS_ABORT;// 设置状态为中止
inst->Done =1;// 设置完成标志
}// if块结束
break;// 结束处理
case STATE_ESTOPPING:// 情况:正在急停
inst->Status =1;// 状态为1
inst->elapsedTime +=(cycletime *override);// 累加时间
//movement already stopped by zero override // 注释:运动已被零倍率停止
if(override==0)// 如果倍率为0
{// if块开始
inst->Status = STATUS_OK;// 状态OK
inst->Done =1;// 完成
}// if块结束
if(inst->elapsedTime > inst->dt[0])// 如果已用时间超过总急停时间
{//movement completed // 注释:运动完成
t = inst->dt[0];// ... (位移计算)
inst->ds =(0.5*a0*t*t+v*t);//used to increase precision in case dt[0] is shorter than one cycle time //
inst->Status = STATUS_OK;// 状态OK
inst->Done =1;// 完成
inst->Acceleration =0;// 加速度为0
}// if块结束
else// 否则
{// else块开始
t = inst->elapsedTime;// ... (位移计算)
inst->ds =(0.5*a0*t*t+v*t);
inst->Acceleration = a0;// 加速度为a0
}// else块结束
inst->Position = inst->beginPosition + inst->ds;// 计算当前位置
//check if movement has completed already but speed has not reached zero yet -> movement must stop in next tangential block! // 注释:同上
//moveDirection negative is needed for manual jogging in negative direction! // 注释:同上
if((!inst->Done)&&(((inst->Position >= inst->endPosition)&&(inst->moveDirection >0))||((inst->Position <= inst->endPosition)&&(inst->moveDirection <0))))// 如果未完成但已越过目标
{// if块开始
inst->Status = STATUS_ABORT;// 设置状态为中止
inst->Done =1;// 设置完成标志
}// if块结束
break;// 结束处理
case STATE_ERROR:// 情况:错误
//return to standstill // 注释:返回静止状态
inst->State = STATE_STANDSTILL;// 切换到静止状态
}// switch块结束
/*************** update OUTPUT values ***************/// 注释块:更新输出值
if(cycletime !=0)// 如果周期时间不为0
{// if块开始
inst->Speed =(inst->Position - oldPosition)/ cycletime;// 通过差分计算速度
if(inst->Done)// 如果已完成
{// if块开始
if((inst->State == STATE_ESTOPPING)||(inst->State == STATE_STOPPING))// 如果是停止或急停
{// if块开始
if(inst->Status == STATUS_OK)// 如果状态正常
{// if块开始
inst->Speed =0;//zero speed at end of movement (not if aborted -> could be non-zero speed and stopping must continue in next movement) // 速度为0
inst->Acceleration =0;// 加速度为0
}// if块结束
}// if块结束
else// 否则(正常运动完成)
{// else块开始
if(inst->Status == STATUS_OK)//not STATUS_ABORT -> movement is completed with EndSpeed and zero acc // 如果状态正常
{// if块开始
inst->Speed = inst->EndSpeed *override;//stable speed at end of movement // 速度等于结束速度
inst->Acceleration =0;// 加速度为0
}// if块结束
//else STATUS_ABORT -> path blending (end speed not necessarily reached, acc not zero) // 注释:否则是状态中止 -> 路径过渡
}// else块结束
inst->State = STATE_STANDSTILL;// 切换到静止状态
}// if块结束
}// if块结束
else// 如果周期时间为0
{// else块开始
inst->Speed =0;// 速度为0
inst->Acceleration =0;// 加速度为0
}// else块结束
/*************** reset all commands ***************/// 注释块:复位所有命令
inst->Start =0;// 清除开始命令
inst->Stop =0;// 清除停止命令
inst->EStop =0;// 清除急停命令
/*************** simplify variable notations ***************/// 注释块:简化变量符号
inst->v = v;// 将局部变量保存回结构体
inst->a0 = a0;// ...
inst->a1 = a1;// ...
inst->j = j;// ...
inst->astart_up = astart_up;// ...
inst->astart_down = astart_down;// ...
}// RSVG 函数体结束
static.h
#ifndefSTATIC_H // 如果宏 STATIC_H 未被定义,则执行以下代码。这是一个防止头文件被重复包含的预处理指令。
#defineSTATIC_H// 定义宏 STATIC_H,以标记该头文件已经被包含。
/* define static variables here */// 注释块:在此处定义静态变量
/* static variables are not modified at the end of a function call, their values are saved and available at the next call */// 注释:静态变量在一个函数调用结束后不会被修改,它们的值会被保存并在下一次调用时可用。
static Robot_Monitor_Type OldMonitor[MAX_ROBOTS];// 定义一个静态数组 OldMonitor,用于存储每个机器人上一个周期的监控数据。
static Buffer_Type Buffer[MAX_ROBOTS];// 定义一个静态数组 Buffer,作为每个机器人的运动指令缓冲区。
staticstructRSVG_Type fRSVG[MAX_ROBOTS];// 定义一个静态数组 fRSVG,为每个机器人创建一个实时速度生成器(Realtime Speed-Velocity Generator)的实例。
static Robot_Jog_Type Jog[MAX_ROBOTS];// 定义一个静态数组 Jog,用于存储每个机器人当前的jog(点动)参数。
staticdouble Override[MAX_ROBOTS];// 定义一个静态数组 Override,用于存储每个机器人当前的目标速度倍率。
//static double OverrideRampStep[MAX_ROBOTS]; // (被注释的代码) 定义一个静态数组 OverrideRampStep,可能用于速度倍率的斜坡步进值。
staticstructFilter_Type FilterOverride[MAX_ROBOTS];// 定义一个静态数组 FilterOverride,为每个机器人的速度倍率创建一个滤波器实例,用于平滑倍率变化。
static UnitsRatio_Type OldUnitsRatioJoints[MAX_ROBOTS][6];// 定义一个静态二维数组 OldUnitsRatioJoints,用于存储每个机器人各关节上一个周期的单位换算参数。
static UnitsRatio_Type OldUnitsRatioAux[MAX_ROBOTS][6];// 定义一个静态二维数组 OldUnitsRatioAux,用于存储每个机器人各辅助轴上一个周期的单位换算参数。
staticdouble OldFilterTime[MAX_ROBOTS];// 定义一个静态数组 OldFilterTime,用于存储每个机器人上一个周期的滤波器时间常数。
staticdouble OldSingleStep[MAX_ROBOTS];// 定义一个静态数组 OldSingleStep,用于存储每个机器人上一个周期的单步模式状态。
staticdouble HaltedByCmd[MAX_ROBOTS];// 定义一个静态数组 HaltedByCmd,作为标志,记录每个机器人是否由命令触发了暂停状态。
staticdouble StoppedTime[MAX_ROBOTS];// 定义一个静态数组 StoppedTime,用于记录每个机器人停止运动后经过的时间,可能用于滤波器的稳定。
staticdouble OldTransitionAngle[MAX_ROBOTS];// 定义一个静态数组 OldTransitionAngle,用于存储每个机器人上一个周期的最大过渡角度参数。
staticdouble OldConveyorPos[MAX_ROBOTS][2];// 定义一个静态二维数组 OldConveyorPos,用于存储每个机器人各传送带上一个周期的位置。
staticdouble OldSVGPos[MAX_ROBOTS];// 定义一个静态数组 OldSVGPos,用于存储每个机器人速度生成器(SVG)上一个周期的位置输出。
staticdouble OldPathCorrections[MAX_ROBOTS][6];// 定义一个静态二维数组 OldPathCorrections,用于存储每个机器人各轴上一个周期的外部路径修正值。
staticstructFilter_Type FilterJoints[MAX_ROBOTS][6];// 定义一个静态二维数组 FilterJoints,为每个机器人的每个关节创建一个滤波器实例,用于平滑设定位置。
staticstructFilter_Type FilterAux[MAX_ROBOTS][6];// 定义一个静态二维数组 FilterAux,为每个机器人的每个辅助轴创建一个滤波器实例。
//static Robot_Parameter_Workspace_Type CyclicWorkspace[MAX_ROBOTS]; // (被注释的代码) 定义静态数组 CyclicWorkspace,可能用于周期性的工作空间监控。
//static Robot_Parameter_Workspace_Type PathPlannerWorkspace[MAX_ROBOTS]; // (被注释的代码) 定义静态数组 PathPlannerWorkspace,可能用于路径规划器的工作空间参数。
staticshort StoppingError[MAX_ROBOTS];// 定义一个静态数组 StoppingError,用于记录导致每个机器人停止运动的错误代码。
staticlong StoppingLine[MAX_ROBOTS];// 定义一个静态数组 StoppingLine,用于记录导致每个机器人停止运动时所在的程序行号。
staticchar* Robot_Program[MAX_ROBOTS];// 定义一个静态指针数组 Robot_Program,每个指针指向一个机器人的程序代码字符串。
staticunsignedlong EvaluationTime;// 定义一个静态无符号长整型变量 EvaluationTime,可能用于性能评估或许可证检查。
staticdouble RedFactor[MAX_ROBOTS];// 定义一个静态数组 RedFactor,存储每个机器人的速度缩减因子,当运动受关节动力学限制时使用。
staticunsignedshort CheckConstDone;// 定义一个静态无符号短整型变量 CheckConstDone,作为标志,记录常量检查是否已完成。
#endif// 结束 #ifndef STATIC_H 的条件编译块。
Transformation.h Transformation.c
Transformations.h 文件
#ifndefTRF_H // 如果宏 TRF_H 未被定义
#defineTRF_H// 则定义宏 TRF_H,这是标准的头文件保护宏,防止头文件被重复包含
#include<math.h>// 包含标准数学库头文件
#include"Robots.h"// 包含机器人运动学函数的声明
#include"Misc.h"// 包含杂项数据类型和函数的声明,如 Mech_Type
/* Declaration of generic transformations function interface */// 注释块:声明通用变换函数接口
unsignedshortTransformations(structMech_Type* Mechanics,unsignedchar Mode,double JointAxes[6],double PathAxes[6],double Axes[6]);// 声明一个通用的运动学变换函数,它根据机器人类型和模式(正解/逆解)调用相应的具体函数
#endif// 结束 #ifndef TRF_H 的宏定义条件块
Transformations.c 文件
#include"Transformations.h"// 包含此源文件对应的头文件 "Transformations.h"
#include<math.h>// 包含标准数学库头文件
#include"Robots.h"// 包含各种机器人运动学函数的具体实现
#include"Misc.h"// 包含杂项数据类型和函数,如 RoundToEpsilon
unsignedshortTransformations(structMech_Type* Mechanics,unsignedchar Mode,double JointAxes[6],double PathAxes[6],double Axes[6])// 定义通用的运动学变换函数
{// 函数体开始
unsignedshort Status;// 声明一个无符号短整型变量 Status,用于存储函数执行的状态
unsignedshort(*UserDirect)(Link_Type[6],double[6],double[6],double[6])= Mechanics->UserTrf.Direct;// 创建一个函数指针 UserDirect,并将其指向用户自定义的正解函数
unsignedshort(*UserInverse)(Link_Type[6],double[6],double[6],double[6])= Mechanics->UserTrf.Inverse;// 创建一个函数指针 UserInverse,并将其指向用户自定义的逆解函数
if(Mode == TRF_DIRECT)//direct transformations -> calculate path axes from joint axes // 如果模式是正运动学变换
{// if块开始
switch(Mechanics->Type)// 根据机械结构类型进行选择
{// switch块开始
case CNC:// 情况:CNC类型
Axes[0]= JointAxes[0];// X坐标直接等于关节1的值
Axes[1]= JointAxes[1];// Y坐标直接等于关节2的值
Axes[2]= JointAxes[2];// Z坐标直接等于关节3的值
//reset unused output values // 注释:复位未使用的输出值
Axes[3]=0;// 姿态A设为0
Axes[4]=0;// 姿态B设为0
Axes[5]=0;// 姿态C设为0
Status = STATUS_OK;// 设置状态为成功
break;// 结束CNC情况
case SCARA:// 情况:SCARA机器人
Status =ScaraDirect(Mechanics->Links,JointAxes,PathAxes,Axes);// 调用SCARA机器人的正解函数
//reset unused output values // 注释:复位未使用的输出值
Axes[4]=0;// 姿态B设为0
Axes[5]=0;// 姿态C设为0
break;// 结束SCARA情况
case DELTA:// 情况:Delta机器人
Status =DeltaDirect(Mechanics->Links,JointAxes,PathAxes,Axes);// 调用Delta机器人的正解函数
//reset unused output values // 注释:复位未使用的输出值
Axes[4]=0;// 姿态B设为0
Axes[5]=0;// 姿态C设为0
break;// 结束Delta情况
case PALLETIZER:// 情况:码垛机器人
Status =PalletDirect(Mechanics->Links,JointAxes,PathAxes,Axes);// 调用码垛机器人的正解函数
//reset unused output values // 注释:复位未使用的输出值
Axes[4]=0;// 姿态B设为0
Axes[5]=0;// 姿态C设为0
break;// 结束码垛机情况
case RTCP:// 情况:RTCP机器人
Status =RTCP_Direct(Mechanics->Links,JointAxes,PathAxes,Axes);// 调用RTCP机器人的正解函数
break;// 结束RTCP情况
case ARM:// 情况:关节臂机器人
Status =ArmDirect(Mechanics->Links,JointAxes,PathAxes,Axes);// 调用6轴关节臂机器人的正解函数
break;// 结束关节臂情况
case USER:// 情况:用户自定义类型
if(UserDirect ==0)// 如果用户自定义的正解函数指针为空
{// if块开始
Status = ERR_TRF_POINTER;// 设置状态为变换指针错误
break;// 结束用户自定义情况
}// if块结束
Axes[0]=0;// 将输出数组清零
Axes[1]=0;// ...
Axes[2]=0;// ...
Axes[3]=0;// ...
Axes[4]=0;// ...
Axes[5]=0;// ...
Status =UserDirect(Mechanics->Links,JointAxes,PathAxes,Axes);// 通过函数指针调用用户自定义的正解函数
break;// 结束用户自定义情况
default:// 默认情况(未知的机器人类型)
Status = ERR_TRF_MECH_NOT_SUPPORTED;// 设置状态为不支持的机械结构错误
}// switch块结束
/* removing small values near zero helps avoid useless errors at the edge of workspace */// 注释:移除接近零的小值有助于避免在工作空间边缘产生无用的错误
int i=0;// 声明循环变量
for(i=0;i<6;i++)// 遍历所有输出轴
{// for循环开始
Axes[i]=RoundToEpsilon(Axes[i]);// 对每个计算出的坐标值进行精度处理
}// for循环结束
}// if块结束
elseif(Mode == TRF_INVERSE)//inverse transformations -> calculate joint axes from path axes // 如果模式是逆运动学变换
{// else if块开始
switch(Mechanics->Type){// 根据机械结构类型进行选择
case CNC:// 情况:CNC类型
Axes[0]= PathAxes[0];// 关节1 的值直接等于 X 坐标
Axes[1]= PathAxes[1];// 关节 2 的值直接等于 Y 坐标
Axes[2]= PathAxes[2];// 关节 3 的值直接等于 Z 坐标
//reset unused output values // 注释:复位未使用的输出值
Axes[3]=0;// 关节 4 设为0
Axes[4]=0;// 关节 5 设为0
Axes[5]=0;// 关节 6 设为0
Status = STATUS_OK;// 设置状态为成功
break;// 结束CNC情况
case SCARA:// 情况:SCARA机器人
Status =ScaraInverse(Mechanics->Links,PathAxes,JointAxes,Axes);// 调用SCARA机器人的逆解函数
//reset unused output values // 注释:复位未使用的输出值
Axes[4]=0;// 关节 5 设为0
Axes[5]=0;// 关节 6 设为0
break;// 结束SCARA情况
case DELTA:// 情况:Delta机器人
Status =DeltaInverse(Mechanics->Links,PathAxes,JointAxes,Axes);// 调用Delta机器人的逆解函数
//reset unused output values // 注释:复位未使用的输出值
Axes[4]=0;// 关节 5 设为0
Axes[5]=0;// 关节 6 设为0
break;// 结束Delta情况
case PALLETIZER:// 情况:码垛机器人
Status =PalletInverse(Mechanics->Links,PathAxes,JointAxes,Axes);// 调用码垛机器人的逆解函数
//reset unused output values // 注释:复位未使用的输出值
Axes[4]=0;// 关节 5 设为0
Axes[5]=0;// 关节 6 设为0
break;// 结束码垛机情况
case RTCP:// 情况:RTCP机器人
Status =RTCP_Inverse(Mechanics->Links,PathAxes,JointAxes,Axes);// 调用RTCP机器人的逆解函数
break;// 结束RTCP情况
case ARM:// 情况:关节臂机器人
Status =ArmInverse(Mechanics->Links,PathAxes,JointAxes,Axes);// 调用6轴关节臂机器人的逆解函数
break;// 结束关节臂情况
case USER:// 情况:用户自定义类型
if(UserInverse ==0)// 如果用户自定义的逆解函数指针为空
{// if块开始
Status = ERR_TRF_POINTER;// 设置状态为变换指针错误
break;// 结束用户自定义情况
}// if块结束
Axes[0]=0;// 将输出数组清零
Axes[1]=0;// ...
Axes[2]=0;// ...
Axes[3]=0;// ...
Axes[4]=0;// ...
Axes[5]=0;// ...
Status =UserInverse(Mechanics->Links,PathAxes,JointAxes,Axes);// 通过函数指针调用用户自定义的逆解函数
break;// 结束用户自定义情况
default:// 默认情况(未知的机器人类型)
Status = ERR_TRF_MECH_NOT_SUPPORTED;// 设置状态为不支持的机械结构错误
}// switch块结束
int i=0;// 声明循环变量
for(i=0;i<6;i++){// 遍历所有输出轴
Axes[i]=RoundToEpsilon(Axes[i]);// 对每个计算出的关节角进行精度处理
}
}else{//this mode does not exist // 如果模式既不是正解也不是逆解
Status = ERR_TRF_MODE;// 设置状态为变换模式错误
}
return Status;// 返回最终的执行状态
}// Transformations 函数体结束
trig.h trig.c
trig.h 文件
#ifndefTRF_TRIG // 如果宏 TRF_TRIG 未被定义
#defineTRF_TRIG// 则定义宏 TRF_TRIG,这是标准的头文件保护宏,防止头文件被重复包含
#include<math.h>// 包含标准数学库头文件,提供如 sin, cos, atan2 等以弧度为单位的三角函数
/* declaration of some useful trigonometric functions */// 注释块:声明一些有用的三角函数
#definePI3.14159265358979// 定义宏 PI,表示圆周率π的近似值
#definesind(x)sin((x)* PI /180.0)// 定义宏函数 sind(x),用于计算角度x的正弦值(将角度转换为弧度后再调用sin函数)
#definecosd(x)cos((x)* PI /180.0)// 定义宏函数 cosd(x),用于计算角度x的余弦值(将角度转换为弧度后再调用cos函数)
#definetand(x)tan((x)* PI /180.0)// 定义宏函数 tand(x),用于计算角度x的正切值(将角度转换为弧度后再调用tan函数)
#defineasind(x)(asin(x)*180.0/ PI)// 定义宏函数 asind(x),用于计算反正弦值,并返回角度(将弧度结果转换为角度)
#defineacosd(x)(acos(x)*180.0/ PI)// 定义宏函数 acosd(x),用于计算反余弦值,并返回角度(将弧度结果转换为角度)
#defineatand(x)(atan(x)*180.0/ PI)// 定义宏函数 atand(x),用于计算反正切值,并返回角度(将弧度结果转换为角度)
#defineatan2d(y,x)(atan2(y,x)*180.0/ PI)// 定义宏函数 atan2d(y,x),用于计算y/x的反正切值(考虑象限),并返回角度
#definesqrt3sqrt(3.0)// 定义宏 sqrt3,表示根号3
#definesin120(sqrt(3.0)/2.0)// 定义宏 sin120,表示120度的正弦值 (√3/2)
#definecos120-0.5// 定义宏 cos120,表示120度的余弦值 (-0.5)
#definetan60sqrt(3.0)// 定义宏 tan60,表示60度的正切值 (√3)
#definesin300.5// 定义宏 sin30,表示30度的正弦值 (0.5)
#definetan30(1.0/sqrt(3.0))// 定义宏 tan30,表示30度的正切值 (1/√3)
#definesign(a)((a<0)?-1:1)// 定义宏函数 sign(a),用于获取数值a的符号(-1表示负数,1表示正数或零)
doubleModulo2PI(double actual,double desired);// 声明函数 Modulo2PI,用于将角度 actual 调整到以 desired 为中心的 2π (360度) 范围内
doubleModuloPI(double actual,double desired);// 声明函数 ModuloPI,用于将角度 actual 调整到以 desired 为中心的 π (180度) 范围内,选择最近的解
#endif// 结束 #ifndef TRF_TRIG 的宏定义条件块
trig.c 文件
#include"trig.h"// 包含此源文件对应的头文件 "trig.h"
doubleModulo2PI(double actual,double desired)// 定义函数 Modulo2PI
{// add or subtract multiples of 2PI to the actual angle to bring it closer to the desired value // 函数体开始,注释:加上或减去2PI的倍数,以使实际角度更接近期望值
double delta =(actual - desired);// 计算实际角度与期望角度之间的差值
int n =((int)delta +180*sign(delta))/360;// 计算需要加减的360度(2π)的圈数 n
return(actual -(360.0* n));// 返回调整后的角度
}
doubleModuloPI(double actual,double desired)// 定义函数 ModuloPI
{// add or subtract multiples of PI to the actual angle to bring it closer to the desired value // 函数体开始,注释:加上或减去PI的倍数,以使实际角度更接近期望值
actual =Modulo2PI(actual,desired);// 首先调用 Modulo2PI,将角度调整到以 desired 为中心的360度范围内
double delta =(actual - desired);// 重新计算差值
if(delta >90) actual -=180;// 如果差值大于90度,则减去180度,使其进入(-90, 90] 区间
if(delta <-90) actual +=180;// 如果差值小于-90度,则加上180度,使其进入[-90, 90) 区间
return actual;// 返回最终调整后的角度
}
更多推荐



所有评论(0)