Webots机器人控制器修改Vector值时崩溃问题求助
Webots模拟器控制器崩溃问题排查与修复
运行Webots模拟器时,主机器人控制器在0.750秒时冻结崩溃,调试确认问题出在vector赋值相关代码段,注释后程序可正常运行。以下是代码中的问题点及修复方案:
核心问题分析
逗号表达式误用导致数值计算错误
代码中input2 = (right1->getVelocity(), right2->getVelocity(), right3->getVelocity()) / 3;使用了逗号表达式,这只会返回最后一个right3->getVelocity()的值,而非三个速度的平均值,会导致后续网络输入异常。State向量未完全赋值
state.resize(3)后仅给state[0]赋值,state[1]和state[2]未初始化(默认值为0),但actor网络要求3维输入,这会引发网络计算的潜在内存问题。Values向量重复添加元素引发越界
连续执行两次values.push_back(valueEstimates[0][0]);,导致values长度是logProbs、rewards等向量的两倍。后续计算优势函数时,访问values[t+1]会触发数组越界,这是控制器崩溃的核心原因。Critic损失计算逻辑错误
计算完平方和后,错误地将criticLoss赋值为rewards.size(),而非求平均损失,异常的损失值会导致反向传播时出现数值溢出或内存错误。
修复后的关键代码段
// library for sim functions #include "include/simFunctions.cpp" // create the sim class Sim sim; class Bot{ private: double currentScore; bool training = true; int currentTerm = 65; int previousTerm = 0; public: const void* message = " "; int functionOutput; // activate or deactivate the hook void hook(bool activated) { if (activated == true) { Hook->setVelocity(2.0); sim.delay(130, "msec"); Hook->setVelocity(0.0); } else if (activated == false) { Hook->setVelocity(-2.0); sim.delay(130, "msec"); Hook->setVelocity(0.0); } } // training functions for network void trainingNetwork(NeuralNetwork& actor, NeuralNetwork& critic, int numEpisodes, double gamma, double learningRate, double GRADIENT_CLASH_THRESHOLD, double weight_decay) { AdamWOptimizer actorOptimizer(learningRate, 0.9, 0.999, 0.01, weight_decay); AdamWOptimizer criticOptimizer(learningRate, 0.9, 0.999, 0.01, weight_decay); actor.add_layer(Layer(3, 128, "relu", actorOptimizer)); actor.add_layer(Layer(128, 128, "relu", actorOptimizer)); actor.add_layer(Layer(128, 4, "linear", actorOptimizer)); critic.add_layer(Layer(2, 128, "relu", criticOptimizer)); critic.add_layer(Layer(128, 128, "relu", criticOptimizer)); critic.add_layer(Layer(128, 1, "linear", criticOptimizer)); for (int episode = 0; episode <= numEpisodes; ++episode) { vector<vector<double>> states; vector<double> actions, rewards, logProbs, values; if (left1->getVelocity() != 0.0) { sim.moveBot(0); sim.delay(50, "msec"); } sim.resetSimManual(); sim.programSetup(); training = true; while (training == true) { double input1; double input2; double input3; // 修复input2的计算逻辑 input1 = (left1->getVelocity() + left2->getVelocity() + left3->getVelocity()) / 3; input2 = (right1->getVelocity() + right2->getVelocity() + right3->getVelocity()) / 3; input3 = robot->getTime(); // 直接初始化完整的state向量 vector<double> state = {input1, input2, input3}; states.push_back(state); vector<vector<double>> actionProbs = actor.forward({state}); vector<vector<double>> valueEstimates = critic.forward({state}); // 移除重复的push操作 values.push_back(valueEstimates[0][0]); sim.delay(64, "msec"); int action = (actionProbs[0][0] > actionProbs[0][1]) ? 0 : 1; logProbs.push_back(log(max(actionProbs[0][action], 1e-8))); functionOutput = action; cout << "MAINBOT: functionOutput = " << functionOutput << endl; functionConvert(functionOutput); sim.receive(); if (receiv->getQueueLength() >= 1) { message = receiv->getData(); currentScore = *(double *)message; rewards.push_back(currentScore); receiv->nextPacket(); } if (robot->getTime() >= currentTerm) { training = false; previousTerm = currentTerm; currentTerm = currentTerm + 61; } } vector<double> advantages; for (int t = 0; t < rewards.size(); ++t) { double td_target = rewards[t] + (t < rewards.size() - 1 ? gamma * values[t + 1] : 0.0); advantages.push_back(td_target - values[t]); } double actorLoss = computeLoss(logProbs, advantages); // 修复criticLoss计算逻辑 double criticLoss = 0.0; for (size_t i = 0; i < rewards.size(); ++i) { double td_target = rewards[i] + (i < rewards.size() - 1 ? gamma * values[i + 1] : 0.0); criticLoss += pow(td_target - values[i], 2); } // 计算平均损失 criticLoss /= rewards.size(); actor.backward({{actorLoss}}, GRADIENT_CLASH_THRESHOLD); actor.update_weights(); critic.backward({{criticLoss}}, GRADIENT_CLASH_THRESHOLD); critic.update_weights(); } } double computeLoss(const vector<double>& logProbs, const vector<double>& advantages) { double loss = 0.0; for (int i = 0; i < logProbs.size(); ++ i) { loss -= logProbs[i] * advantages[i]; } return loss; } void functionConvert(int functionID) { if (functionID == 0) { sim.moveBot(0); } else if (functionID == 1) { sim.moveBot(1); } else if (functionID == -1) { sim.moveBot(2); } else if (functionID == 2) { sim.moveBot(3); } else if (functionID == -2) { sim.moveBot(4); } } };
内容的提问来源于stack exchange,提问作者user27382745
相关产品推荐
相关产品推荐

