package com.algo.model; /** * CTU物理参数配置类 * 包含CTU运动的各种物理参数,用于路径规划和碰撞检测 */ public class CTUPhysicalConfig { /** * 最大移动速度 (米/秒) */ private double maxSpeed; /** * 正常移动速度 (米/秒) */ private double normalSpeed; /** * 最大加速度 (米/秒²) */ private double maxAcceleration; /** * 最大减速度 (米/秒²) */ private double maxDeceleration; /** * 转向时间 (秒) - 90度转向所需时间 */ private double turnTime90; /** * 转向时间 (秒) - 180度转向所需时间 */ private double turnTime180; /** * CTU之间的最小安全距离 (米) */ private double minSafetyDistance; /** * CTU之间的最小跟随距离 (米) */ private double minFollowingDistance; /** * CTU的物理长度 (米) */ private double ctuLength; /** * CTU的物理宽度 (米) */ private double ctuWidth; /** * 启动时间 (秒) - 从静止到正常速度所需时间 */ private double startupTime; /** * 停止时间 (秒) - 从正常速度到静止所需时间 */ private double stopTime; /** * 路径点之间的标准距离 (米) */ private double standardPointDistance; // 默认构造函数 - 使用基于实际场地的物理参数 public CTUPhysicalConfig() { this.maxSpeed = 1.0; // 1000mm/s = 1.0米/秒 this.normalSpeed = 1.0; // 正常运行速度100%最大速度 this.maxAcceleration = 0.4; // 400 mm/s^2 = 0.4米/秒² this.maxDeceleration = 0.4; // 相同的加减速度 this.turnTime90 = 4.0; // 每90度转向需要4秒 this.turnTime180 = 8.0; // 180度转向需要8秒 this.minSafetyDistance = 3.0; // 最小安全距离3米 this.minFollowingDistance = 3.0; // 最小跟随距离3米 this.ctuLength = 1.5; // CTU长度1.5米 this.ctuWidth = 1.0; // CTU宽度1米 this.startupTime = 1.0; // 启动时间1秒 this.stopTime = 1.5; // 停止时间1.5秒 this.standardPointDistance = 1.0; // 标准路径点距离1米 } // 完整参数的构造函数 public CTUPhysicalConfig(double maxSpeed, double normalSpeed, double maxAcceleration, double maxDeceleration, double turnTime90, double turnTime180, double minSafetyDistance, double minFollowingDistance, double ctuLength, double ctuWidth, double startupTime, double stopTime, double standardPointDistance) { this.maxSpeed = maxSpeed; this.normalSpeed = normalSpeed; this.maxAcceleration = maxAcceleration; this.maxDeceleration = maxDeceleration; this.turnTime90 = turnTime90; this.turnTime180 = turnTime180; this.minSafetyDistance = minSafetyDistance; this.minFollowingDistance = minFollowingDistance; this.ctuLength = ctuLength; this.ctuWidth = ctuWidth; this.startupTime = startupTime; this.stopTime = stopTime; this.standardPointDistance = standardPointDistance; } // Getter和Setter方法 public double getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(double maxSpeed) { this.maxSpeed = maxSpeed; } public double getNormalSpeed() { return normalSpeed; } public void setNormalSpeed(double normalSpeed) { this.normalSpeed = normalSpeed; } public double getMaxAcceleration() { return maxAcceleration; } public void setMaxAcceleration(double maxAcceleration) { this.maxAcceleration = maxAcceleration; } public double getMaxDeceleration() { return maxDeceleration; } public void setMaxDeceleration(double maxDeceleration) { this.maxDeceleration = maxDeceleration; } public double getTurnTime90() { return turnTime90; } public void setTurnTime90(double turnTime90) { this.turnTime90 = turnTime90; } public double getTurnTime180() { return turnTime180; } public void setTurnTime180(double turnTime180) { this.turnTime180 = turnTime180; } public double getMinSafetyDistance() { return minSafetyDistance; } public void setMinSafetyDistance(double minSafetyDistance) { this.minSafetyDistance = minSafetyDistance; } public double getMinFollowingDistance() { return minFollowingDistance; } public void setMinFollowingDistance(double minFollowingDistance) { this.minFollowingDistance = minFollowingDistance; } public double getCtuLength() { return ctuLength; } public void setCtuLength(double ctuLength) { this.ctuLength = ctuLength; } public double getCtuWidth() { return ctuWidth; } public void setCtuWidth(double ctuWidth) { this.ctuWidth = ctuWidth; } public double getStartupTime() { return startupTime; } public void setStartupTime(double startupTime) { this.startupTime = startupTime; } public double getStopTime() { return stopTime; } public void setStopTime(double stopTime) { this.stopTime = stopTime; } public double getStandardPointDistance() { return standardPointDistance; } public void setStandardPointDistance(double standardPointDistance) { this.standardPointDistance = standardPointDistance; } /** * 计算从当前速度加速到目标速度所需的时间 * * @param currentSpeed 当前速度 * @param targetSpeed 目标速度 * @return 所需时间(秒) */ public double getAccelerationTime(double currentSpeed, double targetSpeed) { if (targetSpeed > currentSpeed) { return (targetSpeed - currentSpeed) / maxAcceleration; } else { return (currentSpeed - targetSpeed) / maxDeceleration; } } /** * 计算从当前速度加速/减速到目标速度所需的距离 * * @param currentSpeed 当前速度 * @param targetSpeed 目标速度 * @return 所需距离(米) */ public double getAccelerationDistance(double currentSpeed, double targetSpeed) { double time = getAccelerationTime(currentSpeed, targetSpeed); return (currentSpeed + targetSpeed) * time / 2.0; } /** * 根据路径点距离计算移动时间 * * @param distance 距离(米) * @param currentSpeed 当前速度 * @return 移动时间(秒) */ public double getTravelTime(double distance, double currentSpeed) { if (currentSpeed <= 0) { currentSpeed = normalSpeed; } return distance / currentSpeed; } /** * 根据方向变化计算转向时间 * * @param fromDirection 起始方向角度 * @param toDirection 目标方向角度 * @return 转向时间(秒) */ public double getTurnTime(String fromDirection, String toDirection) { try { double from = Double.parseDouble(fromDirection); double to = Double.parseDouble(toDirection); // 计算角度差 double angleDiff = Math.abs(to - from); if (angleDiff > 180) { angleDiff = 360 - angleDiff; } // 根据角度差计算转向时间 if (angleDiff <= 5) { // 基本无转向 return 0.0; } else if (angleDiff <= 90) { return turnTime90 * (angleDiff / 90.0); } else if (angleDiff <= 180) { return turnTime90 + (turnTime180 - turnTime90) * ((angleDiff - 90) / 90.0); } else { return turnTime180; } } catch (NumberFormatException e) { // 如果方向不是数字,返回默认转向时间 return turnTime90; } } /** * 检查两个CTU之间的距离是否满足安全要求 * * @param distance 距离(米) * @param isFollowing 是否为跟随情况 * @return true如果距离安全 */ public boolean isSafeDistance(double distance, boolean isFollowing) { double minDistance = isFollowing ? minFollowingDistance : minSafetyDistance; return distance >= minDistance; } /** * 计算精确的移动时间,考虑加速度、减速度和实际距离 * * @param distance 实际移动距离(米) * @param startSpeed 起始速度(米/秒) * @param endSpeed 结束速度(米/秒) * @param targetSpeed 目标巡航速度(米/秒) * @return 移动时间(秒) */ public double calculatePreciseMovementTime(double distance, double startSpeed, double endSpeed, double targetSpeed) { if (distance <= 0) return 0.0; // 如果距离很短,直接计算平均速度 if (distance < 0.5) { // 小于0.5米 double avgSpeed = Math.max(0.1, (startSpeed + endSpeed) / 2.0); return distance / avgSpeed; } double totalTime = 0.0; double currentSpeed = startSpeed; double remainingDistance = distance; // 阶段1: 加速到目标速度 if (currentSpeed < targetSpeed) { double accelerationTime = (targetSpeed - currentSpeed) / maxAcceleration; double accelerationDistance = currentSpeed * accelerationTime + 0.5 * maxAcceleration * accelerationTime * accelerationTime; if (accelerationDistance < remainingDistance) { totalTime += accelerationTime; remainingDistance -= accelerationDistance; currentSpeed = targetSpeed; } else { // 距离不足以完全加速,直接计算 return calculateTimeForShortDistance(distance, startSpeed, endSpeed); } } // 阶段2: 减速到目标结束速度 double decelerationDistance = 0.0; double decelerationTime = 0.0; if (currentSpeed > endSpeed) { decelerationTime = (currentSpeed - endSpeed) / maxDeceleration; decelerationDistance = endSpeed * decelerationTime + 0.5 * maxDeceleration * decelerationTime * decelerationTime; } // 阶段3: 匀速巡航 if (remainingDistance > decelerationDistance) { double cruisingDistance = remainingDistance - decelerationDistance; double cruisingTime = cruisingDistance / currentSpeed; totalTime += cruisingTime; } // 添加减速时间 totalTime += decelerationTime; return totalTime; } /** * 计算短距离移动时间(无法完整加速减速的情况) */ private double calculateTimeForShortDistance(double distance, double startSpeed, double endSpeed) { // 使用运动学公式: s = v0*t + 0.5*a*t^2 // 其中 v_f = v0 + a*t,求解 t double avgAcceleration = (endSpeed > startSpeed) ? maxAcceleration : -maxDeceleration; // 如果加速度很小或为0,使用平均速度 if (Math.abs(avgAcceleration) < 0.01) { return distance / Math.max(0.1, (startSpeed + endSpeed) / 2.0); } // 求解二次方程: 0.5*a*t^2 + v0*t - s = 0 double a = 0.5 * avgAcceleration; double b = startSpeed; double c = -distance; double discriminant = b * b - 4 * a * c; if (discriminant < 0) { // 无解,使用平均速度 return distance / Math.max(0.1, (startSpeed + endSpeed) / 2.0); } double t1 = (-b + Math.sqrt(discriminant)) / (2 * a); double t2 = (-b - Math.sqrt(discriminant)) / (2 * a); // 选择正的时间值 double time = (t1 > 0) ? t1 : t2; return Math.max(0.1, time); // 确保时间为正 } /** * 基于实际坐标计算两点间的精确距离(米) * * @param coord1 起点坐标 [x_mm, y_mm] * @param coord2 终点坐标 [x_mm, y_mm] * @return 距离(米) */ public static double calculateRealDistance(double[] coord1, double[] coord2) { if (coord1 == null || coord2 == null || coord1.length < 2 || coord2.length < 2) { return 0.0; } // 坐标单位为毫米,转换为米 double dx = (coord2[0] - coord1[0]) / 1000.0; double dy = (coord2[1] - coord1[1]) / 1000.0; return Math.sqrt(dx * dx + dy * dy); } /** * 计算方向改变角度 * * @param coord1 起点坐标 * @param coord2 中间点坐标 * @param coord3 终点坐标 * @return 转向角度(度) */ public static double calculateTurnAngle(double[] coord1, double[] coord2, double[] coord3) { if (coord1 == null || coord2 == null || coord3 == null) { return 0.0; } // 计算两个向量 double[] vec1 = {coord2[0] - coord1[0], coord2[1] - coord1[1]}; double[] vec2 = {coord3[0] - coord2[0], coord3[1] - coord2[1]}; // 计算向量长度 double len1 = Math.sqrt(vec1[0] * vec1[0] + vec1[1] * vec1[1]); double len2 = Math.sqrt(vec2[0] * vec2[0] + vec2[1] * vec2[1]); if (len1 < 1e-6 || len2 < 1e-6) { return 0.0; } // 计算夹角 double dot = vec1[0] * vec2[0] + vec1[1] * vec2[1]; double cosAngle = dot / (len1 * len2); // 限制cosAngle在[-1, 1]范围内 cosAngle = Math.max(-1.0, Math.min(1.0, cosAngle)); double angle = Math.acos(cosAngle); return Math.toDegrees(angle); } @Override public String toString() { return "CTUPhysicalConfig{" + "maxSpeed=" + maxSpeed + ", normalSpeed=" + normalSpeed + ", maxAcceleration=" + maxAcceleration + ", maxDeceleration=" + maxDeceleration + ", turnTime90=" + turnTime90 + ", turnTime180=" + turnTime180 + ", minSafetyDistance=" + minSafetyDistance + ", minFollowingDistance=" + minFollowingDistance + ", ctuLength=" + ctuLength + ", ctuWidth=" + ctuWidth + ", startupTime=" + startupTime + ", stopTime=" + stopTime + ", standardPointDistance=" + standardPointDistance + '}'; } }