CARLA
 
载入中...
搜索中...
未找到
pytorch.cpp
浏览该文件的文档.
1// Copyright (c) 2022 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB).
2// This work is licensed under the terms of the MIT license.
3// For a copy, see <https://opensource.org/licenses/MIT>.
4
5#define _GLIBCXX_USE_CXX11_ABI 0
6
7#include "pytorch.h"
8
9#include <torch/torch.h>
10#include <torch/script.h>
11#include <torchscatter/scatter.h>
12#include <torchcluster/cluster.h>
13#include <torch/csrc/jit/passes/tensorexpr_fuser.h>
14#include <c10/cuda/CUDACachingAllocator.h>
15#include <string>
16#include <vector>
17#include <ostream>
18#include <sstream>
19// 定义一个空的函数,用于添加标记
20void add_mark(const std::string &text) {
21
22}
23// 定义一个命名空间 carla,其中包含另一个命名空间 learning
24namespace carla {
25namespace learning {
26 // 测试学习功能的函数,打印CUDA版本信息
28 {
29 std::ostringstream ss;// 创建一个字符串流
30 std::cout << "cuda version " << cluster::cuda_version() << std::endl;// 打印cluster命名空间中定义的cuda_version()函数的返回值
31 std::cout << "cuda version " << scatter::cuda_version() << std::endl;// 打印scatter命名空间中定义的cuda_version()函数的返回值
32 // 下面的代码被注释掉了,如果取消注释,将创建一个3x3的单位张量并打印
33 // torch::Tensor tensor = torch::eye(3);
34 // std::cout << tensor << std::endl;
35 }
36// 定义一个函数,用于将WheelInput结构体中的数据转换为PyTorch张量,并将这些张量打包成一个IValue元组返回
37 torch::jit::IValue GetWheelTensorInputs(WheelInput& wheel) {
38 // 从wheel结构体的particles_positions成员变量创建一个张量,表示粒子的位置。
39 // particles_positions是一个指向粒子位置数据的指针,num_particles是粒子的数量,每个粒子有3个位置坐标(x, y, z)
40 at::Tensor particles_position_tensor =
41 torch::from_blob(wheel.particles_positions,
42 {wheel.num_particles, 3}, torch::kFloat32);
43 // 从wheel结构体的particles_velocities成员变量创建一个张量,表示粒子的速度。
44 // particles_velocities是一个指向粒子速度数据的指针,格式与粒子位置相同
45 at::Tensor particles_velocity_tensor =
46 torch::from_blob(wheel.particles_velocities,
47 {wheel.num_particles, 3}, torch::kFloat32);
48 // 从wheel结构体的wheel_positions成员变量创建一个张量,表示车轮的位置。
49 // wheel_positions是一个指向车轮位置数据的指针,车轮位置由3个坐标(x, y, z)表示
50 at::Tensor wheel_positions_tensor =
51 torch::from_blob(wheel.wheel_positions,
52 {3}, torch::kFloat32);
53 // 从wheel结构体的wheel_oritentation成员变量创建一个张量,表示车轮的朝向
54 at::Tensor wheel_oritentation_tensor =
55 torch::from_blob(wheel.wheel_oritentation,
56 {4}, torch::kFloat32);
57 // 从wheel结构体的wheel_linear_velocity成员变量创建一个张量,表示车轮的线速度。
58 // wheel_linear_velocity是一个指向车轮线速度数据的指针,由3个分量(x, y, z)表示
59 at::Tensor wheel_linear_velocity_tensor =
60 torch::from_blob(wheel.wheel_linear_velocity,
61 {3}, torch::kFloat32);
62 // 从wheel结构体的wheel_angular_velocity成员变量创建一个张量,表示车轮的角速度。
63 // wheel_angular_velocity是一个指向车轮角速度数据的指针,同样由3个分量(x, y, z)表示
64 at::Tensor wheel_angular_velocity_tensor =
65 torch::from_blob(wheel.wheel_angular_velocity,
66 {3}, torch::kFloat32);
67 // 将上述所有张量放入一个IValue向量中
68 std::vector<torch::jit::IValue> Tuple
69 {particles_position_tensor, particles_velocity_tensor, wheel_positions_tensor,
70 wheel_oritentation_tensor, wheel_linear_velocity_tensor, wheel_angular_velocity_tensor};
71 return torch::ivalue::Tuple::create(Tuple);// 使用torch::ivalue::Tuple::create方法将IValue向量打包成一个IValue元组,并返回
72 }
73// 定义一个函数,用于从粒子力和轮力张量中提取信息,并填充到一个WheelOutput结构体中
75 const at::Tensor &particle_forces, // 输入参数:粒子力的张量
76 const at::Tensor &wheel_forces ) {// 输入参数:轮力的张量
77 WheelOutput result;
78 // 获取轮力张量的数据指针,并假定数据类型为float
79 const float* wheel_forces_data = wheel_forces.data_ptr<float>();
80 // 从轮力张量中提取x, y, z方向的轮力和轮扭矩,并存储到result结构体中
81 result.wheel_forces_x = wheel_forces_data[0];
82 result.wheel_forces_y = wheel_forces_data[1];
83 result.wheel_forces_z = wheel_forces_data[2];
84 result.wheel_torque_x = wheel_forces_data[3];
85 result.wheel_torque_y = wheel_forces_data[4];
86 result.wheel_torque_z = wheel_forces_data[5];
87 // 获取粒子力张量的数据指针,并假定数据类型为float
88 const float* particle_forces_data = particle_forces.data_ptr<float>();
89 // 定义粒子力的维度数量(假设为3D空间,即x, y, z三个方向)
90 int num_dimensions = 3;
91 // 获取粒子力张量中粒子的数量
92 int num_particles = particle_forces.sizes()[0];
93 // 为存储粒子力的向量预留空间,大小为粒子数量乘以每个粒子的维度数量
94 result._particle_forces.reserve(num_particles*num_dimensions);
95 // 遍历每个粒子,将其x, y, z方向的力添加到result结构体中的粒子力向量中
96 for (int i = 0; i < num_particles; i++) {
97 result._particle_forces.emplace_back(
98 particle_forces_data[i*num_dimensions + 0]);
99 result._particle_forces.emplace_back(
100 particle_forces_data[i*num_dimensions + 1]);
101 result._particle_forces.emplace_back(
102 particle_forces_data[i*num_dimensions + 2]);
103 }
104 return result;
105 }
106// 该函数接收两个常量引用类型的at::Tensor参数,并返回一个WheelOutput 类型的结果
108 const at::Tensor &particle_forces,
109 const at::Tensor &wheel_forces) {
110 WheelOutput result;
111 const float* wheel_forces_data = wheel_forces.data_ptr<float>();
112 // 从wheel_forces中提取轮子X Y Z方向的力
113 result.wheel_forces_x = wheel_forces_data[0];
114 result.wheel_forces_y = wheel_forces_data[1];
115 result.wheel_forces_z = wheel_forces_data[2];
116 // 从 particle_forces中提取每个粒子的力
117 const float* particle_forces_data = particle_forces.data_ptr<float>();
118 int num_dimensions = 3;
119 int num_particles = particle_forces.sizes()[0];
120 result._particle_forces.reserve(num_particles*num_dimensions);
121 for (int i = 0; i < num_particles; i++) {
122 result._particle_forces.emplace_back(
123 particle_forces_data[i*num_dimensions + 0]);
124 result._particle_forces.emplace_back(
125 particle_forces_data[i*num_dimensions + 1]);
126 result._particle_forces.emplace_back(
127 particle_forces_data[i*num_dimensions + 2]);
128 }
129 return result;
130 }
131
132 // 定义一个名为NeuralModelImpl的结构体,它封装了与神经网络模型相关的数据和操作
134 {
136 // 成员变量:一个PyTorch JIT编译的脚本模块,用于加载和执行神经网络
137 torch::jit::script::Module module;
139 // 成员变量:一个存储粒子位置张量的向量,每个张量代表一组粒子的位置信息
140 std::vector<at::Tensor> particles_position_tensors;
141 // 成员变量:一个存储粒子速度张量的向量,每个张量代表一组粒子的速度信息
142 std::vector<at::Tensor> particles_velocity_tensors;
143 // 成员函数:获取与指定车轮相关的输入张量,这些张量将作为神经网络的输入
144 // 参数:
145 // - wheel:一个引用传递的WheelInput结构体,包含了车轮的输入信息
146 // - wheel_idx:指定车轮的索引,用于从可能的多组车轮输入中选择一组
147 // 返回值:
148 // - 一个torch::jit::IValue对象,它封装了神经网络所需的输入张量(或张量的组合)
149 // 这个返回值可以直接被传递给torch::jit::script::Module的forward方法
150 torch::jit::IValue GetWheelTensorInputsCUDA(WheelInput& wheel, int wheel_idx);
151 };
152 torch::jit::IValue NeuralModelImpl::GetWheelTensorInputsCUDA(WheelInput& wheel, int wheel_idx)
153 {// 从WheelInput结构体中的粒子位置数组创建一个张量
154 at::Tensor particles_position_tensor =
155 torch::from_blob(wheel.particles_positions, // 指向数据的指针
156 {wheel.num_particles, 3}, torch::kFloat32);// 张量的形状
157 // 从WheelInput结构体中的粒子速度数组创建一个张量,过程与位置张量类似
158 at::Tensor particles_velocity_tensor =
159 torch::from_blob(wheel.particles_velocities,
160 {wheel.num_particles, 3}, torch::kFloat32);
161// 创建轮子位置张量
162 at::Tensor wheel_positions_tensor =
163 torch::from_blob(wheel.wheel_positions, // 原始数据,表示轮子的位置
164 {3}, torch::kFloat32);// 张量的维度为3
165// 创建轮子方向张量
166 at::Tensor wheel_oritentation_tensor =
167 torch::from_blob(wheel.wheel_oritentation, // 原始数据,表示轮子的方向
168 {4}, torch::kFloat32);// 表示张量维度为4
169// 创建轮子线性速度张量
170 at::Tensor wheel_linear_velocity_tensor =
171 torch::from_blob(wheel.wheel_linear_velocity, // 原始数据,表示轮子的线性速度
172 {3}, torch::kFloat32);// 表示张量的维度为3
173// 创建轮子角速度张量
174 at::Tensor wheel_angular_velocity_tensor =
175 torch::from_blob(wheel.wheel_angular_velocity, // 原始数据,表示轮子的角速度
176 {3}, torch::kFloat32);// 表示张量的维度为3
177// 将所有准备好的张量以及粒子数量(作为一个标量张量或直接作为整数)放入一个向量中
178 std::vector<torch::jit::IValue> Tuple
179 {particles_position_tensor.cuda(), particles_velocity_tensor.cuda(), wheel_positions_tensor.cuda(),
180 // 修正了变量名以匹配之前的声明
181 wheel_oritentation_tensor.cuda(), wheel_linear_velocity_tensor.cuda(), wheel_angular_velocity_tensor.cuda(),
182 wheel.num_particles};// 直接作为整数传递,而不是张量
183 };
184 return torch::ivalue::Tuple::create(Tuple);
185 }
186
187 NeuralModel::NeuralModel() {
188 // 使用std::make_unique初始化Model成员变量,它是一个指向NeuralModelImpl类型的unique_ptr
189 Model = std::make_unique<NeuralModelImpl>();
190 }
191 void NeuralModel::LoadModel(char* filename, int device) {
192 // 禁用TensorExpr融合器,可能是为了避免某些与模型加载或执行不兼容的问题
193 torch::jit::setTensorExprFuserEnabled(false);
194 // 将传入的char*类型文件名转换为std::string,便于后续操作。
195 std::string filename_str(filename);
196 // 打印正在加载的模型文件名
197 std::cout << "loading " << filename_str << std::endl;
198 try {
199 // 使用torch::jit::load加载模型文件,并将其存储在ModelImpl类的module成员中
200 Model->module = torch::jit::load(filename_str);
201 // 构造CUDA设备字符串,格式为"cuda:X",其中X是传入的设备ID
202 std::string cuda_str = "cuda:" + std::to_string(device);
203 // 将模型移动到指定的CUDA设备上执行
204 // std::cout << "Using CUDA device " << cuda_str << std::endl;
205 // Model->module.to(at::Device(cuda_str));
206 } catch (const c10::Error& e) {
207 // 如果加载模型过程中发生异常(例如文件不存在、格式错误等),则捕获异常并打印错误信息
208 std::cout << "Error loading model: " << e.msg() << std::endl;
209 }
210 // 打印模型加载完成的消息
211 std::cout << "loaded " << filename_str << std::endl;
212 }
213
214 void NeuralModel::SetInputs(Inputs input) {
215 _input = input;
216 }
217
218// 定义一个成员函数 Forward,用于在神经网络模型中执行前向传播
219 void NeuralModel::Forward() {
220 // 创建一个存储PyTorch输入数据的向量
221 std::vector<torch::jit::IValue> TorchInputs;
222 // 将四个轮子的输入数据转换为Tensor并添加到输入向量中
223 TorchInputs.push_back(GetWheelTensorInputs(_input.wheel0));
224 TorchInputs.push_back(GetWheelTensorInputs(_input.wheel1));
225 TorchInputs.push_back(GetWheelTensorInputs(_input.wheel2));
226 TorchInputs.push_back(GetWheelTensorInputs(_input.wheel3));
227 // 将驾驶控制输入(转向、油门、刹车)转换为Tensor并添加到输入向量中
228 auto drv_inputs = torch::tensor(
229 {_input.steering, _input.throttle, _input.braking}, torch::kFloat32); //steer, throtle, brake
230 TorchInputs.push_back(drv_inputs);
231 // 如果地形类型输入有效,则将其添加到输入向量中
232 if (_input.terrain_type >= 0) {
233 TorchInputs.push_back(_input.terrain_type);
234 }
235 // 将是否输出详细信息的标志添加到输入向量中
236 TorchInputs.push_back(_input.verbose);
237// 定义一个变量用于存储模型的输出
238 torch::jit::IValue Output;
239 // 尝试执行模型的前向传播,并捕获可能发生的错误
240 try {
241 Output = Model->module.forward(TorchInputs);
242 } catch (const c10::Error& e) {
243 // 如果发生错误,打印错误信息
244 std::cout << "Error running model: " << e.msg() << std::endl;
245 }
246// 将模型的输出转换为元组,并提取其中的Tensor
247 std::vector<torch::jit::IValue> Tensors = Output.toTuple()->elements();
248 // 对每个轮子的输出Tensor进行处理,并更新输出结构体中的相应字段
250 Tensors[0].toTensor().cpu(), Tensors[4].toTensor().cpu() );
251 _output.wheel1 = GetWheelTensorOutput(
252 Tensors[1].toTensor().cpu(), Tensors[5].toTensor().cpu() );
253 _output.wheel2 = GetWheelTensorOutput(
254 Tensors[2].toTensor().cpu(), Tensors[6].toTensor().cpu() );
255 _output.wheel3 = GetWheelTensorOutput(
256 Tensors[3].toTensor().cpu(), Tensors[7].toTensor().cpu() );
257
258 }
259 void NeuralModel::ForwardDynamic() {
260 {
261
262 std::vector<torch::jit::IValue> TorchInputs;
263 TorchInputs.push_back(GetWheelTensorInputs(_input.wheel0));
264 TorchInputs.push_back(GetWheelTensorInputs(_input.wheel1));
265 TorchInputs.push_back(GetWheelTensorInputs(_input.wheel2));
266 TorchInputs.push_back(GetWheelTensorInputs(_input.wheel3));
267 auto drv_inputs = torch::tensor(
268 // 输入参数:转向、油门、刹车
269 {_input.steering, _input.throttle, _input.braking}, torch::kFloat32); //steer, throtle, brake
270 // 数据类型为float32
271 TorchInputs.push_back(drv_inputs);
272 if (_input.terrain_type >= 0) {
273 TorchInputs.push_back(_input.terrain_type);
274 }
275 TorchInputs.push_back(_input.verbose);
276
277 torch::jit::IValue Output;
278 try {
279 // 调用Model的forward函数,传入TorchInputs,结果存储在Output中
280 Output = Model->module.forward(TorchInputs);
281 } catch (const c10::Error& e) {
282 // 如果捕获到错误,打印错误信息
283 std::cout << "Error running model: " << e.msg() << std::endl;
284 }
285
286 std::vector<torch::jit::IValue> Tensors = Output.toTuple()->elements();
287 // 获取车轮0的输出动态张量
288 _output.wheel0 = GetWheelTensorOutputDynamic(
289 Tensors[0].toTensor().cpu(), Tensors[4].toTensor().cpu());
290 // 获取车轮1的输出动态张量
291 _output.wheel1 = GetWheelTensorOutputDynamic(
292 Tensors[1].toTensor().cpu(), Tensors[5].toTensor().cpu());
293 // 获取车轮2的输出动态张量
294 _output.wheel2 = GetWheelTensorOutputDynamic(
295 Tensors[2].toTensor().cpu(), Tensors[6].toTensor().cpu());
296 // 获取车轮3的输出动态张量
297 _output.wheel3 = GetWheelTensorOutputDynamic(
298 Tensors[3].toTensor().cpu(), Tensors[7].toTensor().cpu());
299
300 }
301
302 c10::cuda::CUDACachingAllocator::emptyCache();
303
304 }
305// NeuralModel类的ForwardDynamic成员函数,用于执行模型的动态前向传播
306 void NeuralModel::ForwardCUDATensors()
307 {
308 // 创建一个用于存储模型输入数据的向量TorchInputs
309 std::vector<torch::jit::IValue> TorchInputs;
310 // 将四个轮子的输入数据(可能是传感器数据)转换为PyTorch张量,并添加到TorchInputs中
311 TorchInputs.push_back(Model->GetWheelTensorInputsCUDA(_input.wheel0, 0));
312 TorchInputs.push_back(Model->GetWheelTensorInputsCUDA(_input.wheel1, 1));
313 TorchInputs.push_back(Model->GetWheelTensorInputsCUDA(_input.wheel2, 2));
314 TorchInputs.push_back(Model->GetWheelTensorInputsCUDA(_input.wheel3, 3));
315 // 将驾驶控制输入(方向盘转角、油门、刹车)组合成一个PyTorch张量,并添加到TorchInputs中
316 auto drv_inputs = torch::tensor(
317 {_input.steering, _input.throttle, _input.braking}, torch::kFloat32); //steer, throtle, brake
318 TorchInputs.push_back(drv_inputs.cuda());
319 // 如果地形类型有效(非负值),则将其作为标量添加到TorchInputs中
320 if (_input.terrain_type >= 0) {
321 // 将verbose标志(可能用于控制模型输出的详细程度)添加到TorchInputs中
322 TorchInputs.push_back(_input.terrain_type);
323 }
324 TorchInputs.push_back(_input.verbose);
325// 定义一个变量Output,用于存储模型的前向传播结果
326 torch::jit::IValue Output;
327 // 尝试执行模型的前向传播,如果发生错误(如模型不匹配、输入数据问题等),则捕获异常并打印错误信息
328 try {
329 Output = Model->module.forward(TorchInputs);
330 } catch (const c10::Error& e) {
331 std::cout << "Error running model: " << e.msg() << std::endl;
332 }
333// 将Output转换为包含多个元素的元组,并提取其中的张量数据
334 std::vector<torch::jit::IValue> Tensors = Output.toTuple()->elements();
335 // 对每个轮子的输出数据,调用GetWheelTensorOutputDynamic函数进行处理(可能是提取特定的输出值或进行格式转换)
336 _output.wheel0 = GetWheelTensorOutput(
337 Tensors[0].toTensor().cpu(), Tensors[4].toTensor().cpu() );
338 _output.wheel1 = GetWheelTensorOutput(
339 Tensors[1].toTensor().cpu(), Tensors[5].toTensor().cpu() );
340 _output.wheel2 = GetWheelTensorOutput(
341 Tensors[2].toTensor().cpu(), Tensors[6].toTensor().cpu() );
342 _output.wheel3 = GetWheelTensorOutput(
343 Tensors[3].toTensor().cpu(), Tensors[7].toTensor().cpu() );
344 }
345
346 Outputs& NeuralModel::GetOutputs() {
347 return _output;
348 }
349
350 NeuralModel::~NeuralModel() {}
351
352}
353}
void test_learning()
Definition pytorch.cpp:27
WheelOutput GetWheelTensorOutputDynamic(const at::Tensor &particle_forces, const at::Tensor &wheel_forces)
Definition pytorch.cpp:107
WheelOutput GetWheelTensorOutput(const at::Tensor &particle_forces, const at::Tensor &wheel_forces)
Definition pytorch.cpp:74
torch::jit::IValue GetWheelTensorInputs(WheelInput &wheel)
Definition pytorch.cpp:37
CARLA模拟器的主命名空间。
Definition Carla.cpp:139
void add_mark(const std::string &text)
Definition pytorch.cpp:20
torch::jit::script::Module ~NeuralModelImpl()
Definition pytorch.cpp:138
std::vector< at::Tensor > particles_velocity_tensors
Definition pytorch.cpp:142
std::vector< at::Tensor > particles_position_tensors
Definition pytorch.cpp:140
torch::jit::IValue GetWheelTensorInputsCUDA(WheelInput &wheel, int wheel_idx)
Definition pytorch.cpp:152
std::vector< float > _particle_forces
Definition pytorch.h:50