#include #include #include #include #include #include #include #include "emqx-client/mqttmsg.h" #include "emqx-client/paho_client.h" #include #include #include // All the webots classes are defined in the "webots" namespace using namespace webots; Paho_client* client_= nullptr; double g_v=0,g_vth=0; void SpeedChangeCallback(std::string topic,int QOS,MqttMsg& msg,void* context) { msg.toSpeed(g_v,g_vth); } double generae_random(std::default_random_engine& generator,double mean,double sigma) { std::normal_distribution distribution(mean, sigma); return distribution(generator); } bool init_mqtt(std::string ip,int port,std::string nodeId,std::string subtopic) { if(client_!= nullptr) { client_->disconnect(); delete client_; } client_=new Paho_client(nodeId); bool ret= client_->connect(ip,port); if(ret) { while(!client_->isconnected()) usleep(1000); client_->subcribe(subtopic,1,SpeedChangeCallback, nullptr); } return ret; } void Rotating(double wmg,double w,double l, double& R1,double& R2,double& R3,double& R4, double& L1,double& L2,double& L3,double& L4) { double theta=atan(l/w); R1=(-theta); R2=(theta); R3=(theta); R4=(-theta); double velocity=wmg*sqrt(w*w+l*l); L1=(-velocity); L2=(velocity); L3=(-velocity); L4=(velocity); } int main(int argc, char **argv) { //init mqtt if(false==init_mqtt("127.0.0.1",1883,"webots-AGV","AgvCmd/cmd1")) { printf(" Init mqtt failed...\n"); return -1; } //随机数 unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); std::default_random_engine generator(seed); // create the Robot instance. webots::Supervisor* super=new webots::Supervisor(); Node* root=super->getRoot(); Node* worldInfo=root->getField("children")->getMFNode(0); Robot *robot = new Robot(); // get the time step of the current world. int timeStep = (int)robot->getBasicTimeStep(); webots::Motor* RM1=robot->getMotor("R1_motor"); webots::Motor* RM2=robot->getMotor("R2_motor"); webots::Motor* RM3=robot->getMotor("R3_motor"); webots::Motor* RM4=robot->getMotor("R4_motor"); //R1->getPositionSensor()->enable(timeStep); webots::Motor* R1_l=robot->getMotor("L1_motor"); webots::Motor* R2_l=robot->getMotor("L2_motor"); webots::Motor* R3_l=robot->getMotor("L3_motor"); webots::Motor* R4_l=robot->getMotor("L4_motor"); RM1->setPosition(0); RM2->setPosition(0); RM3->setPosition(0); RM4->setPosition(0); R1_l->setPosition(INFINITY); R2_l->setPosition(INFINITY); R3_l->setPosition(INFINITY); R4_l->setPosition(INFINITY); R1_l->setVelocity(0.0); R2_l->setVelocity(0.0); R3_l->setVelocity(0.0); R4_l->setVelocity(0.0); webots::GPS* gps=robot->getGPS("gps"); webots::InertialUnit* imu=robot->getInertialUnit("imu"); webots::Gyro* gyr=robot->getGyro("gyro"); gyr->enable(timeStep); gps->enable(timeStep); imu->enable(timeStep); double w=2.5; double l=1.3; double radius=0.1915; double K=1.0/radius; auto last=std::chrono::steady_clock::now(); while (robot->step(timeStep) != -1) { auto now=std::chrono::steady_clock::now(); auto duration = std::chrono::duration_cast(now - last); double time = double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den; ////发布: //增加高斯分布 double x=gps->getValues()[2] + generae_random(generator,0,0.001); double y=gps->getValues()[0] + generae_random(generator,0,0.001); double theta=imu->getRollPitchYaw()[2]+generae_random(generator,0,0.3*M_PI/180.0); //获取gps速度,判断朝向 double vm1=R3_l->getVelocity()*radius; double vm2=-R4_l->getVelocity()*radius; double v=gps->getSpeed(); if(vm1+vm2<0.0) v=-v; //陀螺仪角速度 double vth=gyr->getValues()[1]; if(time>0.2) { printf(" publish delay................ time:%f -------------------------------------\n",time); } /*printf("dt:%f x y:%f %f, yaw:%f velocity:%f vth:%f %f %f\n",time, x,y,theta, v,gyr->getValues()[0],gyr->getValues()[1],gyr->getValues()[2]);*/ last=now; if(client_) { MqttMsg msg; msg.fromStatu(x,y,theta, v,vth); client_->publish("AgvStatu/robot1",1,msg); } //变速,角速度封顶 if(fabs(g_vth)>0.4) { g_vth=g_vth>0?0.4:-0.4; } //初始值 double R1=0,R2=0,R3=0,R4=0; double L1=g_v; double L2=g_v; double L3=g_v; double L4=g_v; double theta1=0; double theta2=0; //无角速度,直线 if(fabs(g_vth)<0.0001) { R1=R2=R3=R4=0; L1=L2=L3=L4=g_v; } else //有角速度 { if (fabs(g_v) < 0.00001) { //原地旋转 if (fabs(g_vth) > 0.0001) Rotating(g_vth, w / 2.0, l / 2.0, R1, R2, R3, R4, L1, L2, L3, L4); } else { //默认原地旋转 Rotating(g_vth, w / 2.0, l / 2.0, R1, R2, R3, R4, L1, L2, L3, L4); double base = pow(g_v / g_vth,2)-(l*l/4); //满足运动方程 if(base>=0.1) { double BaseR=sqrt(base)-w/2; if(BaseR>0) { if(g_vth*g_v>=0) { R1=atan(l/BaseR); R2=atan(l/(BaseR+w)); L3=BaseR*g_vth; L4=(BaseR+w)*g_vth; R3=0; R4=0; L1=L3/cos(R1); L2=L4/cos(R2); } else { R1=-atan(l/(BaseR+w)); R2=-atan(l/BaseR); L3=-(BaseR+w)*g_vth; L4=-BaseR*g_vth; R3=0; R4=0; L1=L3/cos(R1); L2=L4/cos(R2); } } } } } //printf(" R1-R4:%.5f %.5f %.5f %.5f L1-L4:%.5f %.5f %.5f %.5f V:%.5f Vth:%.5f\n", // R1,R2,R3,R4,L1,L2,L3,L4,v,vth); RM1->setPosition(R1); RM2->setPosition(R2); RM3->setPosition(R3); RM4->setPosition(R4); R1_l->setVelocity(L1*K); R2_l->setVelocity(-L2*K); R3_l->setVelocity(L3*K); R4_l->setVelocity(-L4*K); }; // Enter here exit cleanup code. delete robot; delete super; return 0; }