Описание проблемы

Всем привет. В последнее время я занимаюсь созданием простых анимационных роликов. Недавно столкнулся со следующей проблемой -- мой персонаж должен коснуться звонка перед входом в квартиру пальцем руки. Скелет руки представлен на Fig.1. Это трехзвенный механизм, имеющий шарнирное закрепление в точке O. Требуется, манипулируя углами α,β,γ, перевести точку A3 (эффектор) в точку E , если такое движение возможно. Данная задача имеет традиционное решение. Известны начальные значения углов. Решаем обратную задачу манипулятора, описанную в многочисленных статьях, и находим конечные значения углов α,β,γ. Каждый из интервалов между начальным и конечным значением угла разбивается на заданное число частей N . В результате получаем набор углов, с помощью которых получаем нужную траекторию движения руки. Поскольку для решения обратной задачи придётся решать нелинейные уравнения относительно углов, такой алгоритм не очень удобен. В книге Рик Парент "Компьютерная анимация" КУДИЦ-ОБРАЗ, М.:2004 предложено другое решение. К сожалению, изложение в упомянутой книге излишне абстрактно. В данной краткой статье представлена простая реализация алгоритма из этой книги. В конце статьи дана ссылка на ролик, в котором использован описанный метод.

 Fig.1 Модель скелета руки
Fig.1 Модель скелета руки

Математическая модель и решение задачи

Ограничимся плоским случаем, хотя используемые уравнения легко адаптируются к трёхмерному случаю. Введём обозначения для длин костей

Все углы отсчитываются по часовой стрелке. В этих обозначениях координаты точки A3 задаются уравнениями

Fig.2 Кинематические уравнения скелета руки

Введём вектор Vec , соединяющий точки A3 и E . Если мы правильно выбрали приращения углов dα,dβ,dγ, и точка A3 приблизилась к E на величину dVec , то упомянутые приращения связаны уравнениями (2)

Имея два уравнения для трёх неизвестных приращений, мы не можем определить эти приращения однозначно. Выход заключается в использовании псевдообратной матрицы. В этом случае мы получаем одно из возможных решений системы (2). Это решение обладает свойством минимальности длины полученного вектора. Данное обстоятельство освобождает от опасности получить большое значение для какого-либо приращения. Теперь алгоритм построения траектории выглядит следующим образом.

  • Устанавливаем начальные значения углов и коэффициент Coe<1

  • В цикле

    • Находим положение эффектора

    • Находим вектор Vec из эффектора в точку E

    • Находим dVec= Coe*Vec и вычисляем приращения углов с помощью (2)

    • Находим новые углы и проверяем расстояние от эффектора до E

Ниже приведена реализация этого алгоритма с помощью библиотеки numpy.

import numpy as np
from numpy.linalg import pinv,norm

Angl = np.float_([1.2,.7,0]) #Alpha,Beta,Gamma
E = np.float_([30,-40]) # Point E
Bones = np.float_([50,45,3]) #L1,L2,L3
Coe = 0.1
Dist = 100
def oneStep(Angl):
    Cos = np.cos(Angl)
    Sin = np.sin(Angl)
    #Current coords eq (1)
    Matr = np.float_([Cos,Sin])
    Coords =  np.dot(Matr,Bones)
    Vec = E -Coords
    Dist = norm(Vec)
    #Calculate Delta eq(2)
    Matr = np.float_([-Sin*Bones,Cos*Bones])
    PInv = pinv(Matr) #pseudoinverse matrix
    dVec = Coe *Vec # dVec
    Delta = np.dot(PInv,dVec)
    return Angl+Delta,Dist

AllAngl = []
AllAngl.append(Angl)    
while Dist >2:
    Angl,Dist = oneStep(Angl)
    AllAngl.append(Angl)

Формально, требуется дополнительно следить за тем, чтобы рука в локтевом суставе не согнулась в обратную сторону. Поскольку это делается очевидным образом, проверка условия правильности сгиба не отражена в тексте программы.
Посмотреть на работу алгоритма можно здесь Пример анимации .

Комментарии (3)


  1. Sixshaman
    30.12.2021 11:21

    >Формально, требуется дополнительно следить за тем, чтобы рука в локтевом суставе не согнулась в обратную сторону

    А вот и нет! Сгиб в обратную сторону используется довольно часто, чтобы сделать анимацию более "живой".


  1. maxiy01
    30.12.2021 12:45

    1. cartoon77 Автор
      31.12.2021 10:55

      Использование псевдообратной матрицы позволяет решать задачу с произвольным числом параметров.