AGV_controller.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. #include <webots/Robot.hpp>
  2. #include <webots/Motor.hpp>
  3. #include <webots/PositionSensor.hpp>
  4. #include <webots/GPS.hpp>
  5. #include <webots/Gyro.hpp>
  6. #include <webots/InertialUnit.hpp>
  7. #include "emqx-client/mqttmsg.h"
  8. #include "emqx-client/paho_client.h"
  9. #include <unistd.h>
  10. #include <chrono>
  11. #include <random>
  12. #include "timedlockdata.hpp"
  13. // All the webots classes are defined in the "webots" namespace
  14. using namespace webots;
  15. Paho_client* client_= nullptr;
  16. TimedLockData<NavMessage::Speed> g_speed;
  17. void SpeedChangeCallback(std::string topic,int QOS,MqttMsg& msg,void* context)
  18. {
  19. NavMessage::Speed speed;
  20. msg.toProtoMessage(speed);
  21. g_speed.reset(speed,0.3);
  22. }
  23. double generae_random(std::default_random_engine& generator,double mean,double sigma)
  24. {
  25. std::normal_distribution<double> distribution(mean, sigma);
  26. return distribution(generator);
  27. }
  28. bool init_mqtt(std::string ip,int port,std::string nodeId,std::string subtopic)
  29. {
  30. if(client_!= nullptr)
  31. {
  32. client_->disconnect();
  33. delete client_;
  34. }
  35. client_=new Paho_client(nodeId);
  36. bool ret= client_->connect(ip,port);
  37. if(ret)
  38. {
  39. while(!client_->isconnected()) usleep(1000);
  40. client_->subcribe(subtopic,1,SpeedChangeCallback, nullptr);
  41. }
  42. return ret;
  43. }
  44. void Rotating(double wmg,double w,double l,
  45. double& R1,double& R2,double& R3,double& R4,
  46. double& L1,double& L2,double& L3,double& L4)
  47. {
  48. double theta=atan(l/w);
  49. R1=(-theta);
  50. R2=(theta);
  51. R3=(theta);
  52. R4=(-theta);
  53. double velocity=wmg*sqrt(w*w+l*l);
  54. L1=(-velocity);
  55. L2=(velocity);
  56. L3=(-velocity);
  57. L4=(velocity);
  58. }
  59. void Horizontal(double velocity,double& R1,double& R2,double& R3,double& R4,
  60. double& L1,double& L2,double& L3,double& L4)
  61. {
  62. R1=-M_PI/2.0;
  63. R2=M_PI/2.0;
  64. R3=M_PI/2.0;
  65. R4=-M_PI/2.0;
  66. L1=-velocity;
  67. L2=velocity;
  68. L3=velocity;
  69. L4=-velocity;
  70. }
  71. void Vrtical(double velocity,double& R1,double& R2,double& R3,double& R4,
  72. double& L1,double& L2,double& L3,double& L4)
  73. {
  74. R1=0;
  75. R2=0;
  76. R3=0;
  77. R4=0;
  78. L1=velocity;
  79. L2=velocity;
  80. L3=velocity;
  81. L4=velocity;
  82. }
  83. int main(int argc, char **argv) {
  84. //init mqtt
  85. if(false==init_mqtt("127.0.0.1",1883,"webots-AGV","monitor/speedcmd"))
  86. {
  87. printf(" Init mqtt failed...\n");
  88. return -1;
  89. }
  90. //随机数
  91. unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
  92. std::default_random_engine generator(seed);
  93. // create the Robot instance.
  94. Robot *robot = new Robot();
  95. // get the time step of the current world.
  96. int timeStep = (int)robot->getBasicTimeStep();
  97. webots::Motor* RM1=robot->getMotor("R1_motor");
  98. webots::Motor* RM2=robot->getMotor("R2_motor");
  99. webots::Motor* RM3=robot->getMotor("R3_motor");
  100. webots::Motor* RM4=robot->getMotor("R4_motor");
  101. //R1->getPositionSensor()->enable(timeStep);
  102. webots::Motor* R1_l=robot->getMotor("L1_motor");
  103. webots::Motor* R2_l=robot->getMotor("L2_motor");
  104. webots::Motor* R3_l=robot->getMotor("L3_motor");
  105. webots::Motor* R4_l=robot->getMotor("L4_motor");
  106. RM1->setPosition(0);
  107. RM2->setPosition(0);
  108. RM3->setPosition(0);
  109. RM4->setPosition(0);
  110. R1_l->setPosition(INFINITY);
  111. R2_l->setPosition(INFINITY);
  112. R3_l->setPosition(INFINITY);
  113. R4_l->setPosition(INFINITY);
  114. /*RM1->setTorque(100);
  115. RM2->setTorque(100);
  116. RM3->setTorque(100);
  117. RM4->setTorque(100);*/
  118. R1_l->setVelocity(0.0);
  119. R2_l->setVelocity(0.0);
  120. R3_l->setVelocity(0.0);
  121. R4_l->setVelocity(0.0);
  122. webots::GPS* gps=robot->getGPS("gps");
  123. webots::InertialUnit* imu=robot->getInertialUnit("imu");
  124. webots::Gyro* gyr=robot->getGyro("gyro");
  125. gyr->enable(timeStep);
  126. gps->enable(timeStep);
  127. imu->enable(timeStep);
  128. double w=2.5;
  129. double l=1.3;
  130. double radius=0.1915;
  131. double K=1.0/radius;
  132. auto last=std::chrono::steady_clock::now();
  133. while (robot->step(timeStep) != -1) {
  134. auto now=std::chrono::steady_clock::now();
  135. auto duration = std::chrono::duration_cast<std::chrono::microseconds>(now - last);
  136. double time = double(duration.count()) * std::chrono::microseconds::period::num /
  137. std::chrono::microseconds::period::den;
  138. ////发布:
  139. //增加高斯分布
  140. double x=gps->getValues()[2] + generae_random(generator,0,0.02);
  141. double y=gps->getValues()[0] + generae_random(generator,0,0.02);
  142. double theta=imu->getRollPitchYaw()[2]+generae_random(generator,0,0.3*M_PI/180.0);
  143. //获取gps速度,判断朝向
  144. double vm1=R3_l->getVelocity()*radius;
  145. double vm2=-R4_l->getVelocity()*radius;
  146. double v=gps->getSpeed();
  147. if(vm1+vm2<0.0)
  148. v=-v;
  149. //陀螺仪角速度
  150. double vth=gyr->getValues()[1];
  151. if(time>0.2)
  152. {
  153. printf(" publish delay................ time:%f -------------------------------------\n",time);
  154. }
  155. /*printf("dt:%f x y:%f %f, yaw:%f velocity:%f vth:%f %f %f\n",time,
  156. x,y,theta,
  157. v,gyr->getValues()[0],gyr->getValues()[1],gyr->getValues()[2]);*/
  158. last=now;
  159. if(client_)
  160. {
  161. MqttMsg msg;
  162. NavMessage::AGVStatu statu;
  163. statu.set_x(x);
  164. statu.set_y(y);
  165. statu.set_theta(theta);
  166. statu.set_v(v);
  167. statu.set_vth(vth);
  168. msg.fromProtoMessage(statu);
  169. client_->publish("monitor/statu",1,msg);
  170. }
  171. if(g_speed.timeout())
  172. {
  173. RM1->setPosition(0);
  174. RM2->setPosition(0);
  175. RM3->setPosition(0);
  176. RM4->setPosition(0);
  177. R1_l->setVelocity(0);
  178. R2_l->setVelocity(0);
  179. R3_l->setVelocity(0);
  180. R4_l->setVelocity(0);
  181. continue;
  182. }
  183. //变速----------------------------------
  184. double cmd_v=g_speed.Get().v();
  185. double cmd_vth=g_speed.Get().vth();
  186. //初始值
  187. double R1=0,R2=0,R3=0,R4=0;
  188. double L1=cmd_v;
  189. double L2=cmd_v;
  190. double L3=cmd_v;
  191. double L4=cmd_v;
  192. if(g_speed.Get().type()==1) //原地旋转
  193. {
  194. if (fabs(cmd_vth) > 0.0001)
  195. Rotating(cmd_vth, w / 2.0, l / 2.0, R1, R2, R3, R4, L1, L2, L3, L4);
  196. }
  197. else if(g_speed.Get().type()==2) //横移
  198. {
  199. Horizontal(g_speed.Get().v(),R1, R2, R3, R4, L1, L2, L3, L4);
  200. }
  201. else if(g_speed.Get().type()==3) { //巡线/前进
  202. if (fabs(cmd_vth) > 0.4) {
  203. cmd_vth = cmd_vth > 0 ? 0.4 : -0.4;
  204. }
  205. //------------------------------------------------
  206. //无角速度,直线
  207. if (fabs(cmd_vth) < 0.0001) {
  208. R1 = R2 = R3 = R4 = 0;
  209. L1 = L2 = L3 = L4 = cmd_v;
  210. } else //有角速度
  211. {
  212. if (fabs(cmd_v) < 0.00001) {
  213. //原地旋转
  214. if (fabs(cmd_vth) > 0.0001)
  215. Rotating(cmd_vth, w / 2.0, l / 2.0, R1, R2, R3, R4, L1, L2, L3, L4);
  216. } else {
  217. //默认原地旋转
  218. Rotating(cmd_vth, w / 2.0, l / 2.0, R1, R2, R3, R4, L1, L2, L3, L4);
  219. double base = pow(cmd_v / cmd_vth, 2) - (l * l / 4);
  220. //满足运动方程
  221. if (base >= 0.0001) {
  222. double BaseR = sqrt(base) - w / 2;
  223. if(BaseR<0.05)
  224. BaseR=0.05;
  225. //printf("BaseR : %f \n",BaseR);
  226. if (BaseR > 0) {
  227. if (cmd_vth * cmd_v >= 0) {
  228. R1 = atan(l / BaseR);
  229. R2 = atan(l / (BaseR + w));
  230. L3 = BaseR * cmd_vth;
  231. L4 = (BaseR + w) * cmd_vth;
  232. R3 = 0;
  233. R4 = 0;
  234. L1 = L3 / cos(R1);
  235. L2 = L4 / cos(R2);
  236. } else {
  237. R1 = -atan(l / (BaseR + w));
  238. R2 = -atan(l / BaseR);
  239. L3 = -(BaseR + w) * cmd_vth;
  240. L4 = -BaseR * cmd_vth;
  241. R3 = 0;
  242. R4 = 0;
  243. L1 = L3 / cos(R1);
  244. L2 = L4 / cos(R2);
  245. }
  246. }
  247. }
  248. }
  249. }
  250. }else{
  251. L1=L2=L3=L4=0;
  252. }
  253. printf(" R1-R4:%.5f %.5f %.5f %.5f L1-L4:%.5f %.5f %.5f %.5f V:%.5f Vth:%.5f\n",
  254. R1,R2,R3,R4,L1,L2,L3,L4,v,vth);
  255. RM1->setPosition(R1);
  256. RM2->setPosition(R2);
  257. RM3->setPosition(R3);
  258. RM4->setPosition(R4);
  259. R1_l->setVelocity(L1*K);
  260. R2_l->setVelocity(-L2*K);
  261. R3_l->setVelocity(L3*K);
  262. R4_l->setVelocity(-L4*K);
  263. };
  264. // Enter here exit cleanup code.
  265. delete robot;
  266. return 0;
  267. }