Исходный вопрос
Я хочу создать пользовательскую функцию Lambda
с использованием керас, которая выполняет прямую кинематику шарнирного рычага.
Эта функция имеет набор углов в качестве входных данных и должнавывести вектор, содержащий положение и ориентацию конечного эффектора.
Я мог бы легко создать эту функцию в numpy;но когда я захотел переместить его в Keras, все стало сложно.
Поскольку вход и выход лямбда-функции являются тензорами, все операции должны выполняться с использованием тензоров и внутренних операций.
Проблема в том, что мне нужно создать матрицу преобразования из входных углов.
Я мог бы использовать K.cos
и K.sin
(K
- тензор потока бэкэнда) для вычисления косинусов и синусовуглы.Но проблема в том, как создать тензор, который представляет собой матрицу 4X4, которая содержит несколько ячеек, которые являются просто числами (0
или 1
), а другие являются частями тензора.Например, для вращения Z:
T = tf.convert_to_tensor( [[c, -s, 0, dX],
[s, c, 0, dY],
[0, 0, 1, dZ],
[0, 0, 0, 1]])
Здесь c
и s
вычисляются с использованием K.cos(input[3])
и K.sin(input[3])
.Это не работает.Я получаю:
ValueError: Фигуры должны иметь одинаковый ранг, но равны 1 и 0 От слияния фигуры 1 с другими фигурами.для 'lambda_1 / pack / 0' (op: 'Pack') с формами ввода: [5], [5], [], [].
Есть предложения?
Дальнейшие проблемы
Код, предоставленный @Aldream, работал нормально.Проблема заключается в том, что когда я встраиваю это в слой Lambda, я получаю сообщение об ошибке при компиляции модели.
...
self.model.add(Lambda(self.FK_Keras))
self.model.compile(optimizer="adam", loss='mse', metrics=['mse'])
Как видите, я использую класс, который содержит модель и различные функции.Сначала у меня есть вспомогательная функция, которая вычисляет матрицу преобразования:
def trig_K( angle):
r = angle*np.pi/180.0
return K.cos(r), K.sin(r)
def T_matrix_K(rotation, axis="z", translation=K.constant([0,0,0])):
c, s = trig_K(rotation)
dX = translation[0]
dY = translation[1]
dZ = translation[2]
if(axis=="z"):
T = K.stack( [[c, -s, 0., dX],
[s, c, 0., dY],
[0., 0., 1., dZ],
[0., 0., 0., 1.]], axis=0)
if(axis=="y"):
T = K.stack( [ [c, 0.,-s, dX],
[0., 1., 0., dY],
[s, 0., c, dZ],
[0., 0., 0., .1]], axis=0)
if(axis=="x"):
T = K.stack( [ [1., 0., 0., dX],
[0., c, -s, dY],
[0., s, c, dZ],
[0., 0., 0., 1.]], axis=0)
return T
Затем FK_keras вычисляет преобразование конечного эффектора:
def FK_Keras(self, angs):
# Compute local transformations
base_T=T_matrix_K(angs[0],"z",self.base_pos_K)
shoulder_T=T_matrix_K(angs[1],"y",self.shoulder_pos_K)
elbow_T=T_matrix_K(angs[2],"y",self.elbow_pos_K)
wrist_1_T=T_matrix_K(angs[3],"y",self.wrist_1_pos_K)
wrist_2_T=T_matrix_K(angs[4],"x",self.wrist_2_pos_K)
# Compute end effector transformation
end_effector_T=K.dot(base_T,K.dot(shoulder_T,K.dot(elbow_T,K.dot(wrist_1_T,wrist_2_T))))
# Compute Yaw, Pitch, Roll of end effector
y=K.tf.atan2(end_effector_T[1,0],end_effector_T[1,1])
p=K.tf.atan2(-end_effector_T[2,0],K.tf.sqrt(end_effector_T[2,1]*end_effector_T[2,1]+end_effector_T[2,2]*end_effector_T[2,2]))
r=K.tf.atan2(end_effector_T[2,1],end_effector_T[2,2])
# Construct the output tensor [x,y,z,y,p,r]
output = K.stack([end_effector_T[0,3],end_effector_T[1,3],end_effector_T[2,3], y, p, r], axis=0)
return output
Здесь self.base_pos_K и другие векторы переводов являются константами:
self.base_pos_K = K.constant(np.array([x,y,z]))
Код Tle застревает в функции компиляции и возвращает эту ошибку:
ValueError: Фигуры должны иметь одинаковый ранг, но равны 1 и 0 Из слияния фигуры 1 с другими фигурами,для 'lambda_1 / stack_1' (op: 'Pack') с формами ввода: [5], [5], [], [].
Я попытался создать быстрый тестовый код, подобный этому:
arm = Bot("")
# Articulation angles
input_data =np.array([90., 180., 45., 25., 25.])
sess = K.get_session()
inp = K.placeholder(shape=(5), name="inp")#)
res = sess.run(arm.FK_Keras(inp),{inp: input_data})
Этот код работает без ошибок.Есть кое-что о интеграции этого в лямбда-слой последовательной модели.
Решенные проблемы
Действительно, проблема была связана с тем, как Keras работает с данными.Он добавляет пакетное измерение, которое следует учитывать при реализации функции.
Я имел дело с этим по-другому, в том числе переопределением T_matrix_K для работы с этим дополнительным измерением, но я думаю, что способ, предложенный @Aldream более элегантен.
Большое спасибо @Aldream.Его ответы были весьма полезны.