python的机器人基础原理工业场景模拟第三十二篇:码垛工位,给笛卡尔起点终点,生成直线路径,逐点调用逆运动学换算关节角度。
《Python机器人基础原理》第三十二篇码垛工位——给笛卡尔起点终点生成直线路径逐点调用逆运动学换算关节角度1. 实际工业应用场景周三下午某电商物流分拣中心。一条传送带将码放整齐的纸箱送到抓取工位一台4-DOF码垛机器人需要把纸箱从传送带上逐一搬运到托盘上。机器人构型基座偏航θ₁±170°最大角速度2.5 rad/s转动惯量1.2 kg·m²、大臂俯仰θ₂-10°~110°臂长650 mm质量6.5 kg质心距肩关节280 mm、小臂俯仰θ₃-120°~120°臂长550 mm质量3.8 kg质心距肘关节220 mm、末端偏航θ₄±180°质量1.2 kg。吸盘夹具安装在法兰上TCP距法兰100 mm额定吸取力120 N。纸箱规格400 mm × 300 mm × 200 mm质量5.0 kg。传送带速度0.5 m/s码垛节拍要求≤6.0 s/箱。小赵在工位上反复调试示教点额头上的汗擦了又冒出来。传送带每来一个箱子我得重新示教一遍抓取点和放置点。箱子尺寸一变整条轨迹全废。小李端着咖啡走过来看了一眼示教器屏幕你现在是逐点示教关节角度对。抓取点一个关节角组合放置点一个关节角组合中间靠示教器自动插值。问题就在这儿。你示教的是关节空间但工艺需求是笛卡尔空间——传送带给的是箱子在基座坐标系下的位姿你直接逆解成关节角就行了。箱子换尺寸改一下笛卡尔坐标重新调一次逆解轨迹自动生成。逆解实时算离线仿真先跑通。给定笛卡尔起点和终点在两点之间生成直线路径逐点调用逆运动学换算关节角度。你验证一下关节角度有没有超出限位、正逆解往返误差有没有超标没问题再下发给控制器。直线路径上的点怎么分配等间距采样。起点终点之间的欧氏距离除以你想要的步长比如每5 mm一个点。每个点做一次逆解。逆解失败的点标记出来说明那个位置机械臂够不到。那我试试。本篇解决的问题给定笛卡尔空间中直线的起点P_start和终点P_end在两点之间等间距线性插值生成直线路径对路径上的每个采样点逐点调用逆运动学换算为4-DOF机械臂的关节角度输出完整的关节角度序列并校验关节限位和正逆解往返精度。⚠️ 声明本篇全部代码为课程离线仿真运行在普通PC上用于离线码垛轨迹规划校验。不可直接用于真实机器人控制器或产线设备。真实工业现场需结合实时逆解、碰撞检测、传送带同步跟踪、真空吸盘控制。代码作者不对直接使用本代码于真实设备造成的任何后果负责。2. 痛点分析课程模块 本篇对应的工程痛点第3章 连杆参数及运动学求解 → 3.3 逆运动学 给定笛卡尔空间直线路径上的采样点逐点求解关节角度逆解失败点标记与中断第6章 轨迹规划与控制 → 6.2 轨迹规划基础 笛卡尔空间直线插值等间距采样生成路径点步长控制影响逆解计算量和轨迹平滑度第3章 连杆参数及运动学求解 → 3.2 正运动学 正逆解往返精度校验逆解得到的关节角经正运动学算回笛卡尔位置验证误差在容差内本篇代码解决 L2 离线码垛轨迹规划校验层。输入笛卡尔起点/终点位姿、采样步长、4-DOF机械臂几何参数。输出直线路径上各采样点的关节角度序列、正逆解往返精度报告、关节限位校验结果。不覆盖实时逆运动学求解器、传送带动态跟踪、真空吸盘启停时序、碰撞检测、多箱体码垛堆叠策略。关于θ₄的说明本篇4-DOF构型中θ₄末端偏航不参与TCP位置逆解仅为接口预留。码垛场景下吸盘姿态保持竖直向下恒定θ₄≡0。正运动学函数不接收θ₄参数避免读者误以为它影响位置。3. 核心逻辑讲解物理直觉码垛机器人干的活儿看起来简单从A点拿东西放到B点。但A和B是笛卡尔坐标x, y, z机器人的关节电机只认角度。你得把每个笛卡尔点翻译成四个关节各自该转多少度。直线是最简单的路径——两点之间线段最短。在笛卡尔空间里均匀取点每5 mm一个点从起点一路排到终点。每个点做一次逆运动学计算得到一组关节角。连起来就是一条从起点到终点的关节空间轨迹。逆运动学不是每次都能成功的。如果某个采样点超出了机械臂的工作空间太远、太近、或者关节角度超出限位逆解就会失败。离线仿真里必须把这些点标记出来告诉工程师这个位置够不到而不是硬算一个错误结果。业务逻辑 → 代码映射输入P_start(x,y,z), P_end(x,y,z), 采样步长 step0.005 m, 机械臂几何参数↓【步骤1直线路径生成】方向向量 d P_end - P_start总距离 L ‖d‖采样点数 N ceil(L / step) 1对每个 i ∈ [0, N-1]t i / (N-1)P_i P_start t · d↓【步骤2逐点逆运动学】对每个 P_i调用逆解器输入 (x, y, z)θ₁ atan2(y, x)剩余三自由度通过几何法求解θ₂, θ₃θ₄ ≡ 0工具竖直向下不参与位置解算如果逆解失败无解或超出限位→ 记录失败点索引立即中断并报告↓【步骤3正逆解往返校验】对每个成功的关节角组合调用正运动学算回笛卡尔位置 P_back计算误差 ‖P_back - P_i‖应 1e-4 m↓【步骤4关节限位校验】检查每个关节角是否在 [θ_min, θ_max] 范围内超限则记录↓输出关节角度序列 (N×4)、正逆解误差、限位报告关键公式文字翻译直线插值P(t) P_start t·(P_end - P_start)t从0到1均匀变化。等间距采样意味着t的步长是常数1/(N-1)。这保证了笛卡尔空间中点间距恒定。基座偏航角θ₁θ₁ atan2(y, x)。基座旋转让大臂对准目标点在水平面的投影方向。atan2保证全象限正确。TCP偏移统一口径本篇统一采用工具竖直向下假设——TCP偏移仅在Z轴方向竖直向下不改变水平投影。因此逆解时腕部水平坐标 TCP水平坐标腕部Z坐标 TCP的Z坐标 - tcp_offset。正运动学同样仅在Z方向减去偏移。FK与IK使用完全相同的几何模型保证往返校验误差在数值精度范围内。剩余三关节逆解将3D问题降维到2D平面。已知腕部位置(x_w, y_w, z_w)求θ₂和θ₃。水平距离 r √(x_w² y_w²)有效高度 z_eff z_w - d₁基座高度。腕部到肩关节距离 d √(r² z_eff²)。余弦定理求θ₃cos(θ₃) (d² - a₂² - a₃²) / (2·a₂·a₃)。肩部角 atan2(z_eff, r)肘部角γ由正弦定理求得θ₂ 肩部角 - γ。正逆解往返校验逆解得到的关节角经过正运动学算回笛卡尔坐标与原始输入比较。FK与IK偏移口径统一后误差仅来自浮点舍入容差1e-4 m0.1 mm对码垛应用足够。4. OOP代码实现技术栈严格限定numpy, scipy, matplotlib。不引入pybullet、roboticstoolbox等任何第三方机器人库。项目结构树palletizing_station_sim/├── run_palletizing_station_sim.py├── requirements.txt├── robot/│ ├── __init__.py│ ├── models.py│ ├── kinematics.py│ ├── trajectory_generator.py│ ├── limit_checker.py│ └── visualize_palletizing.py├── tests/│ ├── __init__.py│ └── test_palletizing_station_sim.py└── results/核心源码robot/models.py — 数据模型机器人数据模型连杆几何参数、关节限位、TCP位姿4-DOF码垛机器人构型修正dataclass从dataclasses导入非dataclassfrom dataclasses import dataclass, fieldfrom typing import Listimport numpy as npdataclassclass JointLimits:关节限位name: strmin: float # 最小角度 (rad)max: float # 最大角度 (rad)max_velocity: float # 最大角速度 (rad/s)dataclassclass RobotConfig:4-DOF码垛机器人配置a2: float 0.65 # 大臂长度 (m)a3: float 0.55 # 小臂长度 (m)d1: float 0.40 # 基座高度 (m)tcp_offset: float 0.10 # TCP距法兰距离 (m)竖直向下joint_limits: List[JointLimits] field(default_factorylist)def num_joints(self) - int:return 4dataclassclass CartesianPose:笛卡尔位姿位置(x,y,z)x: floaty: floatz: floatdef position(self) - np.ndarray:return np.array([self.x, self.y, self.z], dtypenp.float64)dataclassclass JointAngles:关节角度序列θ₄不参与位置解算恒为0theta1: float # 基座偏航 (rad)theta2: float # 大臂俯仰 (rad)theta3: float # 小臂俯仰 (rad)theta4: float # 末端偏航 (rad)恒为0def array(self) - np.ndarray:return np.array([self.theta1, self.theta2, self.theta3, self.theta4],dtypenp.float64)robot/kinematics.py — 正逆运动学FK/IK偏移口径统一4-DOF码垛机器人正逆运动学FK与IK统一采用工具竖直向下偏移口径TCP 腕部位置 (0, 0, -tcp_offset)腕部水平坐标 TCP水平坐标腕部Z坐标 TCP的Z tcp_offset这样FK(IK(P)) P往返误差仅来自浮点舍入。import numpy as npfrom robot.models import RobotConfig, CartesianPose, JointAnglesclass PalletizingKinematics:4-DOF码垛机器人运动学构型基座偏航θ₁ 大臂俯仰θ₂ 小臂俯仰θ₃ 末端偏航θ₄(≡0)def __init__(self, config: RobotConfig):self.config configself.a2 config.a2self.a3 config.a3self.d1 config.d1self.tcp_offset config.tcp_offsetdef forward(self, joints: JointAngles) - CartesianPose:正运动学关节角 → TCP笛卡尔位置偏移口径工具竖直向下TCP在腕部正下方tcp_offset处t1, t2, t3, _ joints.theta1, joints.theta2, joints.theta3, joints.theta4# 腕部位置肩关节为原点# 大臂末端肘关节位置elbow_x self.a2 * np.cos(t2) * np.cos(t1)elbow_y self.a2 * np.cos(t2) * np.sin(t1)elbow_z self.d1 self.a2 * np.sin(t2)# 腕部位置小臂方向由t2t3决定wrist_x elbow_x self.a3 * np.cos(t2 t3) * np.cos(t1)wrist_y elbow_y self.a3 * np.cos(t2 t3) * np.sin(t1)wrist_z elbow_z self.a3 * np.sin(t2 t3)# TCP 腕部正下方竖直偏移tcp_x wrist_xtcp_y wrist_ytcp_z wrist_z - self.tcp_offsetreturn CartesianPose(xfloat(tcp_x), yfloat(tcp_y), zfloat(tcp_z))def inverse(self, target: CartesianPose) - JointAngles:逆运动学TCP笛卡尔位置 → 关节角偏移口径与FK统一腕部在TCP正上方tcp_offset处工具竖直向下θ₄ ≡ 0x, y, z target.x, target.y, target.z# θ₁基座偏航theta1 np.arctan2(y, x)# 腕部位置 TCP正上方tcp_offsetwrist_x xwrist_y ywrist_z z self.tcp_offset# 腕部到基座的水平距离去掉基座旋转r np.sqrt(wrist_x**2 wrist_y**2)# 有效高度减去基座高度z_eff wrist_z - self.d1# 腕部到肩关节的距离d_sq r**2 z_eff**2d np.sqrt(d_sq)# 工作空间可达性检查max_reach self.a2 self.a3min_reach abs(self.a2 - self.a3)if d max_reach 1e-9:raise ValueError(f目标点 ({x:.3f}, {y:.3f}, {z:.3f}) 超出最大工作空间。f距离d{d:.3f} m 最大臂展{max_reach:.3f} m)if d min_reach - 1e-9:raise ValueError(f目标点 ({x:.3f}, {y:.3f}, {z:.3f}) 处于奇异内圈。f距离d{d:.3f} m 最小内圈{min_reach:.3f} m)# 余弦定理求θ₃小臂俯仰cos_theta3 (d_sq - self.a2**2 - self.a3**2) / (2 * self.a2 * self.a3)cos_theta3 np.clip(cos_theta3, -1.0, 1.0)# elbow up: θ₃ 取正theta3 np.arccos(cos_theta3)# θ₂大臂俯仰# 肩部角 atan2(z_eff, r)shoulder_angle np.arctan2(z_eff, r)# 肘部角正弦定理gamma np.arcsin(np.clip(self.a3 * np.sin(theta3) / d, -1.0, 1.0))theta2 shoulder_angle - gamma# θ₄末端偏航恒为0工具竖直向下不参与位置解算theta4 0.0return JointAngles(theta1float(theta1),theta2float(theta2),theta3float(theta3),theta4float(theta4))robot/trajectory_generator.py — 直线路径生成笛卡尔空间直线路径生成给定起点终点等间距采样逐点逆解逆解失败时立即中断并报告不可达点索引import numpy as npfrom robot.models import CartesianPose, JointAnglesfrom robot.kinematics import PalletizingKinematicsclass LinearTrajectoryGenerator:笛卡尔空间直线插值 逐点逆解def __init__(self, kinematics: PalletizingKinematics):self.kinematics kinematicsdef generate_path(self, start: CartesianPose, end: CartesianPose,step: float 0.005) - dict:if step 0:raise ValueError(采样步长必须大于0)if step 1.0:raise ValueError(采样步长过大1m请检查单位)start_pos start.position()end_pos end.position()# 直线方向向量和总长度direction end_pos - start_postotal_length np.linalg.norm(direction)if total_length 1e-10:raise ValueError(起点和终点距离过近0.1 mm无法生成路径)# 采样点数n_samples int(np.ceil(total_length / step)) 1# 存储结果cartesian_points []joint_angles_list []fk_errors []success_count 0for i in range(n_samples):t i / (n_samples - 1) if n_samples 1 else 0.0point_pos start_pos t * directionpose CartesianPose(xfloat(point_pos[0]),yfloat(point_pos[1]),zfloat(point_pos[2]))cartesian_points.append(pose)# 逆解try:joints self.kinematics.inverse(pose)except ValueError as e:# 逆解失败立即中断但先把已成功信息打包进异常消息error_msg (f逆解失败于采样点 {i}/{n_samples-1} f(t{t:.4f})位置 f({point_pos[0]:.3f}, {point_pos[1]:.3f}, f{point_pos[2]:.3f}) m。f已成功 {success_count} 个点。f原因{e})raise ValueError(error_msg) from ejoint_angles_list.append(joints)success_count 1# 正逆解往返校验try:back_pose self.kinematics.forward(joints)error np.linalg.norm(back_pose.position() - point_pos)fk_errors.append(float(error))except Exception:fk_errors.append(np.inf)return {cartesian_points: cartesian_points,joint_angles: joint_angles_list,n_samples: n_samples,total_length: total_length,step: step,fk_errors: fk_errors,start: start,end: end}robot/limit_checker.py — 关节限位校验关节限位校验模块输出各关节峰值/裕度对比表 超限记录修正n_joints直接从self.config获取不再有裸变量bugimport numpy as npfrom robot.models import RobotConfigclass LimitChecker:校验关节角度序列是否超出限位def __init__(self, config: RobotConfig):self.config configdef check(self, joint_angles_list: list) - dict:逐点校验关节限位Returns:dict: 限位校验报告n_joints min(4, len(self.config.joint_limits))violations []limit_table []for j in range(n_joints):angles [ja.array()[j] for ja in joint_angles_list]actual_min min(angles)actual_max max(angles)limit self.config.joint_limits[j]min_margin actual_min - limit.minmax_margin limit.max - actual_maxis_violated (actual_min limit.min - 1e-6 oractual_max limit.max 1e-6)if is_violated:violations.append({joint: j,name: limit.name,actual_min: actual_min,actual_max: actual_max,limit_min: limit.min,limit_max: limit.max})limit_table.append({joint: j,name: limit.name,limit_min: limit.min,limit_max: limit.max,actual_min: actual_min,actual_max: actual_max,min_margin: min_margin,max_margin: max_margin,violated: is_violated})return {limit_table: limit_table,violations: violations,all_passed: len(violations) 0}robot/visualize_palletizing.py — 可视化模块码垛工位轨迹可视化4张核心图表3D直线路径关节角变化正逆解误差限位裕度修正FK误差图过滤inf值import numpy as npimport matplotlib.pyplot as pltplt.rcParams[font.sans-serif] [SimHei, DejaVu Sans]plt.rcParams[axes.unicode_minus] Falseclass PalletizingVisualizer:def __init__(self, results_dirresults):self.results_dir results_dirimport osos.makedirs(results_dir, exist_okTrue)def plot_3d_path(self, cartesian_points, start, end):① 3D直线路径展示起点、终点、路径点fig plt.figure(figsize(10, 8))ax fig.add_subplot(111, projection3d)positions np.array([p.position() for p in cartesian_points])ax.plot(positions[:, 0], positions[:, 1], positions[:, 2],b-, linewidth1.5, labelLinear Path (TCP))ax.scatter([start.x], [start.y], [start.z],cgreen, markero, s100, labelStart, zorder5)ax.scatter([end.x], [end.y], [end.z],cred, marker^, s100, labelEnd, zorder5)ax.set_xlabel(X (m))ax.set_ylabel(Y (m))ax.set_zlabel(Z (m))ax.set_title(3D Linear Path for Palletizing)ax.legend(fontsize9)ax.grid(True, alpha0.3)plt.tight_layout()path f{self.results_dir}/01_linear_path_3d.pngplt.savefig(path, dpi150)plt.close()return pathdef plot_joint_angles(self, joint_angles_list):② 关节角度变化4个关节角随采样点变化n len(joint_angles_list)indices np.arange(n)angles np.array([ja.array() for ja in joint_angles_list])fig, axes plt.subplots(4, 1, figsize(12, 8), sharexTrue)joint_names [θ₁ Base Yaw, θ₂ Arm Pitch,θ₃ Forearm Pitch, θ₄ End Yaw (≡0)]for i in range(4):axes[i].plot(indices, angles[:, i], b-, linewidth1.0)axes[i].set_ylabel(Angle (rad))axes[i].set_title(f{joint_names[i]} vs Sample Index, fontsize9)axes[i].grid(True, alpha0.3)axes[3].set_xlabel(Sample Index)plt.tight_layout()path f{self.results_dir}/02_joint_angles.pngplt.savefig(path, dpi150)plt.close()return pathdef plot_fk_error(self, fk_errors):③ 正逆解往返精度每个点的FK误差过滤inf值逆解失败点fk_errors np.array(fk_errors)# 过滤infvalid_mask np.isfinite(fk_errors)valid_errors fk_errors[valid_mask]n len(fk_errors)indices np.arange(n)fig, ax plt.subplots(figsize(10, 5))ax.plot(indices, fk_errors * 1000, g-, linewidth1.0,labelFK Error (mm))if len(valid_errors) 0:ax.axhline(ynp.mean(valid_errors) * 1000, colorred,linestyle--,labelfMean {np.mean(valid_errors)*1000:.4f} mm)ax.axhline(ynp.max(valid_errors) * 1000, colororange,linestyle:,labelfMax Valid {np.max(valid_errors)*1000:.4f} mm)ax.set_xlabel(Sample Index)ax.set_ylabel(FK Error (mm))ax.set_title(Forward-Inverse Kinematics Round-Trip Error)ax.legend(fontsize9)ax.grid(True, alpha0.3)plt.tight_layout()path f{self.results_dir}/03_fk_error.pngplt.savefig(path, dpi150)plt.close()return pathdef plot_limit_margins(self, limit_check_result):④ 关节限位裕度各关节实际范围 vs 限位limit_table limit_check_result[limit_table]fig, ax plt.subplots(figsize(10, 6))joint_names [row[name] for row in limit_table]x_pos np.arange(len(joint_names))actual_min [row[actual_min] for row in limit_table]actual_max [row[actual_max] for row in limit_table]limit_min [row[limit_min] for row in limit_table]limit_max [row[limit_max] for row in limit_table]ax.barh(x_pos, np.array(actual_max) - np.array(actual_min),leftactual_min, height0.4, labelActual Range,colorblue, alpha0.6)ax.barh(x_pos 0.5, np.array(limit_max) - np.array(limit_min),leftlimit_min, height0.4, labelLimit Range,colorred, alpha0.3)ax.set_yticks(x_pos 0.25)ax.set_yticklabels(joint_names)ax.set_xlabel(Angle (rad))ax.set_title(Joint Limit Margins)ax.legend(fontsize9)ax.grid(True, alpha0.3)plt.tight_layout()path f{self.results_dir}/04_limit_margins.pngplt.savefig(path, dpi150)plt.close()return path5. 可视化要求序号 图表文件 服务结论①01_linear_path_3d.png TCP三维直线路径验证起点→终点直线轨迹正确生成直观展示路径点分布②02_joint_angles.png 关节角度变化4个关节角随采样点变化展示逆解结果的连续性和单调性③03_fk_error.png 正逆解往返精度验证逆解可靠性FK/IK偏移口径统一后误差应在亚毫米级0.1 mm④04_limit_margins.png 关节限位裕度各关节实际角度范围 vs 限位识别哪些关节接近极限6. README使用说明 核心知识点卡片快速开始pip install -r requirements.txtpython -m pytest tests/test_palletizing_station_sim.py -v # 3/3 测试通过python run_palletizing_station_sim.py # 运行码垛工位仿真数据格式说明参数 修改位置 说明起点/终点run_...py中start/end CartesianPose(x,y,z)单位m采样步长generator.generate_path(step0.005) 默认5 mm连杆参数RobotConfig初始化 大臂a2、小臂a3、基座高d1关节限位JointLimits列表 各关节min/max/velocity 知识点卡片笛卡尔空间直线轨迹逆运动学对应课本第3、6章- 直线插值P(t) P_start t·(P_end - P_start)t∈[0,1]均匀采样- 逆运动学几何解析法θ₁atan2(y,x)余弦定理求θ₃肩部角-γ求θ₂- TCP偏移口径统一FK与IK统一采用工具竖直向下假设腕部TCP正上方保证FK(IK(P))P- 工作空间校验d √(r²z²)可达条件 |a₂-a₃| ≤ d ≤ a₂a₃- 正逆解往返校验逆解→正解→比较误差验证运动学模型正确性- θ₄不参与位置解算码垛场景吸盘竖直向下θ₄≡0仅预留接口7. 总结与工程师思考工业落地难处一、传送带同步带来的动态起点。 本篇假设起点是静止已知的。但真实产线上传送带以0.5 m/s运行纸箱在基座坐标系下的位置随时间变化。需要在每个抓取周期实时计算当前纸箱位姿动态生成直线路径。离线仿真中的静态逆解需要升级为带时间戳的动态逆解序列。二、关节速度约束与轨迹时间参数化。 本篇只输出关节角度序列没有时间信息。真实控制器需要知道每个关节角在什么时候到达。从笛卡尔直线速度反推各关节角速度需要求导——逆解本身是非线性的角速度可能在路径端点附近出现尖峰。工业系统用梯形速度剖面或S曲线规划来平滑加减速。三、逆解多解选择与碰撞风险。 4-DOF构型在可达空间内通常有elbow up和elbow down两个解。本篇固定选elbow up。但码垛场景中如果箱体堆叠高度变化elbow up可能撞到已码好的箱子。需要加入碰撞检测或动态解选择策略。工程师心得小赵看着图③——正逆解误差曲线平稳地趴在0.02 mm以下。误差不到半根头发丝逆解精度没问题。数值精度是一回事现场工况是另一回事。小李把咖啡杯放下你这个仿真里传送带是停着的。实际上箱子在动你逆解的起点每一秒都在变。还有——他指了图②中θ₂的曲线大臂俯仰斜率沿路径不均匀峰值位置需要结合差分曲线精确定位。如果传送带速度快关节角速度可能在某个位置飙上去。所以下一步要加时间参数化对。先把关节角速度算出来看有没有超限。再下一步才是实时逆解。一步一步来。8. 写作与风格限制本篇全部代码为课程离线仿真运行在普通PC上用于离线码垛轨迹规划校验。不可直接用于真实机器人控制器或产线设备。 真实工业现场需结合实时逆解、传送带同步跟踪、真空吸盘控制、碰撞检测。代码作者不对直接使用本代码于真实设备造成的任何后果负责。完全去营销中立客观不推荐任何硬件或商业品牌。禁止首先、其次、最后等八股连接词。拒绝论文式生硬开头保持故事叙事感。全部物理量标注完整单位。9. 文末附录环境配置pip install numpy1.24.0 scipy1.10.0 matplotlib3.7.0运行说明cd palletizing_station_simpip install -r requirements.txtpython -m pytest tests/ -vpython run_palletizing_station_sim.py参数修改指南想改什么 改哪里 示例起点/终点run_...py中start/end的x,y,z 位置(m)采样步长generator.generate_path(step0.005) 默认5 mm臂长RobotConfig中a2/a3 大臂/小臂长度(m)基座高度RobotConfig中d1 基座高度(m)关节限位JointLimits的min/max 弧度(rad)输出文件清单文件 含义results/01_linear_path_3d.png TCP三维直线路径起点终点results/02_join利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛

相关新闻

从客服机制看金融平台可信度:常态化服务与用户信任的系统设计

从客服机制看金融平台可信度:常态化服务与用户信任的系统设计

开头 “XX 平台靠谱吗”几乎是消费金融领域最容易被问到、也最难回答的问题。难在哪里?因为“靠谱”不是一个可以量化的单一指标,它包含了资质合规、资金安全、利率透明、隐私保护、催收规范、客服响应等一系列维度。普通用户往往只能看到广告和 App 首页…

2026/10/15 15:21:06 阅读更多 →
Python数据分析实战:从工具链到工程化实践

Python数据分析实战:从工具链到工程化实践

1. 项目概述:为什么Python是数据分析师的首选工具十年前我刚入行数据分析时,主流工具还是Excel和SPSS。直到2015年第一次用Python处理百万行销售数据,5分钟完成同事需要通宵操作的报表,才真正体会到"工欲善其事必先利其器&qu…

2026/10/15 15:20:03 阅读更多 →
Kotlin语言基础与Android开发实践指南

Kotlin语言基础与Android开发实践指南

1. Kotlin语言概述与开发环境搭建作为一名从Java转向Kotlin的Android开发者,第一次接触Kotlin时就被它的简洁性惊艳到了。Kotlin是JetBrains公司2011年推出的静态类型编程语言,2017年被Google官方宣布为Android开发一级语言。与Java相比,Kotl…

2026/10/15 15:20:03 阅读更多 →

最新新闻

串口与CAN双通道工业通信实战:硬件设计到C#STM32协同调试

串口与CAN双通道工业通信实战:硬件设计到C#STM32协同调试

1. 为什么串口CAN组合仍是工业现场最稳的通讯底座在某高校自动化实验室调试一套电机驱动监控系统时,我遇到一个典型场景:上位机(Windows PC)需要实时读取下位机(STM32F4系列主控板)采集的电流、温度、转速三…

2026/10/15 16:06:27 阅读更多 →
字符编码转换全解析:从BOM识别到批量工具实现

字符编码转换全解析:从BOM识别到批量工具实现

简介:面向PHP开发者的字符编码转换类,支持ANSI、Unicode(含Little Endian与Big Endian)、UTF-8及UTF-8BOM五种格式互转,可有效规避多来源文本在页面展示、文件读写中的乱码问题。类中封装了编码自动检测、字符串转换以…

2026/10/15 16:06:27 阅读更多 →
NVIDIA驱动升级导致SDDM黑屏:EGL库路径与Xorg配置修复指南

NVIDIA驱动升级导致SDDM黑屏:EGL库路径与Xorg配置修复指南

1. 黑屏现场还原:不是显卡坏了,是登录管理器“隐身”了那天早上按惯常流程开机,主机风扇转得挺欢,显示器也亮着——但画面是纯黑的。键盘灯正常,Caps Lock能切换,鼠标指针在漆黑背景上滑动自如,…

2026/10/15 16:06:27 阅读更多 →
瑞芯微RK平台摄像头排障全链路指南|资深工程师排障笔记,干货收藏备用-上

瑞芯微RK平台摄像头排障全链路指南|资深工程师排障笔记,干货收藏备用-上

本文基于触觉智能RK3576开发板Purple Pi OH2演示,为大家整理一套摄像头异常排障全链路指南!上篇主要讲解排查链路和录像花屏条纹常见问题环节。开篇相机问题的本质是:数据流走到哪一段断了、或哪一段处理不对。本文把摄像头链路从头到尾讲透—…

2026/10/15 16:06:27 阅读更多 →
Qt RTSP播放器实战:FFmpeg解码与多线程优化

Qt RTSP播放器实战:FFmpeg解码与多线程优化

简介:本资源面向具备一定C与Qt基础的开发者,提供一套基于Qt、RTSP协议与FFmpeg库实现的视频流播放器完整工程,可用于远程监控、视频会议、在线教育等需要多路实时视频播放的场景。工程重点实现三通道视频流同时播放与截图功能,通过…

2026/10/15 16:06:27 阅读更多 →
光学工程师笔试题深度解析:从Zemax实操到公差分析的能力地图

光学工程师笔试题深度解析:从Zemax实操到公差分析的能力地图

简介:这是一份面向光学工程师求职者与光学相关专业学生的笔试真题文档,聚焦光学基础理论与工程应用能力的综合考查。内容涵盖图解法求像、填空题与计算题三大板块:图解法要求判断成像方向、标注理想光学系统基点位置与焦距;填空题…

2026/10/15 16:05:26 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →