using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Numerics; namespace KinematicsBase { #region BaseClass [Serializable] public enum UnitType { mm, cm, m } [Serializable] public enum LimitType { Constant, NoLimits //,Variable } public enum JointType { /// /// 旋转 /// Revolute, /// /// 滑移 /// Prismatic } [Serializable] public class JointMaxValues { public JointMaxValues() { } public JointMaxValues(double speed, double acceleration) { Speed = speed; Acceleration = acceleration; } public double SpeedFromJointLimit(JointLimit jointLimit) { if (jointLimit.Interval <= 0.000000001) { Speed = 0; } else { Speed = (jointLimit.HighLimit - jointLimit.LowLimit) / (jointLimit.Interval / 1000f); } return Speed; } public double Speed { get; set; } public double Acceleration { get; set; } } [Serializable] public class JointLimit { public JointLimit() { } /// /// 创建JointLimit类构造方法 /// /// LimitType. /// 最小极限 double /// 最大极限 double public JointLimit(LimitType limitType, double lowLimit, double highLimit) { this.LimitType = limitType; this.LowLimit = lowLimit; this.HighLimit = highLimit; } public JointLimit(LimitType limitType, double lowLimit, double highLimit, int interval) { this.LimitType = limitType; this.LowLimit = lowLimit; this.HighLimit = highLimit; this.Interval = interval; } public LimitType LimitType { get; set; } public double LowLimit { get; set; } public double HighLimit { get; set; } /// /// 时间优先时候的时间,单位毫秒 /// public int Interval; } [Serializable] public class Joint { /// /// ModeId JointId value /// public static event Action OnDataChange = null; public static event Action OnDataChangeJointIsRun = null; //public static event Action UpdateJoint; public static void DataChange(string modeId, string id, object val) { if (OnDataChange != null) { OnDataChange.Invoke(modeId, id, val); } } public static void DataChangeJointIsRun(string modeId, string id, bool val) { if (OnDataChangeJointIsRun != null) { OnDataChangeJointIsRun.Invoke(modeId, id, val); } } public Joint() { GraphPosition = new System.Drawing.Point[2]; } public Joint(string id, string name, bool isDriving = true) { this.Id = id; this.Name = name; this.IsDriving = isDriving; //this.Valuefactor = 1; } public System.Drawing.Point[] GraphPosition { set; get; } public string Id { get; set; } public string Name { get; set; } public string ModelId { get; set; } /// /// 驱动轴 /// 联动时的主运动 /// public bool IsDriving { get; set; } public string ParentLinkId { get; set; } public string ChildLinkId { get; set; } /// /// 父模型代码 /// public string PId { get; set; } /// /// 子模型代码 /// public string CId { get; set; } public Axis Axis { get; set; } public JointType JointType { get; set; } public bool LockJoint { get; set; } public JointLimit JointLimit { get; set; } public JointMaxValues JointMaxValue { get; set; } /// /// 模型初始值 /// public double Value { get; set; } public bool FindJointById(Joint joint) { return Id == joint.Id; } /// /// 输入参数 /// public double ValueInput { get; set; } /// /// 倍率 1 /// public double ValueFactor { get; set; } = 1; /// /// 模型当前值 /// public double ValueCurrent { get; set; } public string Script; public bool IsScript; public bool IsOnlyHomePose; public static double GetJointPosition(Joint joint) { double val = -1; switch (joint.JointType) { case JointType.Prismatic: switch (joint.Axis.AxisFlag) { case AxisFlag.X: val = Convert.ToSingle(joint.Axis.Loaction.Position.X); break; case AxisFlag.Y: val = Convert.ToSingle(joint.Axis.Loaction.Position.Y); break; case AxisFlag.Z: val = Convert.ToSingle(joint.Axis.Loaction.Position.Z); break; } break; //一、绕定轴X-Y-Z旋转(RPY角) //二、绕动轴Z-Y-X旋转(Euler角) case JointType.Revolute: switch (joint.Axis.AxisFlag) { case AxisFlag.X: val = Convert.ToSingle(joint.Axis.Loaction.FixedAngle.R); break; case AxisFlag.Y: val = Convert.ToSingle(joint.Axis.Loaction.FixedAngle.P); break; case AxisFlag.Z: val = Convert.ToSingle(joint.Axis.Loaction.FixedAngle.Y); break; } break; } return val; } /// /// 计算位姿变换 /// /// 初始坐标doule[7] /// 沿着某个轴转,X/Y/Z/RX/RY/RZ /// 移动步长,转动单位弧度,移动单位与输入一致 /// 目标坐标doule[7] public PositionQuaternion TransformCoordinates(Joint joint, double step) { string along = GetJointAlong(joint); double[] initCoordinate = new double[7]; initCoordinate[0] = joint.Axis.LoactionQuaternion.Position.X; initCoordinate[1] = joint.Axis.LoactionQuaternion.Position.Y; initCoordinate[2] = joint.Axis.LoactionQuaternion.Position.Z; initCoordinate[3] = joint.Axis.LoactionQuaternion.Quaternion.X; initCoordinate[4] = joint.Axis.LoactionQuaternion.Quaternion.Y; initCoordinate[5] = joint.Axis.LoactionQuaternion.Quaternion.Z; initCoordinate[6] = joint.Axis.LoactionQuaternion.Quaternion.W; return TransformCoordinates(initCoordinate, along, step, joint.JointType); } public static string GetJointAlong(Joint joint) { string along = "X"; switch (joint.JointType) { case JointType.Prismatic: switch (joint.Axis.AxisFlag) { case AxisFlag.X: along = "X"; break; case AxisFlag.Y: along = "Y"; break; case AxisFlag.Z: along = "Z"; break; } break; //一、绕定轴X-Y-Z旋转(RPY角) //二、绕动轴Z-Y-X旋转(Euler角) case JointType.Revolute: switch (joint.Axis.AxisFlag) { case AxisFlag.X: along = "RX"; break; case AxisFlag.Y: along = "RY"; break; case AxisFlag.Z: along = "RZ"; break; } break; } return along; } /// /// 计算位姿变换 /// /// 初始坐标doule[7] /// 沿着某个轴转,X/Y/Z/RX/RY/RZ /// 移动步长,转动单位弧度,移动单位与输入一致 /// 目标坐标doule[7] static public PositionQuaternion TransformCoordinates(double[] initCoordinate, string along, double step, JointType jointType) { PositionQuaternion PoseLoactionQuaternion = new PositionQuaternion(); // 存储转换结果 //double[] res = new double[7]; if (jointType == JointType.Revolute) { step = step * Math.PI / 180; } var stepFloat = Convert.ToSingle(step); // 初始姿态 var initPos = new System.Numerics.Vector3(Convert.ToSingle(initCoordinate[0]), Convert.ToSingle(initCoordinate[1]), Convert.ToSingle(initCoordinate[2])); var initQua = new System.Numerics.Quaternion(Convert.ToSingle(initCoordinate[3]), Convert.ToSingle(initCoordinate[4]), Convert.ToSingle(initCoordinate[5]), Convert.ToSingle(initCoordinate[6])); var resPos = new System.Numerics.Vector3(); var resQua = new System.Numerics.Quaternion(); resPos = initPos; // 转动或移动 switch (along.ToUpper()) { case "X": { resPos.X += stepFloat; resQua = initQua; break; } case "Y": { resPos.Y += stepFloat; resQua = initQua; break; } case "Z": { resPos.Z += stepFloat; resQua = initQua; break; } case "RX": { resPos = initPos; var quaTrans = System.Numerics.Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), stepFloat); resQua = System.Numerics.Quaternion.Multiply(initQua, quaTrans); break; } case "RY": { resPos = initPos; var quaTrans = System.Numerics.Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), stepFloat); resQua = System.Numerics.Quaternion.Multiply(initQua, quaTrans); break; } case "RZ": { resPos = initPos; var quaTrans = System.Numerics.Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), stepFloat); resQua = System.Numerics.Quaternion.Multiply(initQua, quaTrans); break; } } //res[0] = resPos.X/1000; //res[1] = resPos.Y/1000; //res[2] = resPos.Z/1000; //res[3] = resQua.X; //res[4] = resQua.Y; //res[5] = resQua.Z; //res[6] = resQua.W; PoseLoactionQuaternion.Position.X = resPos.X / 1000; PoseLoactionQuaternion.Position.Y = resPos.Y / 1000; PoseLoactionQuaternion.Position.Z = resPos.Z / 1000; PoseLoactionQuaternion.Quaternion.X = resQua.X; PoseLoactionQuaternion.Quaternion.Y = resQua.Y; PoseLoactionQuaternion.Quaternion.Z = resQua.Z; PoseLoactionQuaternion.Quaternion.W = resQua.W; return PoseLoactionQuaternion; } #region Method //public static void JointListRemove(List JointList,ListJointListOld) //{ // if (JointListOld == null) return; // foreach(var item in JointListOld) // { // int index = JointList.FindIndex(t => t.Id == item.Id); // if (index >= 0) // { // JointList.RemoveAt(index); // } // } //} ///// ///// 将设备JointList加入系统列表 ///// ///// ///// //public static void JointListViewAddAndUpdate(List JointList, List jointList) //{ // int index; // foreach (var item in jointList) // { // index = JointList.FindIndex(t => t.Id == item.Id); // if (index > -1) // { // JointList.RemoveAt(index); // item.ValueCurrent = item.Value; // JointList.Add(item); // Joint.DataChange(item.Id, item.Value); // } // else // { // item.ValueCurrent = item.Value; // JointList.Add(item); // Joint.DataChange(item.Id, item.Value); // } // } //} #endregion ///// ///// 当前实际位置 ///// //public PositionFixedAngle PositionCurrent { get; set; } ///// ///// 根据输入值和倍率计算模型当前位置 ///// ///// ///// //public PositionFixedAngle GetPositionCurrent(double ValueInput) //{ // Value = Value * ValueFactor; // this.ValueInput = ValueInput; // PositionCurrent.Position.X = Axis.Loaction.Position.X + positionNormalMatrix.x * Value; // PositionCurrent.Position.Y = Axis.Loaction.Position.Y + positionNormalMatrix.y * Value; // PositionCurrent.Position.Z = Axis.Loaction.Position.Z + positionNormalMatrix.z * Value; // PositionCurrent.FixedAngle.R = Axis.Loaction.FixedAngle.R + positionNormalMatrix.rx * Value; // PositionCurrent.FixedAngle.P = Axis.Loaction.FixedAngle.P + positionNormalMatrix.ry * Value; // PositionCurrent.FixedAngle.Y = Axis.Loaction.FixedAngle.Y + positionNormalMatrix.rz * Value; // return PositionCurrent; //} ///// ///// 根据界面数据,给位置变换标准矩阵赋值 ///// ///// //public PositionNormalMatrix SetPositionNormalMatrix() //{ // positionNormalMatrix.x =0; // positionNormalMatrix.y =0; // positionNormalMatrix.z = 0; // positionNormalMatrix.rx = 0; // positionNormalMatrix.ry = 0; // positionNormalMatrix.rz = 0; // switch (JointType) // { // case JointType.Revolute: // switch (Axis.AxisFlag) // { // case AxisFlag.X: // positionNormalMatrix.rx = 1; // break; // case AxisFlag.Y: // positionNormalMatrix.ry = 1; // break; // case AxisFlag.Z: // positionNormalMatrix.rz = 1; // break; // } // break; // case JointType.Prismatic: // switch (Axis.AxisFlag) // { // case AxisFlag.X: // positionNormalMatrix.x = 1; // break; // case AxisFlag.Y: // positionNormalMatrix.y = 1; // break; // case AxisFlag.Z: // positionNormalMatrix.z = 1; // break; // } // break; // } // switch (Axis.Flip) // { // case 1: // positionNormalMatrix.x = -positionNormalMatrix.x; // positionNormalMatrix.y = -positionNormalMatrix.y; // positionNormalMatrix.z = -positionNormalMatrix.z; // positionNormalMatrix.rx = -positionNormalMatrix.rx; // positionNormalMatrix.ry = -positionNormalMatrix.rx; // positionNormalMatrix.rz = -positionNormalMatrix.rx; // break; // } // return positionNormalMatrix; //} } #endregion }