机器人学:AI 在物理世界的应用
机器人学(Robotics)是 AI 与物理世界交互的学科,涉及感知、决策、控制、学习。
机器人核心架构
1. 感知(Perception)
从传感器获取环境信息:
- 视觉:摄像头、RGB-D(Kinect, RealSense)
- 触觉:力/力矩传感器、触觉皮肤
- IMU:加速度计、陀螺仪(位姿估计)
- LiDAR:激光雷达(3D 环境建模)
- 里程计:轮式编码器、视觉里程计(VO)
2. 状态估计(State Estimation)
从传感器数据估计机器人位姿和环境模型:
SLAM(Simultaneous Localization and Mapping):
传感器输入 → 特征提取 → 数据关联(匹配) → 优化(位姿+地图) → 输出:位姿 + 地图常用方法:
- 激光 SLAM:Cartographer, Hector SLAM
- 视觉 SLAM (VSLAM):ORB-SLAM3, OpenVSLAM
- 图优化:g2o, GTSAM
python
# ORB-SLAM3 示例(C++,但可通过 ROS 调用)
# 1. 启动 SLAM 节点
rosrun orb_slam3_ros Mono /path/to/vocabulary/orb_vocab.txt /path/to/config.yaml
# 2. 发布位姿话题
rostopic echo /orb_slam3/camera_pose滤波方法:
- 卡尔曼滤波(KF):线性高斯系统
- 扩展卡尔曼滤波(EKF):非线性线性化
- 粒子滤波(PF):多假设,非高斯
python
import pykalman
kf = pykalman.KalmanFilter(
transition_matrices=[[1, 1], [0, 1]], # 状态转移
observation_matrices=[[1, 0]], # 观测矩阵
initial_state_mean=[0, 0],
initial_state_covariance=[[1, 0], [0, 1]]
)
state_means, state_covariances = kf.filter(observations)3. 规划(Planning)
给定目标,规划安全高效的路径或轨迹。
路径规划(Path Planning)
搜索算法:
- A*(A-Star):启发式搜索,最优
- Dijkstra:无启发,保证最优
- RRT(Rapidly-exploring Random Tree):随机采样,适合高维空间
python
import numpy as np
def a_star(start, goal, grid):
"""grid: 0=free, 1=obstacle"""
from heapq import heappop, heappush
open_set = [(0, start)]
came_from = {}
g_score = {start: 0}
f_score = {start: heuristic(start, goal)}
while open_set:
current = heappop(open_set)[1]
if current == goal:
return reconstruct_path(came_from, current)
for neighbor in get_neighbors(current, grid):
tentative_g = g_score[current] + cost(current, neighbor)
if neighbor not in g_score or tentative_g < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g
f_score[neighbor] = tentative_g + heuristic(neighbor, goal)
heappush(open_set, (f_score[neighbor], neighbor))
return None采样算法:
- RRT:渐近最优*,后续连接优化
- PRM(Probabilistic Roadmap):先构建路网,再查询
运动规划(Motion Planning)
考虑动力学约束,生成时间轨迹:
- 时间弹性带(TEB):优化带时间参数的轨迹
- CHOMP:梯度下降优化
- TrajOpt:序列凸规划
4. 控制(Control)
执行规划好的轨迹,实时调整控制量。
经典控制:
- PID:位置/速度环
- LQR:线性二次型调节器
- MPC(模型预测控制):滚动优化
python
import control
# LQR 设计
A = np.array([[1, 1], [0, 1]]) # 状态矩阵
B = np.array([[0], [1]]) # 输入矩阵
Q = np.eye(2) * 10 # 状态权重
R = np.eye(1) * 1 # 控制权重
K, S, E = control.lqr(A, B, Q, R) # 求解 LQR 增益
# u = -K @ x5. 学习(Learning)
用数据驱动替代或增强传统模块:
- 强化学习(RL):端到端策略学习
- 模仿学习(IL):从专家演示学习
- 元学习:快速适应新任务
强化学习在机器人中的应用
为什么用 RL?
传统控制需要精确模型,但机器人动力学复杂(摩擦、柔性)。RL 直接从交互中学习策略。
常见算法
1. 深度 Q 网络(DQN)
离散动作空间:
python
import torch
import torch.nn as nn
import torch.optim as optim
from collections import deque
import random
class QNetwork(nn.Module):
def __init__(self, state_dim, action_dim):
super().__init__()
self.net = nn.Sequential(
nn.Linear(state_dim, 128),
nn.ReLU(),
nn.Linear(128, 128),
nn.ReLU(),
nn.Linear(action_dim, 1)
)
def forward(self, state):
return self.net(state)
class ReplayBuffer:
def __init__(self, capacity):
self.buffer = deque(maxlen=capacity)
def push(self, transition):
self.buffer.append(transition)
def sample(self, batch_size):
return random.sample(self.buffer, batch_size)
class DQNAgent:
def __init__(self, state_dim, action_dim):
self.q_net = QNetwork(state_dim, action_dim)
self.target_net = QNetwork(state_dim, action_dim)
self.target_net.load_state_dict(self.q_net.state_dict())
self.buffer = ReplayBuffer(10000)
self.optimizer = optim.Adam(self.q_net.parameters(), lr=1e-3)
def select_action(self, state, epsilon=0.1):
if random.random() < epsilon:
return random.randint(0, action_dim-1)
with torch.no_grad():
q_values = self.q_net(torch.FloatTensor(state))
return q_values.argmax().item()
def update(self, batch_size=64):
batch = self.buffer.sample(batch_size)
states, actions, rewards, next_states, dones = zip(*batch)
states = torch.FloatTensor(states)
actions = torch.LongTensor(actions).unsqueeze(1)
rewards = torch.FloatTensor(rewards)
next_states = torch.FloatTensor(next_states)
dones = torch.FloatTensor(dones)
current_q = self.q_net(states).gather(1, actions).squeeze()
next_q = self.target_net(next_states).max(1)[0]
target = rewards + 0.99 * next_q * (1 - dones)
loss = nn.MSELoss()(current_q, target)
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()2. PPO(Proximal Policy Optimization)
连续动作空间(关节力矩):
python
import torch
import torch.nn as nn
import torch.optim as optim
class Actor(nn.Module):
def __init__(self, state_dim, action_dim):
super().__init__()
self.net = nn.Sequential(
nn.Linear(state_dim, 256),
nn.ReLU(),
nn.Linear(256, 256),
nn.ReLU(),
)
self.mu = nn.Linear(256, action_dim) # 均值
self.log_std = nn.Parameter(torch.zeros(action_dim)) # 对数标准差
def forward(self, state):
x = self.net(state)
return self.mu(x), self.log_std.exp()
class Critic(nn.Module):
def __init__(self, state_dim):
super().__init__()
self.net = nn.Sequential(
nn.Linear(state_dim, 256),
nn.ReLU(),
nn.Linear(256, 256),
nn.ReLU(),
nn.Linear(256, 1)
)
def forward(self, state):
return self.net(state)
class PPO:
def __init__(self, state_dim, action_dim):
self.actor = Actor(state_dim, action_dim)
self.critic = Critic(state_dim)
self.optimizer = optim.Adam(list(self.actor.parameters()) + list(self.critic.parameters()), lr=3e-4)
def update(self, states, actions, old_log_probs, rewards, dones, clip_eps=0.2, epochs=10):
# 计算 advantages
values = self.critic(states).squeeze()
returns = compute_returns(rewards, dones) # Generalized Advantage Estimation
advantages = returns - values.detach()
advantages = (advantages - advantages.mean()) / (advantages.std() + 1e-8)
for _ in range(epochs):
new_log_probs, entropy = self.actor.evaluate(states, actions)
ratio = (new_log_probs - old_log_probs).exp()
surr1 = ratio * advantages
surr2 = torch.clamp(ratio, 1-clip_eps, 1+clip_eps) * advantages
actor_loss = -torch.min(surr1, surr2).mean() - 0.01 * entropy.mean()
critic_loss = nn.MSELoss()(values, returns)
loss = actor_loss + 0.5 * critic_loss
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()机器人学习框架
1. ROS / ROS 2(Robot Operating System)
事实标准机器人中间件:
ros2 topic list # 查看话题
ros2 topic echo /camera/image_raw # 查看图像
ros2 service list # 查看服务
ros2 node list # 查看节点包管理:rosdep install --from-paths src --rosdistro humble -r
2. Gym / Gymnasium
强化学习环境标准接口:
python
import gymnasium as gym
env = gym.make('FetchPickAndPlace-v2')
obs, info = env.reset()
for _ in range(1000):
action = env.action_space.sample() # 随机策略
obs, reward, terminated, truncated, info = env.step(action)机器人环境:
- PyBullet:物理仿真,内置 Kuka、Fetch 等机器人
- MuJoCo(DeepMind):高质量物理,现在开源免费
- Isaac Gym(NVIDIA):GPU 加速,大规模并行
python
import gymnasium as gym
import robodesk # 或以下之一
env = gym.make('AdroitHandDoor-v1') # 灵巧手开门
env = gym.make('ShadowHandGrasp-v0') # Shadow-hand 抓取
env = gym.make('XArm7Reach-v0') # XArm7 机械臂3. PyRobot
Facebook 的机器人 API 封装:
python
from pyrobot.robots import Fetch
robot = Fetch()
robot.base.go_to(1, 0, 0) # 移动到 (1, 0, 0)
robot.arm.traj_play('/path/to/trajectory.txt')实战:机械臂抓取
任务
随机位置抓取物体(如块、球)。
解决方案
感知:
- RGB-D 相机(RealSense)
- 目标检测(YOLO)→ 位姿估计(ICP)
规划:
- 抓取点采样(基于深度图)
- 逆运动学(IK)求解关节角度
控制:
- 关节空间 PID
- 末端轨迹跟踪
代码结构(ROS 2 + Python)
python
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from geometry_msgs.msg import PoseStamped
from control_msgs.action import FollowJointTrajectory
import cv2
import numpy as np
class PickPlaceNode(Node):
def __init__(self):
super().__init__('pick_place')
self.image_sub = self.create_subscription(Image, '/camera/color/image_raw', self.image_callback, 10)
self.pose_pub = self.create_publisher(PoseStamped, '/target_pose', 10)
self.trajectory_client = ActionClient(self, FollowJointTrajectory, '/arm_controller/follow_joint_trajectory')
def image_callback(self, msg):
# 1. RGB-D → 目标检测(YOLO)
img = self.bridge.imgmsg_to_cv2(msg, "bgr8")
detections = yolo_model(img)
# 2. 深度图 + 位姿估计
depth = self.get_depth()
target_pose = self.estimate_pose(detections[0], depth)
# 3. 发送目标位姿
pose_msg = PoseStamped()
pose_msg.pose = target_pose
self.pose_pub.publish(pose_msg)
# 4. 发送抓取轨迹(预定义或 IK 求解)
self.send_grasp_trajectory(target_pose)
def main():
rclpy.init()
node = PickPlaceNode()
rclpy.spin(node)仿真到现实(Sim2Real)
仿真环境与真实世界有差异(dynamics gap),策略直接部署会失败。
域随机化(Domain Randomization)
在仿真中随机化参数,提升鲁棒性:
python
# PyBullet 中的随机化
import pybullet as p
p.setAdditionalSearchPath(pybullet_data.getDataPath())
p.loadURDF("plane.urdf", [0, 0, -0.1]) # 地面
# 随机化摩擦、质量、光照等
for body_id in object_ids:
p.changeDynamics(body_id, -1, lateralFriction=np.random.uniform(0.3, 0.8))
p.changeVisualShape(body_id, -1, rgbaColor=np.random.rand(3).tolist() + [1])渐进式域适应(Progressive Nets)
仿真 → 仿真(随机化增强) → 真实
在线微调
在真实世界少量交互,微调策略:
python
# 使用离线 RL 预训练 + 在线微调
pretrained_policy = offline_rl_train(sim_data)
real_policy = online_fine_tune(pretrained_policy, real_robot, epochs=100)具身智能与基础模型
新兴方向:将大语言模型(LLM)作为机器人的"大脑"。
示例:Google RT-2 (Robotic Transformer 2)
- 用互联网图像-文本数据预训练
- 指令跟随: "把红色方块放到蓝色盒子里"
- 零样本 generalization:无需机器人数据训练
python
# 伪代码
llm = GPT4V() # 多模态大模型
def robot_policy(observation, instruction):
# observation: RGB-D + 关节状态
prompt = f"""
你是一个机器人控制器。给定图片和指令,输出动作。
指令:{instruction}
当前状态:{observation}
可能的动作:
1. 移动到 (x, y, z)
2. 抓取
3. 释放
4. 旋转 45°
输出格式:JSON {{"action": "...", "params": ...}}
"""
response = llm.generate(prompt)
action = parse_json(response)
return execute_action(action)优点:通用性强,无需大量机器人数据。 缺点:延迟高(LLM 推理)、安全性未知、难以低层控制。
开源项目与数据集
开源硬件
- UR5e / UR3:Universal Robots,6 自由度协作臂
- Franka Emika Panda:7 自由度,力控优秀
- TurtleBot3:入门移动机器人
- Unitree Go1:四足机器人,价格亲民
仿真环境
| 环境 | 特点 |
|---|---|
| PyBullet | 易用,免费,多种机器人 |
| MuJoCo | 物理真实感强,现在免费 |
| Isaac Sim | NVIDIA,GPU 加速,照片级渲染 |
| ** CoppeliaSim (V-REP)** | 老牌,支持多机器人 |
数据集
| 数据集 | 内容 | 用途 |
|---|---|---|
| RLBench | 100+ 机器人任务(Sim) | 模仿学习 / RL |
| BEHAVIOR | 120 个日常任务 | 具身 AI |
| Oxford RobotCar | 真实驾驶数据 | SLAM, 自动驾驶 |
| KITTI | 自动驾驶 | 视觉、激光雷达 |
| Matterport3D | 3D 室内场景 | 导航 |
工业应用案例
1. 仓储物流(Amazon Robotics)
- Kiva 机器人:货架到人
- 感知:2D 激光 + 里程计 + 二维码定位
- 规划:多机器人路径规划(避免碰撞)
- 控制:差速轮,导航到货架
2. 汽车制造(特斯拉)
- 机器人焊接/涂胶:轨迹精确,力控
- 感知:3D 视觉定位工件
- 规划:离线编程(Offline Programming),示教再现
3. 手术机器人(达芬奇)
- 主从控制:医生操作主手,机械臂从手复制
- 力反馈:触觉反馈,医生感受组织阻力
- 稳定性: tremor filtering(滤除手抖)
挑战与未来
挑战
- Sim2Real Gap:仿真到现实性能下降
- 安全性:碰撞检测、紧急停止、人机协作
- 长尾场景:罕见情况(如电缆缠绕、轮子打滑)
- 能耗:移动机器人续航有限
未来方向
- 多模态基础模型:视觉-语言-动作统一(RT-2, PALIM)
- 自监督学习:机器人自己探索,无需人工标注
- 人形机器人:Tesla Optimus, Boston Dynamics Atlas
- 群体智能:多机器人协作(蜂群、编队)
入门建议
- 仿真先行:PyBullet + Gymnasium,不用真机器人
- ROS 2:学习机器人中间件,工业界标准
- 算法:从经典控制(PID)→ 运动规划(RRT)→ 强化学习(PPO)
- 硬件:TurtleBot3 或 UR5e(如果有条件)
- 课程:Coursera "Robotics Specialization"(Penn),"CS237B"(Berkeley)
机器人学是软硬结合、理论与实践并重的学科,动手写代码 + 仿真实验是关键!
