/// <summary> /// 伺服运动模块中计算下一周期的Tcp位置 /// </summary> /// <param name="tcpRealPosition">实时Tcp坐标</param> /// <param name="referenceForce">参考力信号</param> /// <returns>返回下一周期的Tcp位置</returns> protected override double[] ServoMotionNextTcpPosition(double[] tcpRealPosition, double[] referenceForce, double[] moreInfo = null) { int refFlag = 0; double[] refDist = new double[] { 0.0, 0.0 }; double[] refPosture = new double[] { 0.0, 0.0, 0.0 }; double refForce = 0.0; lock (refLocker) { refFlag = servoMotionRefFlag; refDist[0] = servoMotionRefPos[0]; refDist[1] = servoMotionRefPos[1]; refPosture[0] = servoMotionRefPos[2]; refPosture[1] = servoMotionRefPos[3]; refPosture[2] = servoMotionRefPos[4]; refForce = servoMotionRefPos[5]; } double[] nextTcpPosition = (double[])tcpRealPosition.Clone(); // 暂停运动 if (servoMotionActivePause) { return(nextTcpPosition); } // 姿态变化,单周期幅值限制 double[] currentPosture = new double[] { tcpRealPosition[3], tcpRealPosition[4], tcpRealPosition[5] }; double[] transitPosture = URMath.Quatnum2AxisAngle( URMath.FindTransitQuatnum( URMath.AxisAngle2Quatnum(currentPosture), URMath.AxisAngle2Quatnum(refPosture))); double transitAngle = URMath.LengthOfArray(transitPosture); double[] transitAxis = new double[] { transitPosture[0] / transitAngle, transitPosture[1] / transitAngle, transitPosture[2] / transitAngle }; if (transitAngle <= servoMotionMaxAngleIncrement) { nextTcpPosition[3] = refPosture[0]; nextTcpPosition[4] = refPosture[1]; nextTcpPosition[5] = refPosture[2]; } else { double[] newPosture = URMath.Quatnum2AxisAngle( URMath.QuatnumRotate(new Quatnum[] { URMath.AxisAngle2Quatnum(currentPosture), URMath.AxisAngle2Quatnum(new double[] { transitAxis[0] * servoMotionMaxAngleIncrement, transitAxis[1] * servoMotionMaxAngleIncrement, transitAxis[2] * servoMotionMaxAngleIncrement }) })); nextTcpPosition[3] = newPosture[0]; nextTcpPosition[4] = newPosture[1]; nextTcpPosition[5] = newPosture[2]; } // 位移变化 double[] currentPosition = new double[] { tcpRealPosition[0], tcpRealPosition[1], tcpRealPosition[2] }; double[] initialPosition = new double[] { servoMotionBeginTcpPosition[0], servoMotionBeginTcpPosition[1], servoMotionBeginTcpPosition[2] }; double[] initialPosture = new double[] { servoMotionBeginTcpPosition[3], servoMotionBeginTcpPosition[4], servoMotionBeginTcpPosition[5] }; double[] aimPointAtPlane = new double[] { initialPosition[0] + servoMotionToolDirectionXAtBase[0] * refDist[0] + servoMotionToolDirectionYAtBase[0] * refDist[1], initialPosition[1] + servoMotionToolDirectionXAtBase[1] * refDist[0] + servoMotionToolDirectionYAtBase[1] * refDist[1], initialPosition[2] + servoMotionToolDirectionXAtBase[2] * refDist[0] + servoMotionToolDirectionYAtBase[2] * refDist[1] }; double[] currentZAxisAtBase = internalProcessor.ZDirectionOfTcpAtBaseReference(tcpRealPosition); double enlongedCoeff = (currentZAxisAtBase[0] * (currentPosition[0] - aimPointAtPlane[0]) + currentZAxisAtBase[1] * (currentPosition[1] - aimPointAtPlane[1]) + currentZAxisAtBase[2] * (currentPosition[2] - aimPointAtPlane[2])) / (currentZAxisAtBase[0] * servoMotionToolDirectionZAtBase[0] + currentZAxisAtBase[1] * servoMotionToolDirectionZAtBase[1] + currentZAxisAtBase[2] * servoMotionToolDirectionZAtBase[2]); double[] aimPointAtSurf = new double[] { aimPointAtPlane[0] + enlongedCoeff * servoMotionToolDirectionZAtBase[0], aimPointAtPlane[1] + enlongedCoeff * servoMotionToolDirectionZAtBase[1], aimPointAtPlane[2] + enlongedCoeff * servoMotionToolDirectionZAtBase[2] }; double[] refDelta = new double[] { aimPointAtSurf[0] - currentPosition[0], aimPointAtSurf[1] - currentPosition[1], aimPointAtSurf[2] - currentPosition[2] }; double refDeltaDistance = URMath.LengthOfArray(refDelta); double[] refDeltaDirection = new double[] { refDelta[0] / refDeltaDistance, refDelta[1] / refDeltaDistance, refDelta[2] / refDeltaDistance }; if (refDeltaDistance > servoMotionMaxDistanceIncrement) { aimPointAtSurf[0] = currentPosition[0] + servoMotionMaxDistanceIncrement * refDeltaDirection[0]; aimPointAtSurf[1] = currentPosition[1] + servoMotionMaxDistanceIncrement * refDeltaDirection[1]; aimPointAtSurf[2] = currentPosition[2] + servoMotionMaxDistanceIncrement * refDeltaDirection[2]; } nextTcpPosition[0] = aimPointAtSurf[0]; nextTcpPosition[1] = aimPointAtSurf[1]; nextTcpPosition[2] = aimPointAtSurf[2]; // 力变化 double forceDirectionZIncrement = 0.0; bool ifContinueForceTrack; lock (enableLocker) { ifContinueForceTrack = servoMotionForceTrackEnable; } if (ifContinueForceTrack) { double differenceForceZ = referenceForce[2] - (-refForce); if (Math.Abs(differenceForceZ) <= servoMotionMinAvailableForce) { forceDirectionZIncrement = 0.0; } else if (Math.Abs(differenceForceZ) >= servoMotionMaxAvailableForce) { forceDirectionZIncrement = Math.Sign(differenceForceZ) * servoMotionMaxIncrement; } else { forceDirectionZIncrement = Math.Sign(differenceForceZ) * ((Math.Abs(differenceForceZ) - servoMotionMinAvailableForce) / (servoMotionMaxAvailableForce - servoMotionMinAvailableForce) * (servoMotionMaxIncrement - servoMotionMinIncrement) + servoMotionMinIncrement); } nextTcpPosition[0] += (currentZAxisAtBase[0] * forceDirectionZIncrement); nextTcpPosition[1] += (currentZAxisAtBase[1] * forceDirectionZIncrement); nextTcpPosition[2] += (currentZAxisAtBase[2] * forceDirectionZIncrement); } // 记录数据 servoMotionRecordDatas.Add(new double[] { tcpRealPosition[0], tcpRealPosition[1], tcpRealPosition[2], tcpRealPosition[3], tcpRealPosition[4], tcpRealPosition[5], referenceForce[0], referenceForce[1], referenceForce[2], referenceForce[3], referenceForce[4], referenceForce[5], DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second, DateTime.Now.Millisecond, DateTime.Now.Hour * 3600 * 1000 + DateTime.Now.Minute * 60 * 1000 + DateTime.Now.Second * 1000 + DateTime.Now.Millisecond, refFlag }); return(nextTcpPosition); }