Вопрос или проблема
У меня есть решатель обратной кинематики. Я хочу сместить значение угла одного сустава так, чтобы оно хотя бы приблизилось к определенному значению, при котором этот угол приведет к тому, что звено будет плоским или параллельным земле. Скрипт работает хорошо, но моя проблема в том, что fmincon останавливает итерацию, я думаю, как только достигается значение по умолчанию TolFun. Значение смещения составляет около ±0.17 радиан или ±10 градусов.
Я пытался использовать очень маленькое значение TolFun, например, 1e-12, но когда итерация сходится, угол, который я хочу сместить, все равно не достигает желаемого значения или не приближается к нему. Я пробовал добавлять пороговое значение fval и использовать цикл while, но, как мне кажется, критерий остановки TolFun все еще превосходит это, так как при запуске скрипта почти достигаются аналогичные сходимости. Мне нужна помощь в том, как реализовать смещение. Вот фрагмент кода:
function A = transformation_matrix(theta, alpha, a, d)
A = [[cos(theta), -cos(alpha) * sin(theta), sin(alpha) * sin(theta), a * cos(theta)];
[sin(theta), cos(alpha) * cos(theta), -sin(alpha) * cos(theta), a * sin(theta)];
[0, sin(alpha), cos(alpha), d];
[0, 0, 0, 1]];
end
function position = forward_kinematics(joint_angles)
theta2 = joint_angles(1);
theta3 = joint_angles(2);
theta4 = joint_angles(3);
theta5 = joint_angles(4);
theta6 = joint_angles(5);
A1 = transformation_matrix(0, 0, 0, 148);
A2 = transformation_matrix(theta2, pi/2, 0, 152);
A3 = transformation_matrix(theta3, 0, 250, 0);
A4 = transformation_matrix(theta4, 0, 160, 0);
A5 = transformation_matrix(theta5 + pi/2, pi/2, 0, 0);
A6 = transformation_matrix(theta6, 0, -75, 160);
position_matrix = A1 * A2 * A3 * A4 * A5 * A6 * [0; 0; 0; 1];
%threshold = 1e-8; % Малый порог для округления до нуля
%position_matrix(abs(position_matrix) < threshold) = 0; % Установить маленькие значения в ноль
position = position_matrix(1:3);
end
function error = objective_function(joint_angles, target, initial_guess, is_first_run)
theta3 = joint_angles(2);
theta4 = joint_angles(3);
theta5 = -(theta3 + theta4);
position = forward_kinematics(joint_angles);
error = norm(position - target);
bias_theta5 = abs(joint_angles(4) - theta5);
disp('Смещение угла 5:');
disp(bias_theta5);
error += 1 * bias_theta5 % смещение для приближения угла 5 к значению, параллельному начальной координате Y
if ~is_first_run
error += 0.1 * norm(joint_angles - initial_guess); % Штраф за отклонение от начального предположения
end
end
function error = objective_function(joint_angles, target, initial_guess, is_first_run)
theta3 = joint_angles(2);
theta4 = joint_angles(3);
theta5 = -(theta3 + theta4);
position = forward_kinematics(joint_angles);
error = norm(position - target);
bias_theta5 = abs(joint_angles(4) - theta5);
disp('Смещение угла 5:');
disp(bias_theta5);
error += 1 * bias_theta5; % Смещение для приближения угла 5 к значению, параллельному начальной координате Y
if ~is_first_run
error += 0.1 * norm(joint_angles - initial_guess); % Штраф за отклонение от начального предположения
end
end
function [joint_angles, exitflag] = inverse_kinematics(target_position, initial_guess, is_first_run)
options = optimset('Display', 'final', 'MaxIter', 2000); % Пропускаем 'TolFun'
% Ограничения для начальных значений первых четырех углов
initial_lb = [-(5/6) * pi; -(1/6) * pi; -(11/18) * pi; -(1/2) * pi];
initial_ub = [ (5/6) * pi; (5/9) * pi; 0; (1/2) * pi];
if is_first_run
lb = initial_lb; % Используем начальные нижние границы
ub = initial_ub; % Используем начальные верхние границы
else
% Обновляем границы на основе конвергированных углов суставов
lb = initial_lb - initial_guess(1:4); % Вычитаем конвергированные значения
ub = initial_ub - initial_guess(1:4); % Вычитаем конвергированные значения
end
initial_guess_4 = initial_guess(1:4);
%max_iter = 100; % Устанавливаем максимальное количество итераций
fval_threshold = 0.17; % Критерий остановки для fval
iter = 0;
converged = false;
while ~converged %&& iter < max_iter
% Оптимизируем theta2, theta3, theta4
[joint_angles_4, fval, exitflag] = fmincon(@(j) objective_function([j; 0], target_position, initial_guess, is_first_run), ...
initial_guess_4, [], [], [], [], lb, ub, [], options);
% Проверяем критерий остановки по fval
if fval < fval_threshold
converged = true; % Мы достигли желаемого fval
end
initial_guess_4 = joint_angles_4; % Обновляем начальное предположение для следующей итерации
%iter = iter + 1;
end
joint_angles = [joint_angles_4; 0]; % Устанавливаем theta 6 в ноль
% Отображаем результат
if converged
fprintf('Сошлось с fval: %f\n', fval);
else
fprintf('Достигнуто максимальное количество итераций без достижения желаемого fval.\n');
end
end
Ответ или решение
Оптимизация многослойной задачи: Ближайшее к желаемым значениям при решении обратной кинематики
При решении задачи обратной кинематики с помощью fmincon
существует необходимость в точной настройке результирующих углов сочленений, особенно если необходимо достижение определённых значений, таких как горизонтальное положение конечного звена. Ваша проблема, заключающаяся в необходимости учитывать вам требуемое биас значение, а также остановка итераций при достижении значения TolFun, может быть решена с учетом ряда важных аспектов.
1. Параметры настройки и их влияние
Отметим, что параметр TolFun может влиять на эффективность поискового алгоритма, поскольку fmincon
завершает выполнение, как только изменение значения целевой функции меньше данного порога. По умолчанию, значение TolFun может быть достаточно высоким, что не позволяет достигнуть желаемых точностей.
Рекомендую установить параметр TolFun в соответствии с заданными вами диапазонами углов:
options = optimset('Display', 'final', 'MaxIter', 2000, 'TolFun', 1e-12);
Тем не менее, просто уменьшение TolFun может не решить вашу проблему, так как может потребоваться дополнительное соответствие целевой функции условиям ограничения.
2. Структура целевой функции
Необходимо настроить вашу целевую функцию так, чтобы она более эффективно учитывала требуемую предвзятость. Например, функцию objective_function
следует переработать с учетом необходимого предвзятого значения, чтобы целевая функция penalized bias добавлялась в более адекватных рамках.
Измените подход к формированию error
:
error = norm(position - target);
bias_theta5 = abs(joint_angles(4) - desired_theta5); % где desired_theta5 - целевое значение
error += penalty_factor * bias_theta5; % добавьте вес в зависимости от ваших нужд
Где desired_theta5
— это предопределенное значение, к которому вы хотите приблизить результат.
3. Ограничения на значения сочленений
При использовании fmincon
, стоит убедиться, что ограничения не противоречат сохранению этого допустимого диапазона. Управление не только диапазонами, но и введение дополнительных ограничений могут стать ключом к управлению результивной функцией.
Убедитесь, что значения нижней и верхней границы сочленений${lb}$ и ${ub}$ корректно настроены, чтобы они не вводили более строгие условия, чем это необходимо для достижения результата:
if is_first_run
lb = initial_lb; % Используем начальные нижние границы
ub = initial_ub; % Используем начальные верхние границы
else
lb = initial_lb; % Убедитесь, что углы не выходят за пределы
ub = initial_ub;
end
4. Введение дополнительных критериев остановки
Ваш подход с использованием цикла while может быть правильным. Рассмотрите возможность введения дополнительных параметров для завершения, например, контроля на основе error
:
if fval < fval_threshold && bias_theta5 < tolerance_value
converged = true; % Достигли как fval, так и требования по углу
end
Это поможет избежать преждевременной остановки алгоритма, если целевая функция не отвечает текущим требованиям по дополнительным преференциям.
Заключение
Изменив настройки TolFun
, пересмотрев структуру целевой функции для учета биаса и улучшив управление ограничениями сочленений, можно ожидать более точных и спрогнозированных результатов в обратной кинематике. Не забывайте о необходимости тестирования и правки формул в соответствии с реальными значениями и физическими параметрами системы. Для достижения оптимального результата комбинируйте различные стратегии, чтобы найти наиболее подходящее решение для вашей задачи.