Введение

В этой статье я рассмотрю свою заявку на участие в Udacity Robotics ND Project 8 - Deep RL Arm Manipulation. Цель этого проекта - создать агента DQN и определить функции вознаграждения, чтобы научить роботизированную руку выполнять две основные задачи в моделируемой среде:

  1. Прикоснитесь любой частью руки робота к интересующему объекту с точностью не менее 90%.
  2. Только основание захвата манипулятора должно касаться объекта с точностью не менее 80%.

Я рассмотрю детали реализации агента ниже.

Реализация агента DQN

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

ArmPlugin :: Load ()

В этой функции я создаю узлы камеры и столкновения и подписываю их на соответствующие темы. Также ArmPlugin :: OnUpdate () будет вызываться при каждом обновлении мира.

// Create our node for camera communication
cameraNode->Init();
cameraSub = cameraNode->Subscribe("/gazebo/" WORLD_NAME "/camera/link/camera/image", &ArmPlugin::onCameraMsg, this);                
// Create our node for collision detection
collisionNode->Init();
collisionSub = collisionNode->Subscribe("/gazebo/" WORLD_NAME "/" PROP_NAME "/tube_link/my_contact", &ArmPlugin::onCollisionMsg, this);
// Listen to the update event. This event is broadcast every simulation iteration.
this->updateConnection = event::Events::ConnectWorldUpdateBegin(boost::bind(&ArmPlugin::OnUpdate, this, _1));

ArmPlugin :: createAgent ()

Затем я создал агент DQN, предоставив конструктору гиперпараметры. Количество возможных действий определяется как удвоенное количество суставов (DOF), поскольку они могут вращаться как по часовой стрелке, так и против часовой стрелки.

// Create DQN Agent
agent = dqnAgent::Create(INPUT_WIDTH, INPUT_HEIGHT, INPUT_CHANNELS, DOF*2, OPTIMIZER, LEARNING_RATE, REPLAY_MEMORY, BATCH_SIZE, GAMMA, EPS_START, EPS_END, EPS_DECAY, USE_LSTM, LSTM_SIZE, ALLOW_RANDOM, DEBUG_DQN);

ArmPlugin :: onCollisionMsg ()

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

// Check if there is collision between the gripper and object, then issue learning reward
if((strcmp(contacts->contact(i).collision1().c_str(), COLLISION_ITEM) == 0) &&
(strcmp(contacts->contact(i).collision2().c_str(), COLLISION_POINT) == 0))
{
    rewardHistory = REWARD_WIN;
    newReward  = true;
    endEpisode = true;
    // multiple collisions in the for loop above could mess with win count
    return;
}
else {
    // Give penalty for non correct collisions
    rewardHistory = REWARD_LOSS;
    newReward  = true;
    endEpisode = true;
}

ArmPlugin :: updateAgent ()

Этот метод обновляет суставы рук на основе действия, выбранного агентом DQN. В зависимости от метода управления суставами положение суставов может увеличиваться на небольшое положение или на дельту скоростей. Я рассмотрю разницу между ними в следующем разделе.

#if VELOCITY_CONTROL
// Increase or decrease the joint velocity based on whether the action is even or odd
// Set joint velocity based on whether action is even or odd.
float velocity = vel[action/2] + actionVelDelta * ((action % 2 == 0) ? 1.0f : -1.0f);
(...)
#else
// Increase or decrease the joint position based on whether the action is even or odd
const int jointIdx = action / 2;
// Set joint position based on whether action is even or odd.
float joint = ref[jointIdx] + actionJointDelta * ((action % 2 == 0) ? 1.0f : -1.0f);
#endif

ArmPlugin :: OnUpdate ()

Этот метод вычисляет промежуточное вознаграждение, используемое для обучения агента DQN. Я использовал сглаженное скользящее среднее дельты расстояния до объекта и временного штрафа.

const float distDelta = lastGoalDistance — distGoal;
const float movingAvg = 0.9f;
const float timePenalty = 0.50f;
// compute the smoothed moving average of the delta of the distance to the goal
avgGoalDelta = (avgGoalDelta * movingAvg) + (distDelta * (1.0f — movingAvg));
rewardHistory = avgGoalDelta * REWARD_MULTIPLIER — timePenalty;
newReward = true;

Решение о совместных методах контроля

Для управления суставами рук доступны два механизма управления суставами: на основе скорости или положения. Я быстро расскажу о различиях между двумя подходами, а также о том, как каждый из них влияет на точность DQN:

На основе скорости

Управление на основе скорости учитывает физику руки, где изменения скорости определяют положение робота. Этот метод обеспечивает более реалистичные движения по сравнению с прямым контролем положения суставов.

На основе позиции

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

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

Функции вознаграждения

Я создал следующие функции вознаграждения для достижения целей №1 и №2 соответственно:

Функция вознаграждения №1 - Прикоснитесь какой-либо частью руки робота к интересующему объекту.

Для первой цели я создал функцию вознаграждения, которая награждает любое столкновение между рукой и трубкой и штрафует, когда робот сталкивается с самим собой или с землей.

Я также ввел промежуточное вознаграждение, пропорциональное расстоянию до цели, чтобы предоставить агенту след из хлебных крошек, который создает более тесную связь между действием и наградой.

Наконец, я добавил штраф по времени, который гарантирует, что агент достигнет цели как можно быстрее. Этот фактор наказывает за поведение, например, потерю времени на приближение к трубе и получение как можно большего количества промежуточных наград перед тем, как прикоснуться к ней.

Вот краткое изложение функции вознаграждения:

  1. Любая часть руки сталкивается с трубкой: +500
  2. Любая другая форма столкновения (например, рука сталкивается сама с собой): -500
  3. Захват падает на землю: -500
  4. Промежуточное вознаграждение на основе сглаженного скользящего среднего дельты расстояния до объекта и штрафа по времени

Функция награды № 2 - Только основание захвата руки робота должно касаться объекта.

Функция вознаграждения №2 очень похожа на приведенную выше и имеет небольшую модификацию награды за столкновение. Эта функция награждает только столкновения между захватом и трубкой:

  1. Захват (только) сталкивается с трубкой: +500
  2. Любая другая форма столкновения (например, рука сталкивается с самим собой или звено 2 сталкивается с трубкой): -500
  3. Захват падает на землю: -500
  4. Промежуточное вознаграждение на основе сглаженного скользящего среднего дельты расстояния до объекта и штрафа по времени

Гиперпараметры

Ниже я опишу мои гиперпараметры DQN и причины выбора.

Размер изображения на входе

Сведение пространства состояний к минимуму помогло сходимости:

#define INPUT_WIDTH 64
#define INPUT_HEIGHT 64

Обучение

Я выбрал RMSProp в качестве оптимизатора, поскольку он обычно хорошо подходит для повторяющихся нейронных сетей.

#define OPTIMIZER “RMSprop”

Я оставил скорость обучения неизменной, но если бы я столкнулся с проблемами конвергенции, я бы попытался снизить это значение.

#define LEARNING_RATE 0.1f

Чтобы сохранить стабильность пакетных градиентных обновлений, я решил сохранить пул декоррелированных переходов памяти воспроизведения и увеличил размер пакета:

#define REPLAY_MEMORY 10000
#define BATCH_SIZE 32

Сетевая архитектура

Я решил использовать архитектуру LSTM как средство отслеживания предыдущих состояний во внутренней памяти сети.

#define USE_LSTM true
#define LSTM_SIZE 256

Результаты

Результатом доволен. Я получил более 90% точности для обеих функций вознаграждения (см. Видео ниже) менее чем за 200 эпизодов. Введенный последний раз штраф был решающим для того, чтобы Рука могла быстро выполнить задание. Прежде чем ввести этот фактор, робот приближался к трубе и двигался назад, собирая как можно больше промежуточной награды, даже не касаясь трубы.

Полный код можно найти в моем репо:



Будущая работа

Это был чрезвычайно полезный проект. Из всех примеров RL, которые я видел до сих пор, это был первый, который использует Gazebo в качестве среды моделирования. Это действительно интересно, поскольку я могу использовать концепции из предыдущих уроков для создания новых миров в URDF и применять RL поверх них. Т.е. Я хочу попытаться создать гоночную трассу, чтобы машины учились проходить круг за максимально короткое время.

Кроме того, если позволяет время, я хотел бы попытаться управлять роботизированной рукой в ​​моделировании с помощью метода, основанного на скорости, поскольку он более реалистичен и позволит мне протестировать полученный DQN на реальном роботе.