Ошибка возникает из-за пустого массива при индексации. Давайте
исправим проблему в коде:
memento mori
import numpy as np
import matplotlib.pyplot as plt
def s_curve_motion_profile(distance, max_jerk, max_acceleration, max_velocity):
"""
Рассчитывает профили движения с S-образной кривой скорости
Профиль создает движение с ограниченным рывком (jerk), ускорением и скоростью,
обеспечивая плавное ускорение и торможение при движении к цели.
Args:
distance: целевое расстояние перемещения
max_jerk: максимальный рывок (производная ускорения)
max_acceleration: максимальное ускорение
max_velocity: максимальная скорость
Returns:
t_values: массив временных точек
s_values: массив значений пройденного пути
v_values: массив значений скорости
a_values: массив значений уск
# Минимальный интервал времени для достижения максимального ускорения
t_j = max_acceleration / max_jerk
# Минимальный интервал времени для достижения максимальной скорости при максимальном ускорении
t_a = max_velocity / max_acceleration
# Проверяем, достигается ли максимальная скорость
if t_a <= 2 * t_j:
# Максимальная скорость не достигается
# Корректируем максимальное ускорение
t_a = 2 * t_j
max_acceleration = max_velocity / t_a
# Вычисляем скорость в конце фазы разгона
v_peak = max_jerk * (t_j**2) + max_acceleration * (t_a - t_j)
# Расстояние, пройденное во время фазы разгона
s_accel = (max_jerk * t_j**3) / 6 + (max_acceleration * t_j**2) / 2 + max_acceleration * (t_a - 2 * t_j)**2 / 2
# Проверяем, достигается ли максимальная скорость
has_cruise_phase = True
t_v = 0 # Время фазы постоянной скорости
# Рассчитываем полный профиль движения
if 2 * s_accel > distance:
# Цель слишком близка, нужно корректировать профиль
has_cruise_phase = False
# Для случая без фазы постоянной скорости рассчитываем время и скорость
# Используем более надежный алгоритм
v_max_reachable = np.sqrt(max_acceleration * distance / 2)
if v_max_reachable < max_velocity:
max_velocity = v_max_reachable
t_a = max_velocity / max_acceleration
if t_a <= 2 * t_j:
t_a = 2 * t_j
max_acceleration = max_velocity / t_a
# Пересчитываем пройденное расстояние для проверки
s_accel = (max_jerk * t_j**3) / 6 + (max_acceleration * t_j**2) / 2 + max_acceleration * (t_a - 2 * t_j)**2 / 2
else:
# Есть фаза постоянной скорости
t_v = (distance - 2 * s_accel) / max_velocity
# Общее время движения
total_time = 2 * t_a + t_v
# Создаем временную сетку с высоким разрешением
dt = 0.01
t_values = np.arange(0, total_time + dt, dt)
s_values = np.zeros_like(t_values)
v_values = np.zeros_like(t_values)
a_values = np.zeros_like(t_values)
j_values = np.zeros_like(t_values)
# Фаза 1: Увеличение ускорения (положительный рывок)
phase1_mask = t_values <= t_j
j_values[phase1_mask] = max_jerk
a_values[phase1_mask] = max_jerk * t_values[phase1_mask]
v_values[phase1_mask] = (max_jerk * t_values[phase1_mask]**2) / 2
s_values[phase1_mask] = (max_jerk * t_values[phase1_mask]**3) / 6
# Фаза 2: Постоянное ускорение (нулевой рывок)
phase2_mask = (t_values > t_j) & (t_values <= t_a - t_j)
j_values[phase2_mask] = 0
a_values[phase2_mask] = max_acceleration
phase2_indices = np.where(phase2_mask)[0]
if len(phase2_indices) > 0:
for i in phase2_indices:
t = t_values[i]
v_values[i] = (max_jerk * t_j**2) / 2 + max_acceleration * (t - t_j)
s_values[i] = (max_jerk * t_j**3) / 6 + (max_acceleration * t_j**2) / 2 + max_acceleration * (t - t_j)**2 / 2 - (max_acceleration * t_j**2) / 2 + max_acceleration * t_j * (t - t_j)
# Фаза 3: Уменьшение ускорения (отрицательный рывок)
phase3_mask = (t_values > t_a - t_j) & (t_values <= t_a)
j_values[phase3_mask] = -max_jerk
phase2_indices = np.where(phase2_mask)[0]
phase3_indices = np.where(phase3_mask)[0]
if len(phase3_indices) > 0:
for i in phase3_indices:
t = t_values[i]
delta_t = t - (t_a - t_j)
a_values[i] = max_acceleration - max_jerk * delta_t
# Если есть предыдущая фаза, используем ее значения, иначе вычисляем
if len(phase2_indices) > 0:
last_phase2_idx = phase2_indices[-1]
v_values[i] = v_values[last_phase2_idx] + max_acceleration * delta_t - (max_jerk * delta_t**2) / 2
s_values[i] = s_values[last_phase2_idx] + v_values[last_phase2_idx] * delta_t + (max_acceleration * delta_t**2) / 2 - (max_jerk * delta_t**3) / 6
else:
# Вычисляем с нуля, если нет предыдущей фазы
v_1 = (max_jerk * t_j**2) / 2 # скорость в конце фазы 1
v_values[i] = v_1 + max_acceleration * delta_t - (max_jerk * delta_t**2) / 2
s_1 = (max_jerk * t_j**3) / 6 # позиция в конце фазы 1
s_values[i] = s_1 + v_1 * delta_t + (max_acceleration * delta_t**2) / 2 - (max_jerk * delta_t**3) / 6
phase3_indices = np.where(phase3_mask)[0]
last_phase3_idx = phase3_indices[-1] if len(phase3_indices) > 0 else 0
if has_cruise_phase:
# Фаза 4: Постоянная скорость (движение с макс. скоростью)
phase4_mask = (t_values > t_a) & (t_values <= t_a + t_v)
j_values[phase4_mask] = 0
a_values[phase4_mask] = 0
v_values[phase4_mask] = max_velocity
phase4_indices = np.where(phase4_mask)[0]
if len(phase4_indices) > 0:
for i in phase4_indices:
t = t_values[i]
delta_t = t - t_a
s_values[i] = s_values[last_phase3_idx] + max_velocity * delta_t
last_phase4_idx = phase4_indices[-1]
else:
last_phase4_idx = last_phase3_idx
# Фаза 5: Начало торможения (отрицательный рывок)
phase5_mask = (t_values > t_a + t_v) & (t_values <= t_a + t_v + t_j)
j_values[phase5_mask] = -max_jerk
phase5_indices = np.where(phase5_mask)[0]
if len(phase5_indices) > 0:
for i in phase5_indices:
t = t_values[i]
delta_t = t - (t_a + t_v)
a_values[i] = -max_jerk * delta_t
v_values[i] = max_velocity - (max_jerk * delta_t**2) / 2
s_values[i] = s_values[last_phase4_idx] + max_velocity * delta_t - (max_jerk * delta_t**3) / 6
last_phase5_idx = phase5_indices[-1]
else:
last_phase5_idx = last_phase4_idx
# Фаза 6: Постоянное отрицательное ускорение
phase6_mask = (t_values > t_a + t_v + t_j) & (t_values <= t_a + t_v + t_a - t_j)
j_values[phase6_mask] = 0
a_values[phase6_mask] = -max_acceleration
phase6_indices = np.where(phase6_mask)[0]
if len(phase6_indices) > 0:
for i in phase6_indices:
t = t_values[i]
delta_t = t - (t_a + t_v + t_j)
v_values[i] = v_values[last_phase5_idx] - max_acceleration * delta_t
s_values[i] = s_values[last_phase5_idx] + v_values[last_phase5_idx] * delta_t - (max_acceleration * delta_t**2) / 2
last_phase6_idx = phase6_indices[-1]
else:
last_phase6_idx = last_phase5_idx
# Фаза 7: Уменьшение торможения до полной остановки
phase7_mask = (t_values > t_a + t_v + t_a - t_j)
j_values[phase7_mask] = max_jerk
phase7_indices = np.where(phase7_mask)[0]
if len(phase7_indices) > 0:
for i in phase7_indices:
t = t_values[i]
delta_t = t - (t_a + t_v + t_a - t_j)
a_values[i] = -max_acceleration + max_jerk * delta_t
v_values[i] = v_values[last_phase6_idx] - max_acceleration * delta_t + (max_jerk * delta_t**2) / 2
s_values[i] = s_values[last_phase6_idx] + v_values[last_phase6_idx] * delta_t - (max_acceleration * delta_t**2) / 2 + (max_jerk * delta_t**3) / 6
else:
# Без фазы постоянной скорости - сразу к торможению
# Фаза 4: Начало торможения (отрицательный рывок)
phase4_mask = (t_values > t_a) & (t_values <= t_a + t_j)
j_values[phase4_mask] = -max_jerk
phase4_indices = np.where(phase4_mask)[0]
if len(phase4_indices) > 0:
for i in phase4_indices:
t = t_values[i]
delta_t = t - t_a
a_values[i] = -max_jerk * delta_t
v_values[i] = v_values[last_phase3_idx] - (max_jerk * delta_t**2) / 2
s_values[i] = s_values[last_phase3_idx] + v_values[last_phase3_idx] * delta_t - (max_jerk * delta_t**3) / 6
last_phase4_idx = phase4_indices[-1]
else:
last_phase4_idx = last_phase3_idx
# Фаза 5: Постоянное отрицательное ускорение
phase5_mask = (t_values > t_a + t_j) & (t_values <= t_a + (total_time - t_a - t_j))
j_values[phase5_mask] = 0
a_values[phase5_mask] = -max_acceleration
phase5_indices = np.where(phase5_mask)[0]
if len(phase5_indices) > 0:
for i in phase5_indices:
t = t_values[i]
delta_t = t - (t_a + t_j)
v_values[i] = v_values[last_phase4_idx] - max_acceleration * delta_t
s_values[i] = s_values[last_phase4_idx] + v_values[last_phase4_idx] * delta_t - (max_acceleration * delta_t**2) / 2
last_phase5_idx = phase5_indices[-1]
else:
last_phase5_idx = last_phase4_idx
# Фаза 6: Уменьшение торможения до полной остановки
phase6_mask = (t_values > t_a + (total_time - t_a - t_j))
j_values[phase6_mask] = max_jerk
phase6_indices = np.where(phase6_mask)[0]
if len(phase6_indices) > 0:
for i in phase6_indices:
t = t_values[i]
delta_t = t - (t_a + (total_time - t_a - t_j))
a_values[i] = -max_acceleration + max_jerk * delta_t
v_values[i] = v_values[last_phase5_idx] - max_acceleration * delta_t + (max_jerk * delta_t**2) / 2
s_values[i] = s_values[last_phase5_idx] + v_values[last_phase5_idx] * delta_t - (max_acceleration * delta_t**2) / 2 + (max_jerk * delta_t**3) / 6
# Корректировка чтобы последняя скорость была ровно 0
v_values[-1] = 0
return t_values, s_values, v_values, a_values, j_values
def plot_motion_profile(t, s, v, a, j, distance, max_jerk, max_acceleration, max_velocity):
"""
Визуализирует профили движения
"""
fig, axs = plt.subplots(4, 1, figsize=(10, 16), sharex=True)
# График позиции
axs[0].plot(t, s)
axs[0].set_ylabel('Позиция (м)')
axs[0].set_title(f'S-образный профиль движения\nДистанция={distance}м, Jmax={max_jerk}м/с³, Amax={max_acceleration}м/с², Vmax={max_velocity}м/с')
axs[0].grid(True)
# График скорости
axs[1].plot(t, v)
axs[1].set_ylabel('Скорость (м/с)')
axs[1].axhline(y=max_velocity, color='r', linestyle='--', label='Max Velocity')
axs[1].legend()
axs[1].grid(True)
# График ускорения
axs[2].plot(t, a)
axs[2].set_ylabel('Ускорение (м/с²)')
axs[2].axhline(y=max_acceleration, color='r', linestyle='--', label='Max Acceleration')
axs[2].axhline(y=-max_acceleration, color='r', linestyle='--')
axs[2].legend()
axs[2].grid(True)
# График рывка
axs[3].plot(t, j)
axs[3].set_ylabel('Рывок (м/с³)')
axs[3].axhline(y=max_jerk, color='r', linestyle='--', label='Max Jerk')
axs[3].axhline(y=-max_jerk, color='r', linestyle='--')
axs[3].set_xlabel('Время (с)')
axs[3].legend()
axs[3].grid(True)
plt.tight_layout()
return fig
# Параметры движения
distance = 10.0 # метров
max_jerk = 5.0 # м/с³
max_acceleration = 2.0 # м/с²
max_velocity = 1.5 # м/с
# Рассчитать и отобразить профиль движения
t, s, v, a, j = s_curve_motion_profile(distance, max_jerk, max_acceleration, max_velocity)
fig = plot_motion_profile(t, s, v, a, j, distance, max_jerk, max_acceleration, max_velocity)
# Вывести некоторую информацию о движении
print(f"Общее время движения: {t[-1]:.2f} секунд")
print(f"Максимальная скорость: {max(v):.2f} м/с (заданный лимит: {max_velocity} м/с)")
print(f"Максимальное ускорение: {max(a):.2f} м/с² (заданный лимит: {max_acceleration} м/с²)")
print(f"Конечная позиция: {s[-1]:.3f} м (заданная: {distance} м)")
plt.savefig('s_curve_motion_profile.png', dpi=300)
plt.show()
# Пример использования функции с другими параметрами
# Большее расстояние, когда точно достигается макс. скорость
print("\nПример 2: Большее расстояние с выходом на макс. скорость")
distance2 = 30.0
t2, s2, v2, a2, j2 = s_curve_motion_profile(distance2, max_jerk, max_acceleration, max_velocity)
fig2 = plot_motion_profile(t2, s2, v2, a2, j2, distance2, max_jerk, max_acceleration, max_velocity)
print(f"Общее время движения: {t2[-1]:.2f} секунд")
print(f"Максимальная скорость: {max(v2):.2f} м/с")
print(f"Конечная позиция: {s2[-1]:.3f} м")
plt.savefig('s_curve_motion_profile_long_distance.png', dpi=300)
plt.show()
# Небольшое расстояние, когда не достигается макс. скорость
print("\nПример 3: Малое расстояние без выхода на макс. скорость")
distance3 = 1.0
t3, s3, v3, a3, j3 = s_curve_motion_profile(distance3, max_jerk, max_acceleration, max_velocity)
fig3 = plot_motion_profile(t3, s3, v3, a3, j3, distance3, max_jerk, max_acceleration, max_velocity)
print(f"Общее время движения: {t3[-1]:.2f} секунд")
print(f"Максимальная скорость: {max(v3):.2f} м/с")
print(f"Конечная позиция: {s3[-1]:.3f} м")
plt.savefig('s_curve_motion_profile_short_distance.png', dpi=300)
plt.show()
-
- Жесть-то какая! Eddy_Em(466 знак., 03.03.2025 23:15)
- Не должен. Табличные формы рулят. - Cкpипaч(04.03.2025 00:05)
- Твоя проблема, что ты не способен написать простое техническое
задание типа: " Мне нужно наводить телескоп на участок неба с
координатами бляблябля при помощи трёх моторов X, Y, ß. " И так
далее. А ты пытаешься выглядеть умным перед ИИ. А ИИ не студент. - Бoмж(03.03.2025 23:35)
- Когда я ему такое задание дал, он мне полную дичь выдал. Eddy_Em(536 знак., 03.03.2025 23:44)
- Жесть-то какая! Eddy_Em(466 знак., 03.03.2025 23:15)