path_smoother.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. #ifndef PATH_SMOOTHER_HPP
  2. #define PATH_SMOOTHER_HPP
  3. #include "costmap_2d/costmap_2d.h"
  4. #include "teb/lbfgs.h"
  5. #include "teb/BandedSystem.h"
  6. #include <Eigen/Eigen>
  7. #include <cmath>
  8. #include <cfloat>
  9. #include <iostream>
  10. #include <vector>
  11. #include <geometry_msgs/PoseStamped.h>
  12. #include <algorithm>
  13. #include <costmap_2d/costmap_2d_ros.h>
  14. #include <algorithm>
  15. namespace path_smoother
  16. {
  17. class PathSmoother
  18. {
  19. private:
  20. int pieceNum; // 三次样条曲线数量
  21. int nodeNum; // 决策变量点数量
  22. double goalOri; // 轨迹目标点朝向
  23. bool clamp_spline_flag_;
  24. std::vector<Eigen::Matrix<double, 2, 4>> mycMatVec; // 分段三次样条曲线参数
  25. Eigen::Vector2d startPoint; // 起点坐标
  26. Eigen::Vector2d goalPoint; // 终点坐标
  27. Eigen::MatrixX2d points; // 路径的所有点 这个一会儿该成initPoints
  28. Eigen::VectorXd decisionVariables; // 一维的决策变量 包含起点和终点,我怎么感觉不应该包含啊 ?? 包含了的话起点和终点就会动了
  29. BandedSystem A; // 三次样条曲线参数求解矩阵 Ax = b
  30. Eigen::MatrixX2d b; // 三次样条曲线参数求解矩阵 Ax = b
  31. lbfgs::lbfgs_parameter_t lbfgs_params; // lbfgs 求解的参数
  32. costmap_2d::Costmap2D *costMap_; // 代价地图
  33. Eigen::Matrix2d robot_orientation; // 小车当前朝向
  34. // std::vector<double> duration_; // 每段轨迹的时间
  35. Eigen::MatrixX2d Points; // 决策变量点
  36. Eigen::Matrix2Xd costGradient; // 能耗梯度
  37. Eigen::Matrix2Xd penaltyGradient; // 障碍物避让梯度
  38. Eigen::Matrix2Xd kinematicGradient; // 运动学约束梯度
  39. // getKinematicCost()的一些参数
  40. double kCost = 0;
  41. double D = 0;
  42. double maxTurnAngle;
  43. double turningAngle;
  44. std::vector<double> pointAngle;
  45. Eigen::Matrix<double, 2, 1> tangentVec;
  46. std::vector<Eigen::Matrix<double, 2, 1>> pointAngleVec; // (b_x, b_y)^T
  47. // getPenaltyGradient() 的一些参数
  48. Eigen::Vector2d current_point;
  49. Eigen::Vector2d up_point;
  50. Eigen::Vector2d down_point;
  51. Eigen::Vector2d left_point;
  52. Eigen::Vector2d right_point;
  53. std::vector<double> distance = {0, 0, 0, 0};
  54. double penaltyCost = 0;
  55. std::vector<double> L_k;
  56. std::vector<int> cost_k;
  57. std::vector<double> L_k_cost_k;
  58. std::vector<std::vector<int>> p_i;
  59. // solveCurveParameters() 的一些参数
  60. Eigen::MatrixX2d Delta;
  61. Eigen::MatrixX2d ttheta = Eigen::MatrixX2d::Zero(1, 2);
  62. Eigen::Matrix<double, 2, 4> coeff;
  63. /* 2 行 4 列矩阵
  64. d_x c_x b_x a_x
  65. d_y c_y b_y a_y
  66. */
  67. // 权重系数
  68. double weight_start_direction = 5; // 钳制样条曲线的起点约束权重
  69. double weight_goal_direction = 3; // 钳制样条曲线的终点约束权重
  70. // 默认每段轨迹时间是1秒时, 5 3 是效果还ok
  71. double weight_kinematic_cost = 20000; // 一次违反运动学约束的代价权重系数
  72. static inline double costFunction(void *ptr, // 当前类的指针
  73. const Eigen::VectorXd &x, // 决策变量,x
  74. Eigen::VectorXd &g) // 梯度
  75. { // 根据坐标,计算 代价函数值 和 梯度值
  76. // 权重系数
  77. double weight_cost_energy = 10; // 代价函数 能耗权重系数
  78. double weight_cost_obstacle = 80; // 代价函数 障碍物避让权重系数
  79. double weight_cost_kinematic = 10; // 代价函数 运动学约束权重系数
  80. double weight_gradient_energy = 100; // 梯度函数 能耗权重系数
  81. double weight_gradient_obstacle = 6; // 梯度函数 障碍物避让权重系数
  82. double weight_gradient_kinematic = 0.4; // 梯度函数 运动学约束权重系数
  83. PathSmoother &obj = *(PathSmoother *)ptr; // 上面定义了 ptr 的类型是void, 这里要转换成 PathSmoother 类型的指针
  84. // lbfgs::lbfgs_optimize 中没有改动points, 只改动decisionVariables,为了方便计算做个转换
  85. Eigen::MatrixX2d Points; // 决策变量点
  86. Eigen::Matrix2Xd costGradient; // 能耗梯度
  87. Eigen::Matrix2Xd penaltyGradient; // 障碍物避让梯度
  88. Eigen::Matrix2Xd kinematicGradient; // 运动学约束梯度
  89. costGradient.resize(2, obj.pieceNum - 1);
  90. penaltyGradient.resize(2, obj.pieceNum - 1);
  91. kinematicGradient.resize(2, obj.pieceNum - 1);
  92. costGradient.setZero();
  93. penaltyGradient.setZero();
  94. kinematicGradient.setZero();
  95. Points.resize(obj.nodeNum, 2);
  96. Points.row(0) = obj.startPoint;
  97. Points.row(Points.rows() - 1) = obj.goalPoint;
  98. for (int i = 1; i < (x.size() / 2) + 1; i++)
  99. {
  100. Points(i, 0) = x(2 * i - 2); // 决策变量不包含起点和终点
  101. Points(i, 1) = x(2 * i - 1);
  102. }
  103. double costEnergy = 0;
  104. double costPenalty = 0;
  105. double kinematicCost = 0;
  106. // 行驶能耗
  107. obj.solveCurveParameters(Points);
  108. obj.getCostEnergy(costEnergy);
  109. // 障碍物避让
  110. obj.getCostGradient(costGradient);
  111. costPenalty = obj.getPenaltyGradient(penaltyGradient, Points);
  112. // 运动学约束
  113. obj.getKinematicCost(kinematicCost, kinematicGradient);
  114. double cost = weight_cost_energy * costEnergy + weight_cost_obstacle * costPenalty + weight_cost_kinematic * kinematicCost;
  115. for (int i = 0; i < obj.pieceNum - 1; i++)
  116. {
  117. g(2 * i) = weight_gradient_energy * costGradient(0, i) + weight_gradient_obstacle * penaltyGradient(0, i) - weight_gradient_kinematic * kinematicGradient(0, i);
  118. g(2 * i + 1) = weight_gradient_energy * costGradient(1, i) + weight_gradient_obstacle * penaltyGradient(1, i) - weight_gradient_kinematic * kinematicGradient(1, i);
  119. }
  120. return cost;
  121. }
  122. inline void getKinematicCost(double &kinematicCost, Eigen::Matrix2Xd &kinematicGradient)
  123. {
  124. // 计算每个决策变量点的朝向,不能用Hybrid A* 的朝向信息,因为优化过程中点的位置会变化
  125. for (int i = 0; i < nodeNum - 1; i++)
  126. {
  127. tangentVec = mycMatVec[i].col(2) * 0.1 + mycMatVec[i].col(1) * 0.01 + mycMatVec[i].col(0) * 0.001; // 差分法计算每个点的方向向量
  128. tangentVec.normalize();
  129. pointAngleVec[i] = tangentVec;
  130. pointAngle[i] = std::atan(tangentVec(1) / tangentVec(0));
  131. if (tangentVec(1) < 0)
  132. pointAngle[i] += 3.141592;
  133. }
  134. for (int i = 0; i < nodeNum - 3; i++) // 这里只能给第2个到倒数第2个的梯度
  135. {
  136. D = std::sqrt(std::pow((points(i, 0) - points(i + 1, 0)), 2) + std::pow((points(i, 1) - points(i + 1, 1)), 2));
  137. // maxTurnAngle = 3.141592 * 2 * std::asin(D / (2 * 0.77)) / 0.77; // 这段轨迹的最大允许转向角
  138. maxTurnAngle = 2 * std::asin(D / (2 * 0.77)); // 这段轨迹的最大允许转向角
  139. if (i == 0)
  140. turningAngle = std::acos(robot_orientation(0) * pointAngleVec[0](0) + robot_orientation(1) * pointAngleVec[0](1));
  141. else
  142. turningAngle = std::acos(pointAngleVec[i - 1](0) * pointAngleVec[i](0) + pointAngleVec[i - 1](1) * pointAngleVec[i](1));
  143. if (std::abs(turningAngle) > maxTurnAngle)
  144. {
  145. kCost = weight_kinematic_cost * std::pow((turningAngle - maxTurnAngle), 2);
  146. kinematicCost += kCost;
  147. double cross_product = pointAngleVec[i - 1](0) * pointAngleVec[i](1) - pointAngleVec[i - 1](1) * pointAngleVec[i](0);
  148. if (cross_product < 0)
  149. {
  150. kinematicGradient(0, i + 1) = -pointAngleVec[i](1) * kCost;
  151. kinematicGradient(1, i + 1) = pointAngleVec[i](0) * kCost;
  152. }
  153. else
  154. {
  155. kinematicGradient(0, i + 1) = pointAngleVec[i](1) * kCost;
  156. kinematicGradient(1, i + 1) = -pointAngleVec[i](0) * kCost;
  157. }
  158. }
  159. }
  160. }
  161. inline double getPenaltyGradient(Eigen::Matrix2Xd &penaltyGradient, Eigen::MatrixX2d &Points)
  162. {
  163. penaltyGradient.setZero();
  164. Eigen::Matrix2Xd aasdfsd;
  165. aasdfsd.resize(2, pieceNum - 1);
  166. double cost_all = 0;
  167. penaltyCost = 0;
  168. for (int i = 0; i < penaltyGradient.cols(); i++) // 障碍物避让项 求 代价 和 梯度
  169. {
  170. if (static_cast<int>(costMap_->getCost(round(Points(i, 0)), round(Points(i, 1)))) > 20)
  171. {
  172. current_point(0) = round(Points(i, 0));
  173. current_point(1) = round(Points(i, 1));
  174. std::vector<std::pair<int, int>> offsets = {{-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}};
  175. for (int i = 0; i < 8; i++) // 找到8个邻居节点
  176. {
  177. p_i[i][0] = current_point(0) + offsets[i].first;
  178. p_i[i][1] = current_point(1) + offsets[i].second;
  179. }
  180. for (int ii = 0; ii < 8; ii++)
  181. {
  182. L_k[ii] = std::sqrt(std::pow(p_i[ii][0] - Points(i, 0), 2) + std::pow(p_i[ii][1] - Points(i, 1), 2));
  183. cost_k[ii] = costMap_->getCost(round(p_i[ii][0]), round(p_i[ii][1]));
  184. L_k_cost_k[ii] = std::max(L_k[ii] * cost_k[ii], L_k[ii]);
  185. }
  186. int L_m_index = std::min_element(L_k_cost_k.begin(), L_k_cost_k.end()) - L_k_cost_k.begin();
  187. penaltyCost = std::max(L_k[L_m_index] * costMap_->getCost(current_point(0), current_point(1)), penaltyCost);
  188. cost_all += L_k[L_m_index] * costMap_->getCost(current_point(0), current_point(1));
  189. double alpha = std::atan2(Points(i, 1) - p_i[L_m_index][1], Points(i, 0) - p_i[L_m_index][0]);
  190. if (alpha < 0)
  191. {
  192. alpha += 2 * M_PI;
  193. }
  194. penaltyGradient(0, i) = costMap_->getCost(current_point(0), current_point(1)) * (L_k[L_m_index] - 0.5) * std::cos(alpha);
  195. penaltyGradient(1, i) = costMap_->getCost(current_point(0), current_point(1)) * (L_k[L_m_index] - 0.5) * std::sin(alpha);
  196. }
  197. else // 如果不是障碍物,则没有梯度
  198. {
  199. penaltyGradient(0, i) = 0;
  200. penaltyGradient(1, i) = 0;
  201. }
  202. }
  203. return penaltyCost;
  204. }
  205. inline void getCostGradient(Eigen::Matrix2Xd &costGradient)
  206. {
  207. // double dc0, dc1, dd0, dd1;
  208. for (int i = 0; i < mycMatVec.size() - 1; i++)
  209. {
  210. for (int j = 0; j < 2; j++)
  211. {
  212. // dc0 = 8 * mycMatVec[i](j, 1) + 12 * mycMatVec[i](j, 0);
  213. // dc1 = 8 * mycMatVec[i + 1](j, 1) + 12 * mycMatVec[i + 1](j, 0);
  214. // dd0 = 12 * mycMatVec[i](j, 1) + 24 * mycMatVec[i](j, 0);
  215. // dd1 = 12 * mycMatVec[i + 1](j, 1) + 24 * mycMatVec[i + 1](j, 0);
  216. // costGradient(j, i) = 3 * (dc0 - dc1) + 2 * (dd1 - dd0);
  217. costGradient(j, i) = 12 * mycMatVec[i + 1](j, 0) - 12 * mycMatVec[i](j, 0); // 上面的式子化简下来就是这个了
  218. // coeff.col(0) = ((b.row(i + 1) - b.row(i)) / 3).transpose(); // d
  219. // coeff.col(1) = b.row(i).transpose(); // c
  220. // coeff.col(2) = (Delta.row(i) - (2 * b.row(i) + b.row(i + 1)) / 3).transpose(); // b
  221. // coeff.col(3) = points.row(i).transpose(); // a
  222. // mycMatVec[i] = (coeff);
  223. }
  224. }
  225. }
  226. inline void getCostEnergy(double &costEnergy)
  227. {
  228. for (int i = 0; i < pieceNum; i++)
  229. {
  230. for (int j = 0; j < 2; j++) // 代价函数(这里没有乘权重系数)
  231. // costEnergy += 4 * std::pow(mycMatVec[i](j, 1), 2) + 12 * mycMatVec[i](j, 1) * mycMatVec[i](j, 0) * duration_[i] * duration_[i] + 12 * std::pow(mycMatVec[i](j, 0), 2) * duration_[i] * duration_[i] * duration_[i];
  232. costEnergy += 4 * std::pow(mycMatVec[i](j, 1), 2) + 12 * mycMatVec[i](j, 1) * mycMatVec[i](j, 0) + 12 * std::pow(mycMatVec[i](j, 0), 2);
  233. }
  234. return;
  235. }
  236. inline void solveCurveParameters(const Eigen::MatrixX2d &points) // 这里的points包含起点和终点,即N个点
  237. {
  238. Delta.resize(nodeNum - 1, 2);
  239. for (int i = 0; i < Delta.rows(); i++)
  240. Delta.row(i) = points.row(i + 1) - points.row(i);
  241. for (int i = 1; i < b.rows() - 1; i++)
  242. // b.row(i) = 3 * (Delta.row(i) / duration_[i] - Delta.row(i - 1)) / duration_[i - 1];
  243. b.row(i) = 3 * (Delta.row(i) - Delta.row(i - 1));
  244. // 自由边界样条曲线
  245. // b.row(0) = Eigen::MatrixX2d::Zero(1, 2);
  246. // b.row(b.rows() - 1) = Eigen::MatrixX2d::Zero(1, 2);
  247. if (clamp_spline_flag_ == true)
  248. {
  249. // 钳制样条曲线边界设置
  250. ttheta << robot_orientation(0), robot_orientation(1);
  251. // b.row(0) = 3 * (Delta.row(0) / duration_[0] - ttheta * weight_start_direction);
  252. b.row(0) = 3 * (Delta.row(0) - ttheta * weight_start_direction);
  253. ttheta << std::cos(goalOri), std::sin(goalOri);
  254. // b.row(b.rows() - 1) = 3 * (ttheta * weight_goal_direction - Delta.row(Delta.rows() - 1) / duration_[duration_.size() - 1]);
  255. b.row(b.rows() - 1) = 3 * (ttheta * weight_goal_direction - Delta.row(Delta.rows() - 1));
  256. }
  257. else
  258. {
  259. // 自由边界样条曲线
  260. b.row(0) = Eigen::MatrixX2d::Zero(1, 2);
  261. b.row(b.rows() - 1) = Eigen::MatrixX2d::Zero(1, 2);
  262. A(0, 0) = 1;
  263. A(nodeNum - 1, nodeNum - 1) = 1;
  264. for (int i = 1; i < nodeNum - 1; i++)
  265. {
  266. A(i, i - 1) = 1;
  267. A(i, i) = 4;
  268. A(i, i + 1) = 1;
  269. }
  270. A.factorizeLU(); // 对矩阵A做LU分解
  271. }
  272. A.solve(b);
  273. for (int i = 0; i < nodeNum - 1; i++)
  274. {
  275. coeff.col(0) = ((b.row(i + 1) - b.row(i)) / 3).transpose(); // d
  276. coeff.col(1) = b.row(i).transpose(); // c
  277. coeff.col(2) = (Delta.row(i) - (2 * b.row(i) + b.row(i + 1)) / 3).transpose(); // b
  278. coeff.col(3) = points.row(i).transpose(); // a
  279. mycMatVec[i] = (coeff);
  280. // coeff.col(0) = ((b.row(i + 1) - b.row(i)) / (3 * duration_[i])).transpose(); // d
  281. // coeff.col(1) = b.row(i).transpose(); // c
  282. // coeff.col(2) = (Delta.row(i) / duration_[i] - (2 * b.row(i) + b.row(i + 1)) / (3 * duration_[i])).transpose(); // b
  283. // coeff.col(3) = points.row(i).transpose(); // a
  284. // mycMatVec[i] = (coeff);
  285. }
  286. }
  287. public:
  288. inline bool setup(std::vector<geometry_msgs::PoseStamped> &plan, // 这个setup 是在global_planner里面调用的,感觉有些数据可以在小车启动的时候就可以先算好了!!!
  289. costmap_2d::Costmap2DROS *costmap_ros, std::vector<double> duration, bool clamp_spline_flag) // 传递指针
  290. {
  291. clamp_spline_flag_ = clamp_spline_flag;
  292. costMap_ = costmap_ros->getCostmap(); // 代价地图
  293. pieceNum = plan.size() - 1; // 分段数量
  294. nodeNum = plan.size();
  295. startPoint(0) = plan.front().pose.position.x; // 起点坐标
  296. startPoint(1) = plan.front().pose.position.y;
  297. goalPoint(0) = plan.back().pose.position.x; // 终点坐标
  298. goalPoint(1) = plan.back().pose.position.y;
  299. points.resize(plan.size(), 2);
  300. decisionVariables.resize(plan.size() * 2 - 4);
  301. // goalOri = plan[plan.size() - 1].pose.orientation.z; // 这里要改!!
  302. Eigen::Quaterniond q;
  303. Eigen::Vector3d euler;
  304. q.x() = plan[plan.size() - 1].pose.orientation.x;
  305. q.y() = plan[plan.size() - 1].pose.orientation.y;
  306. q.z() = plan[plan.size() - 1].pose.orientation.z;
  307. q.w() = plan[plan.size() - 1].pose.orientation.w;
  308. euler = q.toRotationMatrix().eulerAngles(2, 1, 0); // 用Eigen将四元数转换成直观的欧拉角
  309. goalOri = std::abs(euler[1]) > 1.57 ? euler[0] + 3.141592 : euler[0];
  310. for (int i = 0; i < plan.size(); i++)
  311. {
  312. points(i, 0) = plan[i].pose.position.x;
  313. points(i, 1) = plan[i].pose.position.y;
  314. }
  315. for (int i = 1; i < plan.size() - 1; i++)
  316. {
  317. decisionVariables(2 * i - 2) = plan[i].pose.position.x;
  318. decisionVariables(2 * i - 1) = plan[i].pose.position.y;
  319. }
  320. A.create(nodeNum, 1, 1); // A是带状矩阵,后面两个1表示对角线及上下各1行不是0,其他都是0
  321. b.resize(nodeNum, 2);
  322. // duration_ = duration;
  323. // duration_.resize(nodeNum - 1);
  324. // std::fill(duration_.begin(), duration_.end(), 1);
  325. A.reset();
  326. // 钳制样条曲线边界设置(默认开始的时候是钳制样条曲线)
  327. A(0, 0) = 2;
  328. A(0, 1) = 1;
  329. A(nodeNum - 1, nodeNum - 2) = 1;
  330. A(nodeNum - 1, nodeNum - 1) = 2 * 2;
  331. for (int i = 1; i < nodeNum - 1; i++)
  332. {
  333. A(i, i - 1) = 1;
  334. A(i, i) = 4;
  335. A(i, i + 1) = 1;
  336. }
  337. // A(0, 0) = 2 * duration_[0];
  338. // A(0, 1) = duration_[0];
  339. // A(nodeNum - 1, nodeNum - 2) = duration_[duration_.size() - 1];
  340. // A(nodeNum - 1, nodeNum - 1) = 2 * duration_[duration_.size() - 1];
  341. // for (int i = 1; i < nodeNum - 1; i++)
  342. // {
  343. // A(i, i - 1) = duration_[i - 1];
  344. // A(i, i) = 2 * duration_[i - 1] + 2 * duration_[i];
  345. // A(i, i + 1) = duration_[i];
  346. // }
  347. A.factorizeLU(); // 对矩阵A做LU分解
  348. mycMatVec.resize(pieceNum);
  349. // 运动学约束函数的变量初始化
  350. pointAngleVec.resize(nodeNum - 1);
  351. pointAngle.resize(nodeNum - 1);
  352. L_k.resize(8);
  353. cost_k.resize(8);
  354. L_k_cost_k.resize(8);
  355. p_i.resize(8);
  356. for (int i = 0; i < 8; i++)
  357. {
  358. p_i[i].resize(2);
  359. }
  360. return true;
  361. }
  362. Eigen::VectorXd optimize(int &Ret)
  363. {
  364. std::vector<geometry_msgs::PoseStamped> plan;
  365. double minCost = 100;
  366. lbfgs_params.mem_size = 8; // lbfgs 的一些求解参数, 都有默认值, 按需设置
  367. lbfgs_params.delta = 1.0e-4; // e-4效果还可以,e-03效果就比较一般,时间上e-3差不多要比e-4快一倍
  368. int result = lbfgs::lbfgs_optimize(decisionVariables, minCost, &PathSmoother::costFunction, nullptr, this, lbfgs_params);
  369. // this 应该是传递 A_star_global_planner 中 path_smoother::PathSmoother path_smoother_; 实例化的 path_smoother_ 对象
  370. if (result >= 0)
  371. {
  372. plan.clear();
  373. plan.reserve(decisionVariables.size() / 2);
  374. for (int i = 0; i < decisionVariables.size() / 2; i++)
  375. {
  376. plan[i].pose.position.x = decisionVariables(2 * i + 0);
  377. plan[i].pose.position.y = decisionVariables(2 * i + 1);
  378. }
  379. }
  380. else
  381. {
  382. std::cout << "优化失败,`result = " << result << std::endl;
  383. decisionVariables.resize(0);
  384. }
  385. return decisionVariables;
  386. }
  387. void setRobotPose(const geometry_msgs::PoseStamped &robot_pose)
  388. {
  389. Eigen::Quaterniond q;
  390. q.x() = robot_pose.pose.orientation.x;
  391. q.y() = robot_pose.pose.orientation.y;
  392. q.z() = robot_pose.pose.orientation.z;
  393. q.w() = robot_pose.pose.orientation.w;
  394. Eigen::Vector3d euler = q.toRotationMatrix().eulerAngles(2, 1, 0); // 用Eigen将四元数转换成直观的欧拉角
  395. double robot_theta = std::abs(euler[1]) > 1.57 ? euler[0] + 3.141592 : euler[0];
  396. robot_orientation(0) = std::cos(robot_theta); // x
  397. robot_orientation(1) = std::sin(robot_theta); // y
  398. }
  399. };
  400. }
  401. #endif