在现代机器人技术中,强化学习(Reinforcement Learning, RL)逐渐成为一种有效的学习和决策工具。然而,在实际应用中,安全问题始终是一个重要的考虑因素。本文将探讨如何在麦轮小车上实现安全强化学习算法,以确保在学习和执行任务的过程中,小车能够避免碰撞和其他潜在危险。

一,安全强化学习

强化学习(Reinforcement Learning, RL)是一种机器学习方法,通过智能体与环境的交互,学习如何在不同情况下采取行动,以最大化某种累积奖励。强化学习广泛应用于机器人运动控制、自动驾驶等领域。在运动控制任务中,基于强化学习的智能体能够根据环境变化调整策略,以完成复杂的场景任务,并可以直接从数据中学习策略降低控制系统的设计成本。然而,由于在策略训练过程中强化学习算法可能会探索危险动作,对机器人的安全性构成潜在威胁,并且随着训练周期的增加,反复试验可能会对机器人的运动性能和使用寿命造成损害。因此,为确保运动体在训练策略和实现目标过程中的安全,安全强化学习算法被提出。

安全强化学习通过结合传统强化学习框架与先进的安全约束策略,致力于增强智能体在复杂环境中的表现与安全性。这些技术主要包括状态约束、安全层和恢复策略等,用以确保在执行任务时,智能体不仅能达成预设目标,同时也能避免对自身及环境造成潜在的危害。通过引入如状态约束,可以限制智能体的行为在安全的状态空间内进行;安全层则通过覆盖或修改原有的行为策略来防止危险行为的发生;恢复策略则在智能体偏离安全路径时提供了必要的干预手段。这些方法的综合应用显著提升了强化学习算法在实际应用中的可靠性和安全性。下图为状态约束下安全强化学习的算法框架。


Example Image

强化学习 (RL) 的重点是寻找一个的最优得策略, 以获得最大化的长期回报。它通过反 复观察智能体的状态、采取行动, 并获得奖励来反复优化策略以获得最佳策略。该方法已 成功应用于连续控制任务, 其中多次策略迭代得策略已学会稳定复杂机器人。然而, 由于RL专注于最大化长期奖励, 它很可能在学习过程中探索不安全的行为。这个特性是有问题 的尤其对于将部署在硬件上的 RL 算法, 因为不安全的学习策略可能会损坏硬件或给人类 带来伤害。本文是将现有的无模型 RL 算法(DDPG)与控制障碍函数 (CBF) 集成, 在稀疏奖励下完成运动体的安全控制, 提高学习过程中的探索效率。

由于控制障碍函数具有强约束性的特点, 将强化学习策略探索过程中的动作输出作为 标称控制器的输出, 即控制障碍函数的输入, 以保证探索过程中的实时安全, 其与环境交 互的原如图:


Example Image

运动体执行的动作为:


u_{k}(s)=u_{\theta_{k}}^{R L}(s)+u_{k}^{C B F}\left(s, u_{\theta_{k}}^{R L}\right)

在无模型强化学习的策略探索中, u_{\theta_{k}}^{RL}(s) 给出了一个动作, 试图优化长期奖励, 但可能是不安全的。CBF控制器 u_{k}^{C B F}\left(s, u_{\theta_{k}}^{R L}\right) 过滤掉强化学习动作中不安全的行为, 并提供最小的控制干预, 以确保总体控制器 u_{k}(s)安全, 同时使系统状态保持在安全集内。

CBF控制器的输出 u_{k}^{C B F}\left(s, u_{\theta_{k}}^{R L}\right)由以下公式在每个时间步长进行一次规划求解得出:


u_{k}^{C B F}=\underset{v^s, \epsilon}{\arg \min } \frac{1}{2}\left|v^s-u_{\theta_{k}}^{R L}(s)\right|^2+k_\epsilon \epsilon^2


\text { s.t. } \frac{\partial h_i}{\partial p} v^s \geq-\alpha\left(h_i(p)\right)-\epsilon, \quad \forall i \in \mathcal{N}_s

其中 a_{\mathrm{low}}^{i} \leq a_{t}^{i}+u_{\theta_{k}}^{R L(i)}\left(s_{t}\right) \leq a_{\mathrm{high}}^{i} 对输出的限幅, 在实际控制对象中, 执行器的动作空间有限, 将动作界限做为二次规划的约束条件, 其输出结果就是在界限内的安全动作, 保证运动体的安全。

二,硬件和软件配置

2.1 硬件配置


Example Image

全向移动小车的运动控制是整个实验系统的关键技术之一,它能实现全向移动小车的避障、跟踪等功能。为了保证运动体的安全性和跟踪性,需要通过运动控制器控制四个麦克纳姆轮的的转速和转向,可以控制全向移动小车沿任意方向平移或旋转,从而使小车能够跟踪其安全控制指令。车载控制器采用的是基于 ARM 的微型电脑主板树莓派 3B, 其芯片采用的是 BCM43438, 操作系统采用 Linux 系统, 内置 802.11 nWiFi, 使用 SD 卡当作储存媒体。嵌入式控制器采用的是 RoboMaster A Board 作为底层控制板, 该开发板的主控芯片为 STM32F427IIH6, 具有丰富的扩展接口和通信接口, 板载 IMU 传感器, 可以配合 M2006 直流无刷电机使用。通过 USB 转 TTL 串口模块进行连接, 实现信号的发送与接收。

2.2 软件配置

安装所依赖的环境包

pip install torch==1.10.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install pybullet==3.2.6 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install gym==0.25.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install cvxopt==1.3.2 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install qpth -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install matplotlib -i https://pypi.tuna.tsinghua.edu.cn/simple

三,安全强化学习效果

为了验证安全强化控制算法, 在如下的环境中进行安全控制实验, 运动体 (四轮小车) 需要绕过紫色障碍, 安全到达绿色区域即可获得相应奖励。


Example Image

在 Pybullet 仿真环境下基于 Pytorch 框架构建DDPG-CBF 算法,算法训练及测试的深度学习平台配置为 E5-2698 v4 CPU,Tesla V100 GPU,512G运行内存。


Example Image

物理实验系统由地面控制站、车载控制器、执行器和运动捕捉系统组成。首先,地面控制站在 Python环境下运行设计的安全控制算法,OptiTrack 运动捕捉系统通过摄像机捕捉荧光标记点的位姿,Motive 软件解算出定位系统下装有标记点的全向麦轮小车和障碍物的位姿,再将数据通过局域网实时反馈给地面控制站,通过 TCP/IP 协议发送速度指令给车载控制器,然后车载控制器通过串口协议将解算得到的车体速度发送到 STM32嵌入式控制器,完成电机速度的解算,再将电机转速控制指令发送给电机调速器,形成闭环控制。将训练好的模型迁移到地面控制站,由地面控制站发送小车的控制指令,实验系统的总体框图如图所示


Example Image

最终实现的物理实验效果为:


Example Image

四,核心代码

网络结构

class Actor(nn.Module):  # actor网络
    def __init__(self, state_dim, observation_dim, action_dim, action_bounds, offset):
        super(Actor, self).__init__()
        # actor
        self.actor = nn.Sequential(
            nn.Linear(state_dim + state_dim, 64),  # state and goal
            nn.ReLU(),
            nn.Linear(64, 64),
            nn.ReLU(),
            nn.Linear(64, action_dim),
            nn.Tanh()
        )
        # max value of actions
        self.action_bounds = action_bounds
        self.offset = offset

    def forward(self, state, goal):  # 状态,目标---动作
        return (self.actor(torch.cat([state, goal], 1)) * self.action_bounds) + self.offset


class Critic(nn.Module):  # critic网络,状态,动作,目标--价值
    def __init__(self, state_dim, observation_dim, action_dim, H):
        super(Critic, self).__init__()
        self.critic = nn.Sequential(
            nn.Linear(state_dim + action_dim + state_dim, 64),  # state action goal
            nn.ReLU(),
            nn.Linear(64, 64),
            nn.ReLU(),
            nn.Linear(64, 1),
            nn.Sigmoid()
        )
        self.H = H

    def forward(self, state, action, goal):
        # rewards are in range [-H, 0]
        return -self.critic(torch.cat([state, action, goal], 1)) * self.H

网络更新

 def update(self, buffer, n_iter, batch_size):
        actor_losses = []
        critic_losses = []
        for i in range(n_iter):
            # Sample a batch of transitions from replay buffer:
            state, obs, action, reward, next_state, goal, gamma, done = buffer.sample(
                batch_size)  # sample from replaybuffer

            # convert np arrays into tensors
            state = torch.FloatTensor(state).to(device)
            obs = torch.FloatTensor(obs).to(device)
            action = torch.FloatTensor(action).to(device)
            reward = torch.FloatTensor(reward).reshape((batch_size, 1)).to(device)
            next_state = torch.FloatTensor(next_state).to(device)
            goal = torch.FloatTensor(goal).to(device)
            gamma = torch.FloatTensor(gamma).reshape((batch_size, 1)).to(device)
            done = torch.FloatTensor(done).reshape((batch_size, 1)).to(device)

            with torch.no_grad():
                next_action = self.actor_target(next_state, goal).detach()  # 目标网络
                if self.use_cbf_layer:
                    next_action = self.diff_cbf_layer.cbf_action(next_state, obs, next_action).squeeze(0)
                target_Q = self.critic_target(next_state, next_action, goal).detach()
                target_Q = reward + ((1 - done) * gamma * target_Q).detach()

            critic_loss = self.mseLoss(target_Q, self.critic(state, action, goal))

            self.critic_optimizer.zero_grad()
            critic_loss.backward()
            self.critic_optimizer.step()

            action_real = self.actor(state, goal)
            if self.use_cbf_layer:
                action_real = self.diff_cbf_layer.cbf_action(state, obs, action_real).squeeze(0)
            actor_loss = -self.critic(state, action_real, goal).mean()
            self.actor_optimizer.zero_grad()
            actor_loss.backward()
            self.actor_optimizer.step()

            self._soft_update_target_network(self.actor_target, self.actor)
            self._soft_update_target_network(self.critic_target, self.critic)
            actor_losses.append(actor_loss)
            critic_losses.append(critic_loss)

        average_actor_loss = sum(actor_losses) / len(actor_losses)
        average_critic_loss = sum(critic_losses) / len(critic_losses)
        self.loss_f.write('{} {}\n'.format(average_actor_loss.detach().cpu().numpy(), average_critic_loss.detach().cpu().numpy()))
        self.loss_f.flush()

五,总结

本文介绍了如何在麦轮小车上实现安全强化学习算法,以确保在学习和执行任务过程中,小车能够避免碰撞和其他潜在危险。通过结合控制障碍函数(CBF)与无模型强化学习算法(如DDPG),我们构建了一个能够在保证安全的前提下进行有效探索的控制系统。在实际应用中,利用树莓派和RoboMaster A Board等硬件平台以及Pytorch和Pybullet等软件工具,成功实现了小车在仿真和物理环境中的安全避障与目标追踪。这一方法显著提升了强化学习在机器人运动控制中的安全性和可靠性。

六,参考资料