尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
python的机器人基础原理工业场景模拟第十七篇:产线仿真,修改连杆质心位置,基于动力学术解,统计质心偏移对关节力矩的影响。
《Python机器人基础原理》第十七篇产线仿真——修改连杆质心位置基于动力学术解统计质心偏移对关节力矩的影响1. 实际工业应用场景周三夜班某3C电子装配产线的例行保养窗口。一台4-DOF垂直关节装配机械臂3旋转1垂直平移负责将手机中框从传送带拾取并放置到测试治具中。机器人构型大臂长500 mm小臂长350 mm第三旋转关节腕部俯仰偏置距0 mmz轴垂直行程±150 mm。关节硬件限位θ₁ ±175°、θ₂ ±150°、θ₃ ±150°、d₄ ±150 mm。连杆质量大臂3.5 kg质心距基座0.22 m小臂2.0 kg质心距肘部0.15 m腕部0.8 kg质心距腕关节0.30 m即距肘部0.65 m——腕部模块本身较长末端真空吸盘手机中框负载2.0 kg。额定负载3 kg。保养时维修工拆下小臂进行清洁重新安装时把末端气管支架从原来的内侧位置挪到了外侧——为了走线更顺。没人注意到这个细节。周四早班第一件产品中框放歪了0.6 mm卡进治具时刮伤了边框。小李接到品质异常通知赶到现场。他检查了吸盘真空度——正常。检查了视觉对位——正常。检查了传送带定位——正常。手动慢速模式下没问题他对旁边的新员工说但自动模式下节拍一拉起来第二轴在换向段就开始抖放下去的位置就不对了。新员工翻了翻保养记录昨晚拆过小臂做清洁。小臂拆过……小李调出伺服驱动器的实时力矩曲线第二轴的峰值力矩从原来的14.2 N·m跳到了15.7 N·m。小臂质量没变——还是2.0 kg。但质心位置可能偏了。质心偏了也会影响当然。重力力矩 质量×力臂×重力。质量不变力臂变了——气管支架从内侧挪到外侧小臂质心外移了大概4 cm。重力力矩增量 2.0×9.81×0.04 ≈ 0.78 N·m。加上惯性项里com₂²项的变化和科氏力项h里com₂的线性变化总增量大约1.5 N·m左右。控制器里的前馈模型还是旧质心参数补偿力矩偏了伺服在高速换向时靠反馈PID硬追就出现跟踪误差了。那第三轴呢第三轴在质点模型下重力项含m₃·com₃ m₄·(com₃L₂偏置)——小臂质心com₂的变化不通过L₂传递所以第三轴重力矩基本不受影响。但前馈失准导致的第二轴跟踪误差会传递到末端最终变成定位偏位。小李打开笔记本电脑我需要做一个质心偏移仿真把小臂质心从0.15 m逐步偏移到0.25 m观察各关节力矩的变化趋势。仿真能解释其中一部分——重力项约0.78 N·m惯性/科氏项约0.4 N·m剩下约0.3 N·m可能是装配残余应力或摩擦变化。确认质心偏移是不是主因。本篇解决的问题基于拉格朗日动力学方程 τ M(q)q¨ C(q,q˙)q˙ G(q)在固定轨迹下系统性地修改连杆质心位置参数大臂、小臂、腕部仿真各关节力矩随质心偏移的变化趋势。量化质心偏移对关节负载的影响程度为产线维护后的参数校准提供依据。本篇将连杆视为集中质量质点模型明确声明质心坐标定义的一致性。⚠️ 声明本篇全部代码为课程离线仿真运行在普通PC上用于连杆质心偏移对关节力矩影响的敏感性分析。不可直接用于真实机器人控制器、伺服驱动器或装配产线。真实工业现场需结合在线参数辨识、关节扭矩传感器反馈与安全监控。代码作者不对直接使用本代码于真实设备造成的任何后果负责。2. 痛点分析课程模块 本篇对应的工程痛点第4章 机器人动力学建模 → 4.2 连杆坐标系与D-H参数 连杆质心位置是动力学计算的核心输入安装偏移直接导致力臂变化第4章 → 4.4 关节空间动力学方程 τ M(q)q¨ C(q,q˙)q˙ G(q) 重力项G(q)与质心位置线性相关惯性矩阵M(q)含com²非线性项第5章 机器人关节驱动与控制 → 5.3 前馈补偿 质心偏移导致前馈模型力臂参数失准补偿力矩偏差第7章 机器人非线性控制 → 7.2 自适应控制 质心变化属于慢时变不确定性需要定期重新标定本篇代码解决 L3 离线参数敏感性分析层。输入不同质心位置参数组合输出各关节力矩随质心偏移的变化曲线。代码不是设备实时控制器不做伺服闭环不做在线参数辨识。它做的事情是在离线环境中量化质心偏移→力矩变化的映射关系告诉维护工程师气管支架挪了个位置力矩会偏多少需不需要重新标定。不覆盖完整6轴动力学、摩擦力辨识、实时自适应控制律、力控制。3. 核心逻辑讲解物理直觉你提过水桶吗水桶里的水一样重但你把手从桶边移到桶底提——感觉完全不一样。不是重量变了是力臂变了。机械臂也一样。小臂质量还是2.0 kg但气管支架从内侧挪到外侧质心外移了4 cm。第二轴要多花力气支撑这个偏移的力臂。更关键的是质心位置还出现在惯性矩阵的交叉项里——M₁₂ m₂·(com₂² L₁·com₂·cosθ₂)com₂变大惯性耦合增强第一轴加速时通过M₁₂传递给第二轴的耦合力矩也变大。业务逻辑 → 代码映射输入基准质心参数 质心偏移范围如小臂com₂从0.15→0.25 m↓步骤1生成N组质心参数组合单变量扫描↓步骤2对每组参数在固定梯形轨迹下运行动力学求解↓步骤3记录各关节的峰值力矩τ_M峰值、τ_C峰值、τ_G峰值、τ_total峰值↓步骤4绘制力矩 vs 质心偏移曲线叠加线性拟合线展示非线性偏离↓步骤5计算灵敏度系数每cm偏移引起的力矩变化量单位N·m/m↓步骤6输出对比图表关键公式文字翻译重力项 G(q) 与质心的关系τ_G2 -g·[m₂·com₂·cos(θ₁θ₂) m₃·com₃·cos(θ₁θ₂θ₃) m₄·(com₃L₂)·cos(θ₁θ₂θ₃)]。com₂出现在第一项——小臂质心越远第二轴重力力矩越大。线性关系。惯性矩阵 M(q) 与质心的关系M₁₁中 m₂·com₂² 项随com₂平方增长非线性。M₁₂中 m₂·L₁·com₂·cosθ₂ 项随com₂线性增长。这意味着质心偏移对惯性项的影响比重力项更复杂——小偏移时近似线性大偏移时平方项开始主导。科氏力项与质心的关系h m₂·L₁·com₂ (m₃m₄)·L₁·L₂。com₂增大→h增大→科氏力矩线性增大。高速时影响显著。第三轴重力项与质心的关系τ_G3 -g·[m₃·com₃ m₄·(com₃L₂)]·cos(θ₁θ₂θ₃)。com₃从腕关节量起m₃和m₄的重力臂都通过com₃传递。这与M₃₃ m₃·com₃² m₄·(com₃L₂)²中的坐标定义一致——本篇统一com₃从第三轴腕关节量起。总结重力项和科氏项与质心位置线性相关惯性矩阵中的com₂²项带来非线性效应。小偏移5 cm时近似线性大偏移时需要完整仿真。单位力矩 N·m质心位置 m力臂 m角速度 rad/s。4. OOP代码实现技术栈严格限定numpy, scipy, matplotlib。不引入pybullet、roboticstoolbox等任何第三方机器人库。项目结构树robot_com_sensitivity_sim/├── run_com_sensitivity_sim.py├── requirements.txt├── dynamics/│ ├── __init__.py│ ├── models.py│ ├── trajectory.py│ ├── dynamics_solver.py│ └── visualize.py├── tests/│ ├── __init__.py│ └── test_com_sensitivity_sim.py└── results/核心源码dynamics/models.py — dataclass数据模型4-DOF垂直关节装配机械臂数据模型连杆参数、质量、质心位置、关节限位、重力常量构型说明3旋转1垂直平移θ1: 基座偏航, θ2: 肘部偏航, θ3: 腕部俯仰, d4: z轴升降质心坐标定义全局统一- com₁: 大臂质心距基座关节沿连杆方向的距离 (m)- com₂: 小臂质心距肘部关节沿连杆方向的距离 (m)- com₃: 腕部质心距腕关节第三轴沿连杆方向的距离 (m)- 末端负载质心默认在腕关节处 (com₄0)from dataclasses import dataclass, fieldfrom typing import List, Tuple, Optionalimport numpy as npdataclassclass JointLimit:单关节硬件限位min_val: floatmax_val: floatjoint_name: str def __post_init__(self):if self.min_val self.max_val:raise ValueError(fJointLimit: min_val({self.min_val})必须严格小于fmax_val({self.max_val}))if not np.isfinite(self.min_val) or not np.isfinite(self.max_val):raise ValueError(JointLimit: 限位值必须为有限数值)def contains(self, value: float) - bool:return (self.min_val - 1e-10) value (self.max_val 1e-10)dataclassclass JointLimitSet:4-DOF垂直关节装配机械臂关节限位集合limits: List[JointLimit]def __post_init__(self):if len(self.limits) ! 4:raise ValueError(f需要4个关节限位, 实际{len(self.limits)}个)classmethoddef default_4dof_assembly(cls):默认4-DOF垂直关节装配机械臂限位θ1: ±175° θ2: ±150° θ3: ±150° d4: ±150 mmpi 3.141592653589793return cls(limits[JointLimit(-175 * pi / 180, 175 * pi / 180, joint1_base_yaw),JointLimit(-150 * pi / 180, 150 * pi / 180, joint2_elbow_yaw),JointLimit(-150 * pi / 180, 150 * pi / 180, joint3_wrist_pitch),JointLimit(-0.150, 0.150, joint4_z_lift),])def check_all_with_indices(self, joint_values: List[float]) - Tuple[bool, List[int]]:if len(joint_values) ! 4:raise ValueError(f需要4个关节值, 实际{len(joint_values)}个)all_pass Trueviolation_indices []for i, (val, limit) in enumerate(zip(joint_values, self.limits)):if not limit.contains(val):all_pass Falseviolation_indices.append(i)return all_pass, violation_indicesdataclassclass LinkMassProps:连杆质量与质心属性mass: 质量 (kg)com_x: 质心沿连杆方向距近端关节的距离 (m)com_y, com_z: 垂直于连杆方向的质心偏移 (m)本篇质点模型设为0link_name: 连杆标识max_com_x: 质心允许的最大x值由调用方传入连杆长度上限质心坐标定义统一com_x 为沿连杆方向距近端关节的距离。- 大臂距基座关节- 小臂距肘部关节- 腕部距腕关节第三轴mass: floatcom_x: floatcom_y: floatcom_z: floatlink_name: str max_com_x: Optional[float] None # 连杆长度上限None表示不校验def __post_init__(self):if self.mass 0:raise ValueError(fLinkMassProps: 质量不能为负, 实际{self.mass})for name, val in [(com_x, self.com_x), (com_y, self.com_y),(com_z, self.com_z)]:if not np.isfinite(val):raise ValueError(fLinkMassProps.{name}必须为有限数值)# 质心位置合理性校验不能超出连杆长度if self.max_com_x is not None and self.com_x self.max_com_x:raise ValueError(fLinkMassProps({self.link_name}): 质心x{self.com_x}m f超出连杆长度上限{self.max_com_x}m)dataclassclass MassPropertySet:完整连杆质量属性集合link_props: List[LinkMassProps]link_lengths: List[float] field(default_factorylambda: [0.0, 0.0, 0.0, 0.0])def __post_init__(self):if len(self.link_props) ! 4:raise ValueError(f需要4个连杆质量属性, 实际{len(self.link_props)}个)# 交叉校验质心不能超出对应连杆长度for i, (prop, length) in enumerate(zip(self.link_props, self.link_lengths)):if length 0 and prop.com_x length:raise ValueError(f连杆{i}({prop.link_name}): 质心{prop.com_x}m超出长度{length}m)classmethoddef default_assembly_arm(cls):4-DOF垂直关节装配机械臂质量参数大臂: 3.5 kg, 质心距基座0.22 m (L10.50m)小臂: 2.0 kg, 质心距肘部0.15 m (L20.35m)腕部: 0.8 kg, 质心距腕关节0.30 m (腕部模块长0.35m)末端执行器手机中框: 吸盘0.3 kg 中框1.7 kg 2.0 kg, com0link_lengths [0.50, 0.35, 0.35, 0.0]props [LinkMassProps(3.5, 0.22, 0.0, 0.0, link1_upper_arm, link_lengths[0]),LinkMassProps(2.0, 0.15, 0.0, 0.0, link2_forearm, link_lengths[1]),LinkMassProps(0.8, 0.30, 0.0, 0.0, link3_wrist, link_lengths[2]),LinkMassProps(2.0, 0.0, 0.0, 0.0, link4_end_effector, None),]return cls(link_propsprops, link_lengthslink_lengths)def copy_with_modified_com(self, link_index: int, new_com_x: float):返回修改后的质心属性副本不修改原对象link_index: 0大臂, 1小臂, 2腕部, 3末端new_com_x: 新的质心x坐标 (m)new_props []for i, prop in enumerate(self.link_props):if i link_index:new_props.append(LinkMassProps(prop.mass, new_com_x, prop.com_y, prop.com_z,prop.link_name, prop.max_com_x))else:new_props.append(LinkMassProps(prop.mass, prop.com_x, prop.com_y, prop.com_z,prop.link_name, prop.max_com_x))return MassPropertySet(link_propsnew_props, link_lengthsself.link_lengths)dataclassclass DHParam:标准D-H参数theta: floatd: floata: floatalpha: floatdef __post_init__(self):for name, val in [(theta, self.theta), (d, self.d),(a, self.a), (alpha, self.alpha)]:if not np.isfinite(val):raise ValueError(fDHParam.{name}必须为有限数值)dataclassclass RobotParams:4-DOF垂直关节装配机械臂完整参数大臂500mm, 小臂350mm, 第三轴偏置0mm, d4250mm基座高links: List[DHParam]joint_names: List[str] field(default_factorylambda: [joint1_base_yaw, joint2_elbow_yaw,joint3_wrist_pitch, joint4_z_lift])g: float 9.81classmethoddef default_assembly_arm(cls):links [DHParam(0.0, 0.250, 0.500, 0.0),DHParam(0.0, 0.0, 0.350, 0.0),DHParam(0.0, 0.0, 0.0, 0.0),DHParam(0.0, 0.0, 0.0, 0.0),]return cls(linkslinks)dynamics/trajectory.py — 独立梯形速度轨迹生成器修复三角形分支超调bug独立梯形速度轨迹生成器各关节按位移比例独立计算加速/匀速/减速时长修复三角形轨迹加速减速即覆盖全位移时 t_const 强制为0命名IndependentTrapezoidalTrajectory各关节参数独立import numpy as npclass IndependentTrapezoidalTrajectory:独立梯形速度轨迹每个关节根据自身位移独立计算梯形参数保证所有关节在各自时间内精确到达目标无超调、无速度反向def __init__(self, q_start, q_end, total_time, max_velocity, max_acceleration):q_start: 起始关节角度 [θ1, θ2, θ3, d4]q_end: 终止关节角度total_time: 总运动时间 (s)max_velocity: 峰值关节角速度上限 (rad/s)max_acceleration: 峰值关节角加速度上限 (rad/s²)self.q_start np.array(q_start, dtypefloat)self.q_end np.array(q_end, dtypefloat)self.total_time total_timeself.max_velocity max_velocityself.max_acceleration max_accelerationself.delta_q self.q_end - self.q_startself.joint_params []for i in range(4):dq self.delta_q[i]if abs(dq) 1e-10:self.joint_params.append({v_max: 0.0, a_max: 0.0,t_acc: 0.0, t_const: total_time,t_dec: 0.0, direction: 1.0})continuedirection 1.0 if dq 0 else -1.0abs_dq abs(dq)t_acc_theory max_velocity / max_accelerationif 2 * t_acc_theory total_time:v_candidate max_velocityt_acc t_acc_theoryt_dec t_acc_theoryt_const total_time - t_acc - t_dec# 校验加速段位移 减速段位移 是否足够覆盖总位移accel_dist 0.5 * v_candidate * t_accdecel_dist 0.5 * v_candidate * t_decconst_dist v_candidate * t_const if t_const 0 else 0.0if accel_dist const_dist decel_dist abs_dq - 1e-6:# 位移太大需要降低速度# 先尝试三角形轨迹t_half np.sqrt(abs_dq / max_acceleration)if 2 * t_half total_time:t_half total_time / 2.0v_triangle max_acceleration * t_halft_acc_new t_halft_dec_new t_halft_const_new total_time - 2 * t_halfif t_const_new 0:t_const_new 0.0v_candidate v_trianglet_acc t_acc_newt_dec t_dec_newt_const t_const_newelif accel_dist decel_dist abs_dq - 1e-6:# 加速减速已足够覆盖位移这是三角形轨迹# 重新计算精确的 t_half 使 0.5*a*t² 0.5*a*t² abs_dqt_half np.sqrt(abs_dq / max_acceleration)v_candidate max_acceleration * t_halft_acc t_halft_dec t_halft_const 0.0 # 关键修复三角形轨迹无匀速段else:# 总时间不够完整梯形退化为三角形t_half total_time / 2.0v_candidate max_acceleration * t_halft_acc t_halft_dec t_halft_const 0.0self.joint_params.append({v_max: direction * v_candidate,a_max: direction * max_acceleration,t_acc: t_acc,t_const: t_const,t_dec: t_dec,direction: direction})def evaluate(self, t):在时刻t计算关节位置、速度、加速度if t 0:return self.q_start.copy(), np.zeros(4), np.zeros(4)if t self.total_time:return self.q_end.copy(), np.zeros(4), np.zeros(4)q np.zeros(4)q_dot np.zeros(4)q_ddot np.zeros(4)for i in range(4):dq self.delta_q[i]if abs(dq) 1e-10:q[i] self.q_start[i]continueparams self.joint_params[i]v_max params[v_max]a_max params[a_max]t_acc params[t_acc]t_const params[t_const]t_dec params[t_dec]if t t_acc:# 加速段q_ddot[i] a_maxq_dot[i] a_max * tq[i] self.q_start[i] 0.5 * a_max * t**2elif t t_acc t_const:# 匀速段三角形轨迹时 t_const0此分支不进入q_ddot[i] 0.0q_dot[i] v_maxq[i] (self.q_start[i] 0.5 * a_max * t_acc**2 v_max * (t - t_acc))elif t t_acc t_const t_dec:# 减速段t_dec_elapsed t - t_acc - t_consta_dec -abs(a_max) * params[direction]q_ddot[i] a_decq_dot[i] v_max a_dec * t_dec_elapsedq[i] (self.q_start[i] 0.5 * a_max * t_acc**2 (v_max * t_const if t_const 0 else 0.0) v_max * t_dec_elapsed 0.5 * a_dec * t_dec_elapsed**2)else:q[i] self.q_end[i]q_dot[i] 0.0q_ddot[i] 0.0return q, q_dot, q_ddotdef generate_trajectory_array(self, dt0.01):生成完整轨迹数组times np.arange(0, self.total_time dt, dt)n len(times)q_array np.zeros((n, 4))q_dot_array np.zeros((n, 4))q_ddot_array np.zeros((n, 4))for i, t in enumerate(times):q, qd, qdd self.evaluate(t)q_array[i, :] qq_dot_array[i, :] qdq_ddot_array[i, :] qddreturn times, q_array, q_dot_array, q_ddot_arraydynamics/dynamics_solver.py — 动力学求解器核心业务类动力学求解器计算惯性项、科氏力/离心力项、重力项支持修改连杆质心位置参数仿真质心偏移对各关节力矩的影响τ M(q)q¨ C(q,q˙)q˙ G(q)本篇将连杆视为集中质量质点模型忽略绕质心转动惯量。4-DOF垂直关节臂前3个旋转关节参与平面内动力学第4关节为z平移。质心坐标定义与models.py统一- com₁: 大臂质心距基座关节沿连杆方向 (m)- com₂: 小臂质心距肘部关节沿连杆方向 (m)- com₃: 腕部质心距腕关节第三轴沿连杆方向 (m)- 末端负载质心默认在腕关节处物理声明- 第三轴重力项 τ_G3 -g·[m₃·com₃ m₄·(com₃L₂)]·cos(θ₁θ₂θ₃)与 M₃₃ m₃·com₃² m₄·(com₃L₂)² 使用同一com₃定义距腕关节- 第三轴与θ₁θ₂的科氏耦合在质点共线假设下忽略τ_C30- 小臂质心com₂变化不影响τ_G3力臂走L₂不经过com₂import numpy as npfrom dynamics.models import RobotParams, MassPropertySetclass DynamicsSolver:基于拉格朗日方程的3旋转1平移垂直关节臂动力学求解器输入4关节状态前3个旋转关节参与M/C/G计算z平移关节关节4仅产生轴向力不影响旋转关节力矩注意每次修改质量/质心参数后必须创建新的DynamicsSolver实例因为__init__中缓存了h等派生参数。classmethoddef from_mass_props(cls, params: RobotParams, mass_props: MassPropertySet):工厂方法从参数创建求解器推荐用于参数扫描return cls(params, mass_props)def __init__(self, params: RobotParams, mass_props: MassPropertySet):self.params paramsself.mass_props mass_propsself.g params.g# 提取参数self.L1 params.links[0].aself.L2 params.links[1].aself.m1 mass_props.link_props[0].massself.m2 mass_props.link_props[1].massself.m3 mass_props.link_props[2].massself.m4 mass_props.link_props[3].massself.com1 mass_props.link_props[0].com_xself.com2 mass_props.link_props[1].com_xself.com3 mass_props.link_props[2].com_x# 科氏力耦合系数 h m₂·L₁·com₂ (m₃m₄)·L₁·L₂# com₂增大→h增大→科氏力矩线性增大self.h (self.m2 * self.L1 * self.com2 (self.m3 self.m4) * self.L1 * self.L2)def inertia_matrix(self, theta2, theta3):计算3×3惯性矩阵 M(q)com₂出现在M11的com₂²项和M12的com₂线性项中非线性线性混合com₃从腕关节量起M₃₃ m₃·com₃² m₄·(com₃L₂)²c2 np.cos(theta2)c23 np.cos(theta2 theta3)# M11 m₁·com₁² m₂·(L₁²com₂²2L₁·com₂·cosθ₂)# (m₃m₄)·(L₁²L₂²2L₁·L₂·cos(θ₂θ₃))M11 (self.m1 * self.com1**2 self.m2 * (self.L1**2 self.com2**2 2*self.L1*self.com2*c2) (self.m3 self.m4) * (self.L1**2 self.L2**2 2*self.L1*self.L2*c23))# M12 m₂·(com₂²L₁·com₂·cosθ₂)# (m₃m₄)·(L₂²L₁·L₂·cos(θ₂θ₃))M12 (self.m2 * (self.com2**2 self.L1*self.com2*c2) (self.m3 self.m4) * (self.L2**2 self.L1*self.L2*c23))M13 0.0 # 第三轴与前两轴在质点模型下无惯性耦合# M22 m₂·com₂² (m₃m₄)·L₂²M22 self.m2 * self.com2**2 (self.m3 self.m4) * self.L2**2M23 0.0# M₃₃ m₃·com₃² m₄·(com₃L₂)²# com₃从腕关节量起与G3定义一致M33 self.m3 * self.com3**2 self.m4 * (self.com3 self.L2)**2return np.array([[M11, M12, M13],[M12, M22, M23],[M13, M23, M33]], dtypefloat)def coriolis_vector(self, theta2, theta3, theta1_dot, theta2_dot, theta3_dot):计算科氏力/离心力向量 τ_C C(q,q˙)·q˙质点模型共线假设下第三轴与前两轴无科氏耦合τ_C30s2 np.sin(theta2)tau_C1 -self.h * s2 * (2 * theta1_dot * theta2_dot theta2_dot**2)tau_C2 self.h * s2 * theta1_dot**2tau_C3 0.0return np.array([tau_C1, tau_C2, tau_C3], dtypefloat)def gravity_vector(self, theta1, theta2, theta3):计算重力项向量 G(q)τ_G3 -g·[m₃·com₃ m₄·(com₃L₂)]·cos(θ₁θ₂θ₃)com₃从腕关节量起与M₃₃定义一致小臂质心com₂变化不影响τ_G3c1 np.cos(theta1)c12 np.cos(theta1 theta2)c123 np.cos(theta1 theta2 theta3)# τ_G1 -g·[m₁·com₁·cosθ₁ m₂·(L₁·cosθ₁com₂·cos(θ₁θ₂))# m₃·(L₁·cosθ₁L₂·cos(θ₁θ₂θ₃)com₃·cos(θ₁θ₂θ₃))# m₄·(L₁·cosθ₁L₂·cos(θ₁θ₂θ₃)(com₃L₂)·cos(θ₁θ₂θ₃))]tau_G1 -self.g * (self.m1 * self.com1 * c1 self.m2 * (self.L1 * c1 self.com2 * c12) self.m3 * (self.L1 * c1 self.L2 * c123 self.com3 * c123) self.m4 * (self.L1 * c1 self.L2 * c123 (self.com3 self.L2) * c123))# τ_G2 -g·[m₂·com₂·cos(θ₁θ₂)# m利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛
RELATED

相关推荐

Vant表单校验报错 ‘reduce of undefined‘ 的根因与修复

Vant表单校验报错 ‘reduce of undefined‘ 的根因与修复

如果你在用 Vant UI 做移动端表单,点击提交按钮的一瞬间,控制台突然冒出一句TypeError: Cannot read property reduce of undefined,先别急着去改代码。这个报错看起来像是 Vant 内部某个库函数的 bug,但绝大多数情况下&#xff0…

📅 2026/10/14 10:46:29
CheXpert胸片数据集:不确定性标签与多标签分类实战解析

CheXpert胸片数据集:不确定性标签与多标签分类实战解析

1. 项目缘起与核心定位 1.1 这个数据集到底在解决什么问题 如果你做过医学影像相关的深度学习项目,大概率会遇到一个非常尴尬的局面:公开可用的胸片数据集要么规模太小,要么标注质量参差不齐,要么干脆只给你一个非黑即白的二分类…

📅 2026/10/14 10:46:29
从模糊标题到实时评估系统:Kafka Streams与Redis实战

从模糊标题到实时评估系统:Kafka Streams与Redis实战

1. 从一个模糊的标题说起:为什么“rea”值得单独拿出来聊第一次看到“rea”这个标题的时候,我承认自己愣了几秒。没有正文,没有关键词,没有摘要,就孤零零三个字母。放在任何一个技术社区里,这种标题大概率会…

📅 2026/10/14 10:41:24
MORE NEWS

更多资讯

📰

大比例尺DLG转地理实体:数据体检、映射表与自动化管线

简介:针对1∶500、1∶1 000、1∶2 000比例尺基础地理信息要素数据转换生产基础地理实体数据,这份技术规程面向基础地理信息专业人员和测绘生产管理人员,是新型基础测绘与实景三维中国建设中可实际参照的作业指导文件。内容覆盖范围、引用文件…

📰

IKAnalyzer中文分词器实战:从集成到调优全指南

做中文搜索和内容检索项目时,IKAnalyzer分词器是一个绕不开的名字。如果你的项目对搜索质量有要求,或者说你正在尝试用Lucene、Elasticsearch这类搜索引擎处理中文内容,那这篇文章应该能帮你省掉不少弯路。本文会从一个实际可用、可复现的角度…

📰

Vue登录页如何彻底屏蔽浏览器保存密码提示?五种方案实战对比

1. 登录页密码保存提示的来龙去脉1.1 这个提示到底从哪冒出来的做过前端登录页的人基本都遇到过这个场景:用户输入账号密码,点击登录,页面跳转的一瞬间,浏览器右上角或者地址栏下方弹出一个"是否保存密码"的小气泡。对普…

📰

Knative v1.0 版本发布深度解读:Serving、Eventing、扩展组件与 Operator 的里程碑更新

文档教程云原生 【免费下载链接】docs User documentation for Knative components. 项目地址: https://gitcode.com/gh_mirrors/docs1/docs 点击查看 免费下载 2021 年 11 月 2 日,Knative 正式发布 v1.0 版本,标志着这个构建在 Kubernetes…

📰

sebastian/version 版本演进全解析:从 ChangeLog 看 Git 托管 PHP 项目的版本号管理库

开发工具 【免费下载链接】version Library that helps with managing the version number of Git-hosted PHP projects 项目地址: https://gitcode.com/gh_mirrors/ver/version 点击查看 免费下载 本篇技术指南以 ChangeLog.md 为脉络,完整梳理 sebast…

📰

机械臂建模+双臂蒙特卡洛法工作空间、笛卡尔空间、运动学圆弧轨迹(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 &#x1f381…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬