Files
Handcontrol_LYT_Version_Win…/grasp_network_model.py
2026-07-16 15:24:40 +08:00

113 lines
3.9 KiB
Python

import torch
import torch.nn as nn
import torch.nn.functional as F
class CondGraspNet(nn.Module):
def __init__(self):
super(CondGraspNet, self).__init__()
# === 1. 定义输入维度 ===
# 触觉特征: 12维 (3指 * 2单元 * 2分量)
self.tactile_dim = 12
# 构型特征: 3维 (One-Hot编码: [1,0,0], [0,1,0], [0,0,1])
self.config_dim = 3
input_total_dim = self.tactile_dim + self.config_dim # 15维
# === 2. 定义网络层 (MLP结构) ===
# Layer 1: 特征融合层
# 将触觉信息和构型信息混合
self.fc1 = nn.Linear(input_total_dim, 64)
self.bn1 = nn.BatchNorm1d(64) # 批归一化: 防止梯度消失,加速训练
# Layer 2: 非线性映射层
# 增加网络宽度,拟合复杂的力学关系
self.fc2 = nn.Linear(64, 128)
self.bn2 = nn.BatchNorm1d(128)
# Layer 3: 特征压缩层
self.fc3 = nn.Linear(128, 64)
# Layer 4: 输出层 (Regression Head)
# 输出3个值: [Delta_X, Delta_Y, Delta_Theta]
self.output = nn.Linear(64, 3)
# === 3. 权重初始化 (Xavier) ===
# 这一步对小数据集训练非常重要,能让模型收敛得更快
self._init_weights()
def _init_weights(self):
for m in self.modules():
if isinstance(m, nn.Linear):
nn.init.xavier_uniform_(m.weight)
if m.bias is not None:
nn.init.constant_(m.bias, 0)
def forward(self, tactile_data, config_id_idx):
"""
前向传播函数
:param tactile_data: [Batch_Size, 12] 的触觉数据张量
:param config_id_idx: [Batch_Size] 的构型索引 (例如 [0, 2, 1...])
:return: [Batch_Size, 3] 的预测偏差
"""
# Step 1: 处理构型 ID (One-Hot Encoding)
# 必须把整数 ID (0,1,2) 变成向量 ([1,0,0]...) 才能喂给神经网络
batch_size = tactile_data.size(0)
# 创建一个全0的容器
config_one_hot = torch.zeros(batch_size, self.config_dim).to(tactile_data.device)
# 使用 scatter_ 方法进行填充
# config_id_idx 需要升维: [Batch] -> [Batch, 1]
config_one_hot.scatter_(1, config_id_idx.unsqueeze(1).long(), 1)
# Step 2: 特征拼接 (Concatenate)
# 将触觉数据和构型向量拼在一起 -> [Batch, 15]
x = torch.cat((tactile_data, config_one_hot), dim=1)
# Step 3: 通过隐藏层
x = F.relu(self.bn1(self.fc1(x))) # Linear -> BN -> ReLU
x = F.relu(self.bn2(self.fc2(x))) # Linear -> BN -> ReLU
x = F.relu(self.fc3(x)) # Linear -> ReLU (最后一层通常不用BN)
# Step 4: 输出结果
prediction = self.output(x)
return prediction
# === 单元测试 (Unit Test) ===
# 运行此文件,检查网络结构和输入输出形状是否正确
if __name__ == "__main__":
print("Testing CondGraspNet Model...")
# 1. 实例化模型
model = CondGraspNet()
print(f"Model Structure:\n{model}")
# 2. 创建模拟输入数据 (Batch Size = 8)
# 模拟8条触觉数据 (随机数)
fake_tactile = torch.randn(8, 12)
# 模拟8个构型ID (随机 0, 1, 2)
fake_config = torch.tensor([0, 0, 1, 1, 2, 2, 0, 2], dtype=torch.long)
# 3. 前向推理
print("\nProcessing forward pass...")
try:
output = model(fake_tactile, fake_config)
# 4. 验证结果
print("Input Shape (Tactile):", fake_tactile.shape)
print("Output Shape (Pred): ", output.shape) # 期望是 [8, 3]
print("\nSample Prediction (Row 0):")
print(f"Delta X: {output[0][0].item():.4f} mm")
print(f"Delta Y: {output[0][1].item():.4f} mm")
print(f"Delta θ: {output[0][2].item():.4f} deg")
if output.shape == (8, 3):
print("\n✅ 测试通过:网络维度正确!")
except Exception as e:
print(f"\n❌ 测试失败:{e}")