<jupyter_start><jupyter_text>Сферическая линейная интерполяцияИнтерполяция между двумя ориентацими по кратчайшей траектории делатется посредством операции `slerp`.<jupyter_code>from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np
from IPython.display import HTML
%matplotlib notebook
from kinematics import Vector, Quaternion, Transform
import graphics<jupyter_output><empty_output><jupyter_text>Зададим начальную и конечные ориентации:<jupyter_code>a = np.pi / 4
b = 2 / 3 * np.pi
c = np.pi * 31 / 8

s = Quaternion.identity()
e = Quaternion.from_angle_axis(a, Vector(0, 0, 1)) *\
    Quaternion.from_angle_axis(b, Vector(0, 1, 0)) *\
    Quaternion.from_angle_axis(c, Vector(1, 0, 0))<jupyter_output><empty_output><jupyter_text>Проинтерполируем между двумя ориентациями с использованием `slerp`:<jupyter_code>fig, ax = graphics.figure(2)

graphics.axis(ax, Transform(Vector.zero(), s), 0.9)
graphics.axis(ax, Transform(Vector.zero(), e), 0.9)
ar, ag, ab = graphics.axis(ax, Transform.identity(), 1)

total = 100

def animate(frame):
    progress = frame / total
    q = Quaternion.slerp(
        s,
        e,
        progress
    )
    global ar, ag, ab
    ar.remove(); ag.remove(); ab.remove()
    ar, ag, ab = graphics.axis(ax, Transform(Vector.zero(), q), 1)
    
animate(0)
fps = 25
ani = animation.FuncAnimation(
    fig,
    animate,
    frames=total,
    interval=1000.0/fps
)
HTML(ani.to_jshtml())<jupyter_output><empty_output><jupyter_text>Повторим интерполяцию, но, в этот раз, по углам Эйлера $ZYX$:<jupyter_code>fig, ax = graphics.figure(2)

graphics.axis(ax, Transform(Vector.zero(), s), 0.9)
graphics.axis(ax, Transform(Vector.zero(), e), 0.9)
ar, ag, ab = graphics.axis(ax, Transform.identity(), 1)

total = 100

def animate(frame):
    progress = frame / total
    pa = progress * a
    pb = progress * b
    pc = progress * c
    q = Quaternion.from_angle_axis(pa, Vector(0, 0, 1)) *\
        Quaternion.from_angle_axis(pb, Vector(0, 1, 0)) *\
        Quaternion.from_angle_axis(pc, Vector(1, 0, 0))
    global ar, ag, ab
    ar.remove(); ag.remove(); ab.remove()
    ar, ag, ab = graphics.axis(ax, Transform(Vector.zero(), q), 1)
    
animate(0)
fps = 25
ani = animation.FuncAnimation(
    fig,
    animate,
    frames=total,
    interval=1000.0/fps
)
HTML(ani.to_jshtml())<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1355357899195256, 'fraction_numerical': 0.025412960609911054, 'mean_word_length': 4.168490153172867, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '310354', 'license': 'MIT', 'n_tokens_mistral': 958, 'n_tokens_neox': 928, 'n_words': 205, 'path': 'Meta - SLERP.ipynb', 'repo_name': 'red-hara/jupyter-kinematics-control', 'size': '2361'}