首页/文章/ 详情

C-NCAP 2027版低速后碰撞颈部保护(Whiplash)工况规程解读分析报告

3月前浏览1032

C-NCAP 2027版低速后碰撞颈部保护(Whiplash)工况规程解读分析报告


来源:檐苔
碰撞
著作权归作者所有,欢迎分享,未经许可,不得转载
首次发布时间:2026-06-29
最近编辑:3月前
青瓦松
硕士 签名征集中
获赞 46粉丝 13文章 63课程 0
点赞
收藏
作者推荐

ANSA二次开发:万向铰功能优化

上次发表的ANSA二次开发:万向铰的创建基本实现了万向铰的快速创建:选中万向铰两侧的所有点,然后自动生成RBE2和万向铰。本文在此基础上解决了如下问题:万向铰的一侧已存在RBE2的各种情况。当有RBE2的情况,只要选中RBE2上的任意一个节点就可选中RBE2上的所有节点。具体实现如下:from ansa import basefrom ansa import constantsfrom ansa import calcimport mathimport randomfrom typing import List, Tuple, Union, Iterable, Dict, Optionalclass Vector(object): """ 向量计算工具类。 提供常用的向量运算功能。 """ @classmethod def point2Point(cls, point1:Union[List[float], Tuple[float], base.Entity], point2:Union[List[float], Tuple[float], base.Entity], unit:bool=True)->List[float]: """ 计算两点构成的向量。 Args: point1: 第一个点坐标,可以是列表、元组或 Entity 对象 point2: 第二个点坐标,可以是列表、元组或 Entity 对象 unit: 是否返回单位向量,默认为 True Returns: List[float]: 两点构成的向量,若 unit 为 True 则返回单位向量 """ if isinstance(point1, base.Entity):point1 = point1.position if isinstance(point2, base.Entity):point2 = point2.position vect:List[float] = [p2-p1 for p1, p2 in zip(point1, point2)] return cls.unit(vect) if unit else vect @staticmethod def unit(vect:Union[List[float], Tuple[float]])->List[float]: """ 将一个向量单位化。 Args: vect: 输入向量,可以是列表或元组 Returns: List[float]: 单位向量 """ return calc.Normalize(vect) @staticmethod def distance(point1:Union[List[float], Tuple[float], base.Entity], point2:Union[List[float], Tuple[float], base.Entity] )->float: """ 计算两点的距离。 Args: point1: 第一个点坐标,可以是列表、元组或 Entity 对象 point2: 第二个点坐标,可以是列表、元组或 Entity 对象 Returns: float: 两点之间的距离 """ if isinstance(point1, base.Entity):point1 = point1.position if isinstance(point2, base.Entity):point2 = point2.position # 计算欧氏距离 return math.dist(point1, point2) @staticmethod def move(point:Union[List[float], Tuple[float], base.Entity], vect:Union[List[float], Tuple[float]], dist:float)->List[float]: """ 沿指定向量移动点。 Args: point: 点坐标,可以是列表、元组或 Entity 对象 vect: 移动方向向量 dist: 移动距离 Returns: List[float]: 移动后的点坐标 """ if isinstance(point, base.Entity):point = point.position return list(map(lambda p, v: p+dist*v, point, vect)) @staticmethod def getPointCenter(points:List[Union[List[float], Tuple[float], base.Entity]])->Tuple[float]: """ 计算输入点集 合的中心点。 Args: points: 点集 合,可以是列表、元组或 Entity 对象 Returns: Tuple[float]: 中心点坐标 (x, y, z) """ if not points: return (0.0, 0.0, 0.0) # 累计求和 xSum, ySum, zSum = 0.0, 0.0, 0.0 for point in points: if isinstance(point, base.Entity): point = point.position xSum += point[0] ySum += point[1] zSum += point[2] count:int = len(points) return (xSum/count, ySum/count, zSum/count)class ClusterPoints(object): """ 基于点的聚类分析工具。 使用二分K-Means算法将一组点分成两个簇。 """ def __init__(self, points:Iterable[base.Entity], singleClusterThrehold:float = 7.5, maxIterations:int=20 ): """ 初始化聚类分析器。 Args: points: 输入的实体点集 合 singleClusterThrehold: 簇间最小间隙阈值,用于判断是否为同一簇 maxIterations: 最大迭代次数 """ self.inputValidatedCheck(points) self.singleClusterThrehold = singleClusterThrehold self.maxIterations = maxIterations self.distCache:Dict[Tuple[int, int], float] = {} # 距离缓存,避免重复计算 def inputValidatedCheck(self, points:Iterable[base.Entity])->None: """ 输入验证和标准化。 Args: points: 输入的点集 合 Raises: TypeError: 输入不是列表或元组时抛出 ValueError: 点数量少于2时抛出 """ # 输入验证 if not isinstance(points, list) and not isinstance(points, tuple): raise TypeError('输入必须是一个列表或元组') if len(points)<2: raise ValueError('至少需要两个点才能进行聚类分析') # 验证并标准化点 self.points:List[base.Entity] = [point for point in points if isinstance(point, base.Entity)] self.numOfPoints:int = len(self.points) return None def getDistance(self, idx1:int, idx2:int)->float: """ 获取或计算两点间的距离。 Args: idx1: 第一个点的索引 idx2: 第二个点的索引 Returns: float: 两点之间的距离 """ if idx1==idx2: return 0.0 # 确保索引顺序一致 if idx1>idx2: idx1, idx2 = idx2, idx1 key = (idx1, idx2) try: dist = self.distCache[key] except KeyError: dist = math.dist(self.points[idx1].position, self.points[idx2].position) self.distCache[key] = dist return dist def calcCog(self, indices:Iterable[int])->Optional[Tuple[float]]: """ 快速计算输入下标对应节点构成的簇的中心点。 Args: indices: 节点索引集 合 Returns: Optional[Tuple[float]]: 中心点坐标 (x, y, z),若索引为空则返回 None """ if not indices: return None # 累计求和 xSum, ySum, zSum = 0.0, 0.0, 0.0 for idx in indices: pos = self.points[idx].position xSum += pos[0] ySum += pos[1] zSum += pos[2] count:int = len(indices) return (xSum/count, ySum/count, zSum/count) def calcDistToCenter(self, center1:Tuple[float], center2:Tuple[float], )->Tuple[List[float]]: """ 批量计算所有点到输入的名义中心点的距离。 Args: center1: 第一个中心点坐标 center2: 第二个中心点坐标 Returns: Tuple[List[float]]: (到center1的距离列表, 到center2的距离列表) """ distancesToCenter1:List[float] = [] distancesToCenter2:List[float] = [] # 预计算中心点到所有点的距离 # 注意:这里需要计算欧式距离,不能使用缓存 for idx in range(self.numOfPoints): if self.farthestPointIdx1==idx: distancesToCenter1.append(0.0) distancesToCenter2.append(math.dist(self.points[idx].position, center2)) elif self.farthestPointIdx2==idx: distancesToCenter1.append(math.dist(self.points[idx].position, center1)) distancesToCenter2.append(0.0) else: distancesToCenter1.append(math.dist(self.points[idx].position, center1)) distancesToCenter2.append(math.dist(self.points[idx].position, center2)) return (distancesToCenter1, distancesToCenter2) def calcClusterStats(self, indices:List[int])->Tuple[float]: """ 快速计算簇的统计信息:平均距离、最小距离、最大距离。 小簇(<=50点)计算所有点对,大簇使用采样估计。 Args: indices: 簇中点的索引列表 Returns: Tuple[float]: (平均距离, 最小距离, 最大距离) """ numOfIndices:int = len(indices) if numOfIndices<2: return 0.0, 0.0, 0.0 totalDist, minDist, maxDist = 0.0, math.inf, 0.0 count:int = 0 # 只计算部分点对,近似估计 if numOfIndices<=50: # 小簇,计算所有点对 for i, i_idx in enumerate(indices): for j in range(i+1, numOfIndices): j_idx = indices[j] dist = self.getDistance(i_idx, j_idx) totalDist += dist minDist = min(minDist, dist) maxDist = max(maxDist, dist) count += 1 else: # 大簇,采样估计 sampleSize:int = min(500, numOfIndices*(numOfIndices-1)//2) for _ in range(sampleSize): i = random.choice(indices) j = random.choice(indices) while i==j: j=random.choice(indices) dist = self.getDistance(i, j) totalDist += dist minDist = min(minDist, dist) maxDist = max(maxDist, dist) count += 1 return (totalDist/count if count>0 else 0.0, minDist if minDist<math.inf else 0.0, maxDist) def findFarthestPointsByBest(self)->Tuple[int]: """ 全局遍历获取距离最远的两个点。 Returns: Tuple[int]: 距离最远两个点的索引 """ maxDistance:float = -1.0 point1Idx, point2Idx = 0, 1 for i in range(self.numOfPoints): for j in range(i+1, self.numOfPoints): dist = self.getDistance(i, j) if dist>maxDistance: maxDistance = dist point1Idx, point2Idx = i, j return point1Idx, point2Idx def findFarthestPointToPoint(self, startIdx:int)->int: """ 找到离起点最远的点。 Args: startIdx: 起始点索引 Returns: int: 距离起始点最远的点索引 """ farthestFromStart:int = startIdx maxDist:float = -1.0 for i in range(self.numOfPoints): if i==startIdx:continue dist = self.getDistance(startIdx, i) if dist>maxDist: maxDist = dist farthestFromStart = i return farthestFromStart def findFarthestPoints(self)->Tuple[int]: """ 使用随机采样和三角形不等式找到近似最远的两个点。 算法原理: 1. 随机选择一个点作为起点 2. 找到离起点最远的点作为第一个候选点 3. 找到离第一个候选点最远的点作为第二个候选点 4. 重复几次找到更好的近似 Returns: Tuple[int]: 距离最远的两个点的索引 """ if self.numOfPoints<2: return (0, 0) # 如果点数较少,使用简单方法 if self.numOfPoints<=100: return self.findFarthestPointsByBest() # 对于大数据集,使用近似方法 bestDist:float = -1.0 bestPair:Tuple[int, int] = (0, 1) # 进行几次随机采样 for _ in range(min(5, self.numOfPoints//10)): # 随机选择一个起点 startIdx:int = random.randint(0, self.numOfPoints-1) # 找到离起始点最远的点 farthestFromStart:int = self.findFarthestPointToPoint(startIdx) # 找到离最远点最远的点 farthestFromFarthest:int = self.findFarthestPointToPoint(farthestFromStart) # 计算这对点的距离 dist = self.getDistance(farthestFromStart, farthestFromFarthest) if dist>bestDist: bestDist = dist bestPair = (farthestFromStart, farthestFromFarthest) return bestPair def initCluster(self): """ 初始化簇分配。 将点分配给距离最近的最远点对应的簇。 """ # 初始化簇分配 self.cluster1Indices = [self.farthestPointIdx1] self.cluster2Indices = [self.farthestPointIdx2] # 为剩余点分配初始簇 for idx in range(self.numOfPoints): if idx == self.farthestPointIdx1 or idx==self.farthestPointIdx2:continue dist1 = self.getDistance(idx, self.farthestPointIdx1) dist2 = self.getDistance(idx, self.farthestPointIdx2) if dist1<dist2: self.cluster1Indices.append(idx) else: self.cluster2Indices.append(idx) return None def iterOpti(self): """ 使用优化后的迭代策略进行簇分配优化。 迭代计算中心点并将点重新分配到最近的簇,直到收敛或达到最大迭代次数。 """ # 使用优化后的迭代策略 for _ in range(self.maxIterations): # 计算当前簇的中心点 center1 = self.calcCog(self.cluster1Indices) center2 = self.calcCog(self.cluster2Indices) # 如果某个簇为空,重新初始化 if center1 is None or center2 is None: self.farthestPointIdx1, self.farthestPointIdx2 = self.findFarthestPoints() self.cluster1Indices = [self.farthestPointIdx1] self.cluster2Indices = [self.farthestPointIdx2] continue # 批量计算到中心点的距离 distanceToCenter1, distanceToCenter2 = self.calcDistToCenter(center1, center2) # 根据与中心点的距离进行重新分配点到最近的簇 cluster1Indices = [self.farthestPointIdx1] cluster2Indices = [self.farthestPointIdx2] for i in range(self.numOfPoints): if i==self.farthestPointIdx1 or i==self.farthestPointIdx2:continue if distanceToCenter1[i]<distanceToCenter2[i]: cluster1Indices.append(i) else: cluster2Indices.append(i) # 检查是否收敛 if (set(self.cluster1Indices)==set(cluster1Indices)) and (set(self.cluster2Indices)==set(cluster2Indices)): break self.cluster1Indices = cluster1Indices self.cluster2Indices = cluster2Indices return None def rebuildResult(self): """ 构建返回结果。 根据索引构建对应的实体点列表,确保两个簇都不为空。 """ self.cluster1Points = [self.points[i] for i in self.cluster1Indices] self.cluster2Points = [self.points[i] for i in self.cluster2Indices] # 确保两个簇都不为空 if not self.cluster1Points and self.cluster2Points: self.cluster1Points.append(self.cluster2Points.pop()) elif self.cluster1Points and not self.cluster2Points: self.cluster2Points.append(self.cluster1Points.pop()) return None def isOneCluster(self): """ 判断是否只有一个簇。 根据簇内平均距离和簇间平均距离判断两个簇是否应该合并为一个簇。 Returns: Tuple[List, List, bool]: (所有点, 空列表, True) 如果是一个簇,否则返回 None """ # 使用快速方法判断是否只有一个簇 if self.numOfPoints<=50: # 小数据集:详细计算 avgDist1 = self.calcClusterStats(self.cluster1Indices)[0] avgDist2 = self.calcClusterStats(self.cluster2Indices)[0] # 计算簇间平均距离 interClusterAvg = 0.0 if self.cluster1Points and self.cluster2Points: # 采样计算簇间距离 sampleSize:int = min(100, len(self.cluster1Indices)*len(self.cluster2Indices)) for _ in range(sampleSize): i = random.choice(self.cluster1Indices) j = random.choice(self.cluster2Indices) interClusterAvg += self.getDistance(i, j) interClusterAvg /= sampleSize # 判断逻辑 # 如果簇间平局距离小于簇内平均距离则认为是一个簇 intraClusterAvg = max(avgDist1, avgDist2) if interClusterAvg<intraClusterAvg: allPoints = self.cluster1Points + self.cluster2Points return allPoints, [], True else: # 大数据集:简化判断 # 计算中心点距离 center1 = self.calcCog(self.cluster1Indices) center2 = self.calcCog(self.cluster2Indices) if center1 and center2: centerDist = math.dist(center1, center2) # 计算簇的大小 size1 = len(self.cluster1Indices) size2 = len(self.cluster2Indices) # 如果簇大小悬殊且中心点距离不大,可能是一个簇 if (max(size1, size2)) > 3*min(size1, size2) and centerDist<self.singleClusterThrehold: allPoints = self.cluster1Points + self.cluster2Points return allPoints, [], True return None def run(self): """ 执行聚类分析。 流程: 1. 找到近似最远的两个点作为初始种子点 2. 初始化簇分配 3. 迭代优化簇分配 4. 构建返回结果 5. 判断是否只有一个簇 Returns: Tuple[List, List, bool]: (簇1点列表, 簇2点列表, 是否只有一个簇) """ # 特殊情况处理 if self.numOfPoints==2: dist = self.getDistance(0, 1) if dist<self.singleClusterThrehold: return [self.points[0], self.points[1]], [], True else: return [self.points[0]], [self.points[1]], False # 步骤1:使用优化方法找到近似最远的两个点 self.farthestPointIdx1, self.farthestPointIdx2 = self.findFarthestPoints() # 步骤2:初始化簇分配 self.initCluster() # 步骤3:使用优化后的迭代策略 self.iterOpti() # 步骤4:构建返回结果 self.rebuildResult() # 步骤5:判断是否只有一个簇 result = self.isOneCluster() return result if result else (self.cluster1Points, self.cluster2Points, False)class JointBase(object): """ 关节基础类。 定义关节的通用属性和行为。 """ DECK:int = constants.LSDYNA rbe2Type:str = 'CONSTRAINED_NODAL_RIGID_BODY' def __init__(self, entType:str, nameCN:str=None): """ 初始化关节基础类。 Args: entType: 实体类型名称 nameCN: 中文名称(可选) """ self.entType:str = entType self.nameCN:str = nameCN self.masterNodes:List[base.Entity] = [] if nameCN: print(f'[INFO] 初始化关节类型:{self.nameCN}') @classmethod def createRbe2(cls, nodes:List[base.Entity], masterNode:base.Entity=None)->base.Entity: """ 创建 RBE2 刚性连接。 Args: nodes: 节点列表 masterNode: 主节点,若为 None 则自动创建位于重心处的节点 Returns: base.Entity: 创建的 CONSTRAINED_NODAL_RIGID_BODY 实体 """ print('[INFO]创建RBE2') setEnt:base.Entity = base.CreateEntity(cls.DECK, 'SET') base.AddToSet(setEnt, nodes) setEnt.set_entity_values(cls.DECK, {'Name': f'SET_NODE_{setEnt._id:010d}'}) if not masterNode: cog = base.cog(setEnt) masterNode = base.CreateEntity(cls.DECK, 'NODE', {'X': cog[0], 'Y': cog[1], 'Z':cog[2]}) base.AddToSet(setEnt, masterNode) fields = {'NSID':setEnt._id, 'MASTER':masterNode._id, 'No.of.Nodes':len(nodes)+1} return base.CreateEntity(cls.DECK, cls.rbe2Type, fields) @classmethod def getRbe2FromNode(cls, node:base.Entity)->Optional[base.Entity]: """ 根据输入的节点获取对应的 RBE2 实体。 Args: node: 节点实体 Returns: base.Entity: 对应的 RBE2 实体 """ if not isinstance(node, base.Entity) or node.ansa_type(cls.DECK)!='NODE': return None ents:Dict[base.Entity, List[base.Entity]] = base.NodesToElements(node)[node] rbe2List:List[base.Entity] = [ent for ent in ents if ent.ansa_type(cls.DECK)==cls.rbe2Type] if len(rbe2List)>=2: raise ValueError(f'[ERROR] 节点 {node._id} 上存在多个 RBE2 实体!') if len(rbe2List)==1: return rbe2List[0] return None @classmethod def getRbe2MasterNode(cls, rbe2:base.Entity)->Optional[base.Entity]: """ 从给定的 RBE2 实体中获取主节点。 Args: rbe2: RBE2 实体对象。 Returns: 主节点实体对象,或者None表示没有找到主节点。 """ if not isinstance(rbe2, base.Entity) or rbe2.ansa_type(cls.DECK)!=cls.rbe2Type: return None masterNode:base.Entity = rbe2.get_entity_values(cls.DECK, ['MASTER',])['MASTER'] if not isinstance(masterNode, base.Entity) or masterNode.ansa_type(cls.DECK)!='NODE': return None return masterNode @classmethod def getRbe2OtherNodes(cls, rbe2:base.Entity)->List[base.Entity]: """ 获取 RBE2 刚性单元的其他节点。 Args: rbe2: RBE2 刚性单元实体。 Returns: List[base.Entity]: 其他节点的列表。 """ if not isinstance(rbe2, base.Entity) or rbe2.ansa_type(cls.DECK)!=cls.rbe2Type: return [] masterNode:base.Entity = cls.getRbe2MasterNode(rbe2) nodes:List[base.Entity] = base.CollectEntities(cls.DECK, rbe2, 'NODE', recursive=True) if masterNode in nodes: nodes.remove(masterNode) return nodesclass UniversalJoint(JointBase): """ 万向铰关节类。 用于创建万向铰类型的连接。 """ def __init__(self): """ 初始化万向铰关节。 """ super().__init__('CONSTRAINED_JOINT_UNIVERSAL', nameCN='万向铰') self.pickTypes:Tuple[str] = ('ELEMENT_SHELL', 'ELEMENT_SOLID', self.rbe2Type) @classmethod def getAllNodes(cls, nodes:List[base.Entity])->List[base.Entity]: """ 获取所有节点。 Args: nodes: 节点列表。 Returns: 所有节点的列表。 """ rbe2List:List[base.Entity] = [] allNodes:List[base.Entity] = [] deleteEntities:List[base.Entity] = [] for node in nodes: if ((not isinstance(node, base.Entity)) or (node.ansa_type(cls.DECK)!='NODE') or (node in allNodes)): continue rbe2 = cls.getRbe2FromNode(node) if not rbe2: allNodes.append(node) continue rbe2List.append(rbe2) nodes = cls.getRbe2OtherNodes(rbe2) allNodes.extend(nodes) ents = base.CollectEntities(cls.DECK, rbe2, ['NODE', 'SET'], recursive=True) ents.append(rbe2) deleteEntities.extend(ents) base.DeleteEntity(deleteEntities, force=False) return allNodes def getNodesBy2Axis(self)->bool: """ 获取两轴上的节点。 通过用户交互选择两个轴上的所有节点,并提取端点。 """ print(f'[INFO] 请选择{self.nameCN}第一轴上的节点') axis1Nodes:List[base.Entity] = base.PickNodes(self.DECK, self.pickTypes) if not axis1Nodes: print(f'[WARNING] 未选择{self.nameCN}第一轴上的任何节点') return False print(f'[INFO] 请选择{self.nameCN}第二轴上的所有节点') axis2Nodes:List[base.Entity] = base.PickNodes(self.DECK, self.pickTypes) if not axis2Nodes: print(f'[WARNING] 未选择{self.nameCN}第二轴上的任何节点') return False axis1Nodes = self.getAllNodes(axis1Nodes) self.axis1Node1, self.axis1Node2, _ = self.getVertixByAxis(axis1Nodes) if not self.axis1Node1 or not self.axis1Node2: print(f'[WARNING] 未选择{self.nameCN}第一轴上的一端点未被选中') return False axis2Nodes = self.getAllNodes(axis2Nodes) self.axis2Node1, self.axis2Node2, _ = self.getVertixByAxis(axis2Nodes) if not self.axis2Node1 or not self.axis2Node2: print(f'[WARNING] 未选择{self.nameCN}第二轴上的一端点未被选中') return False return True @classmethod def getVertixByAxis(cls, nodes:List[base.Entity])->Tuple[List[base.Entity], List[base.Entity], bool]: """ 根据轴上的节点获取两个端点簇。 Args: nodes: 轴上的节点列表 Returns: Tuple[List, List, bool]: (簇1点列表, 簇2点列表, 是否只有一个簇) """ obj = ClusterPoints(nodes) return obj.run() @classmethod def createCenterNode(cls, nodes:List[base.Entity])->base.Entity: """ 创建位于节点集 合重心处的节点。 Args: nodes: 节点列表 Returns: base.Entity: 创建的节点实体 """ cog:Tuple[float] = Vector.getPointCenter(nodes) return base.CreateEntity(cls.DECK, 'NODE', {'X': cog[0], 'Y': cog[1],'Z': cog[2]}) @classmethod def getNode4(cls, node1:base.Entity, node2:base.Entity, node3:base.Entity)->base.Entity: """ 计算并创建第四个节点。 通过向量运算确定第四个节点的位置,用于构建万向铰。 算法原理: 1. vect1 = node1 → node2:确定第一轴方向 2. vect2 = node1 → node3:确定第二轴的参考方向 3. vect3 = vect1 × vect2:叉积得到垂直于两向量所在平面的法向量 4. vect4 = vect1 × (vect3/|vect3|):再次叉积,得到同时垂直于第一轴和法向量的向量,即第二轴方向 5. dist = |node1 - node3|:计算参考距离 6. node4 = node1 + dist × vect4:沿第二轴方向移动参考距离得到第四个节点 Args: node1: 原点节点 node2: 定义第一轴方向的节点 node3: 定义第二轴参考方向的节点 Returns: base.Entity: 创建的第四个节点实体 """ vect1:Tuple[float] = Vector.point2Point(node1, node2) vect2:Tuple[float] = Vector.point2Point(node1, node3) vect3:Tuple[float] = calc.CrossProduct(vect1, vect2) vect4:Tuple[float] = Vector.unit(calc.CrossProduct(vect1, Vector.unit(vect3))) dist:float = Vector.distance(node1, node3) pos:List[float] = Vector.move(node1, vect4, dist) return base.CreateEntity(cls.DECK, 'NODE', {'X': pos[0], 'Y': pos[1],'Z': pos[2]}) def run(self)->None: """ 执行万向铰创建流程。 Args: pickFlag: 选择模式标志,默认为2 """ flag:bool = self.getNodesBy2Axis() if not flag: return None node3:base.Entity = self.createCenterNode(self.axis1Node1) axis1MasterPos2:Tuple[float] = Vector.getPointCenter(self.axis1Node2) axis2MasterPos1:Tuple[float] = Vector.getPointCenter(self.axis2Node1) axis2MasterPos2:Tuple[float] = Vector.getPointCenter(self.axis2Node2) cog:Tuple[float] = Vector.getPointCenter([node3, axis1MasterPos2, axis2MasterPos1, axis2MasterPos2]) node1:base.Entity = base.CreateEntity(self.DECK, 'NODE', {'X': cog[0], 'Y': cog[1],'Z': cog[2]}) node2:base.Entity = base.CreateEntity(self.DECK, 'NODE', {'X': cog[0], 'Y': cog[1],'Z': cog[2]}) node4:base.Entity = self.getNode4(node1, node3, axis2MasterPos1) rbe1:base.Entity = self.createRbe2(self.axis1Node1+self.axis1Node2+[node3], node1) rbe2:base.Entity = self.createRbe2(self.axis2Node1+self.axis2Node2+[node4], node2) fields:Dict[str, any] = {'N1': node1, 'N2': node2, 'N3': node3, 'N4': node4} return base.CreateEntity(self.DECK, self.entType, fields)def main(): """ 主函数。 创建并运行万向铰。 """ jointObj = UniversalJoint() jointObj.run()if __name__ == '__main__': main()来源:檐苔

未登录
还没有评论
课程
培训
服务
行家
VIP会员 学习计划 福利任务
下载APP
联系我们
帮助与反馈