#include #include #include #include #include #include #include "emqx-client/mqttmsg.h" #include "emqx-client/paho_client.h" #include #include #include #include "timedlockdata.hpp" // All the webots classes are defined in the "webots" namespace using namespace webots; Paho_client* client_= nullptr; TimedLockData g_speed; void SpeedChangeCallback(std::string topic,int QOS,MqttMsg& msg,void* context) { NavMessage::ToAgvCmd speed; msg.toProtoMessage(speed); g_speed.reset(speed,0.3); } 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); } void Vrtical(double velocity,double wmg,double w,double l,double& R1,double& R2,double& R3,double& R4, double& L1,double& L2,double& L3,double& L4) { if (fabs(wmg) < 0.0001) { R1 = R2 = R3 = R4 = 0; L1 = L2 = L3 = L4 = velocity; printf("virtical111 R1-R4:%.5f %.5f %.5f %.5f L1-L4:%.5f %.5f %.5f %.5f \n", R1,R2,R3,R4,L1,L2,L3,L4); } else {//有角速度 double base = pow(velocity / wmg, 2) - (l * l / 4); //满足运动方程 if (base >= 0.0001) { double BaseR = sqrt(base) - w / 2; if (BaseR < 0.05) BaseR = 0.05; //printf("BaseR : %f \n",BaseR); if (BaseR > 0) { if (wmg * velocity >= 0) { R1 = atan(l / BaseR); R2 = atan(l / (BaseR + w)); L3 = BaseR * wmg; L4 = (BaseR + w) * wmg; 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) * wmg; L4 = -BaseR * wmg; R3 = 0; R4 = 0; L1 = L3 / cos(R1); L2 = L4 / cos(R2); } printf("virtical222 R1-R4:%.5f %.5f %.5f %.5f L1-L4:%.5f %.5f %.5f %.5f \n", R1,R2,R3,R4,L1,L2,L3,L4); } } } } void Horizontal(double velocity,double wmg,double w,double l,double& R1,double& R2,double& R3,double& R4, double& L1,double& L2,double& L3,double& L4) { Vrtical(velocity,wmg,w,l,R3,R1,R4,R2,L3,L1,L4,L2); if (fabs(wmg) < 0.0001) { R1 = -M_PI / 2.0; R2 = M_PI / 2.0; R3 = M_PI / 2.0; R4 = -M_PI / 2.0; L1 = -velocity; L2 = velocity; L3 = velocity; L4 = -velocity; }else{ R1-=M_PI/2.0; R2+=M_PI/2.0; R3+=M_PI/2.0; R4-=M_PI/2.0; L1=-L1; L4=-L4; } } int main(int argc, char **argv) { //init mqtt if(false==init_mqtt("127.0.0.1",1883,"webots-child","ChildPLC/speedcmd")) { 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. 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); /*RM1->setTorque(100); RM2->setTorque(100); RM3->setTorque(100); RM4->setTorque(100);*/ 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.007); double y=gps->getValues()[0] + generae_random(generator,0,0.007); double theta=imu->getRollPitchYaw()[2]+generae_random(generator,0,0.1*M_PI/180.0); //获取gps速度,判断朝向 double vm1=R3_l->getVelocity()*radius; double vm2=-R2_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; NavMessage::LidarOdomStatu odom; odom.set_x(x); odom.set_y(y); odom.set_theta(theta); odom.set_v(v); odom.set_vth(vth); msg.fromProtoMessage(odom); client_->publish("lidar_odom/child",1,msg); NavMessage::AgvStatu speed; speed.set_v(v); speed.set_w(vth); speed.set_clamp(0); speed.set_clamp_other(0); msg.fromProtoMessage(speed); client_->publish("ChildPLC/speed",1,msg); } if(g_speed.timeout()) { RM1->setPosition(0); RM2->setPosition(0); RM3->setPosition(0); RM4->setPosition(0); R1_l->setVelocity(0); R2_l->setVelocity(0); R3_l->setVelocity(0); R4_l->setVelocity(0); continue; } //变速---------------------------------- double cmd_v=g_speed.Get().v(); double cmd_vth=g_speed.Get().w(); //初始值 double R1=0,R2=0,R3=0,R4=0; double L1=cmd_v; double L2=cmd_v; double L3=cmd_v; double L4=cmd_v; if(g_speed.Get().t()==1) //原地旋转 { printf("旋转:"); if (fabs(cmd_vth) > 0.0001) Rotating(cmd_vth, w / 2.0, l / 2.0, R1, R2, R3, R4, L1, L2, L3, L4); } else if(g_speed.Get().t()==2) //横移 { printf("横移:"); if (fabs(cmd_vth) > 0.4) { cmd_vth = cmd_vth > 0 ? 0.4 : -0.4; } Horizontal(cmd_v,cmd_vth,l,w,R1, R2, R3, R4, L1, L2, L3, L4); } else if(g_speed.Get().t()==3){ //巡线/前进 printf("前进:"); if (fabs(cmd_vth) > 0.4) { cmd_vth = cmd_vth > 0 ? 0.4 : -0.4; } Vrtical(cmd_v,cmd_vth,w,l,R1,R2,R3,R4,L1,L2,L3,L4); } printf("Child 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,cmd_v,cmd_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; return 0; }