00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 #include <labust/ros/diver_sim.h>
00038 #include <labust/math/NumberManipulation.hpp>
00039 
00040 #include <auv_msgs/NavSts.h>
00041 #include <sensor_msgs/JointState.h>
00042 
00043 using namespace labust::simulation;
00044 
00045 DiverSim::DiverSim():
00046                 jnames(20,""),
00047                 jdefaults(60,0),
00048                 move_head(false),
00049                 runSim(false),
00050                 Ts(0.1)
00051 {
00052         this->onInit();
00053 }
00054 
00055 void DiverSim::onInit()
00056 {
00057         ros::NodeHandle nh,ph("~");
00058 
00059         
00060         nh.param("simulation/sampling_time",Ts,Ts);
00061         
00062         ph.param("sampling_time", Ts, Ts);
00063         
00064         model.setTs(Ts);
00065 
00066         
00067         ph.param("joint_names",jnames,jnames);
00068         ph.param("joint_defaults",jdefaults,jdefaults);
00069         ph.param("move_head", move_head, move_head);
00070 
00071         if (jdefaults.size() != 3*jnames.size())
00072         {
00073                 ROS_ERROR("Parameter joint_defaults needs to have 3x the size of parameter joint_names.");
00074                 throw std::runtime_error("Invalid size of parameter joint_defaults");
00075         }
00076 
00077         
00078         for(int i=0; i<jnames.size(); ++i)
00079         {
00080                 jstate.name.push_back(jnames[i] + "_x");
00081                 jstate.name.push_back(jnames[i] + "_y");
00082                 jstate.name.push_back(jnames[i] + "_z");
00083         jstate.position.push_back(jdefaults[3*i]);
00084         jstate.position.push_back(jdefaults[3*i+1]);
00085         jstate.position.push_back(jdefaults[3*i+2]);
00086         }
00087 
00088         navsts = nh.advertise<auv_msgs::NavSts>("state",1);
00089         joints = nh.advertise<sensor_msgs::JointState>("joint_states",1);
00090         nusub = nh.subscribe<auv_msgs::BodyVelocityReq>("diver_nu",1,&DiverSim::onNu,this);
00091 
00092         runner = boost::thread(boost::bind(&DiverSim::start, this));
00093 }
00094 
00095 void DiverSim::start()
00096 {
00097         runSim = true;
00098         ros::Rate rate(1/Ts);
00099         while (ros::ok() && runSim)
00100         {
00101                 this->step();
00102                 rate.sleep();
00103         }
00104 }
00105 
00106 void DiverSim::step()
00107 {
00108         double hpan(0),htilt(0);
00109         auv_msgs::NavSts::Ptr nav(new auv_msgs::NavSts());
00110         {
00111                 boost::mutex::scoped_lock l(nu_mux);
00112                 labust::tools::vectorToPoint(nu, nav->body_velocity);
00113                 labust::tools::vectorToRPY(nu, nav->orientation_rate,3);
00114                 if (move_head)
00115                 {
00116                         enum {p = 3, q =4};
00117                         hpan = nu(p);
00118                         htilt = nu(q);
00119                         
00120                         nu(p) = 0;
00121                         nu(q) = 0;
00122                 }
00123                 
00124                 model.step(nu);
00125                 if (move_head)
00126                 {
00127                         enum {p = 3, q =4};
00128                         
00129                         nu(p) = hpan;
00130                         nu(q) = htilt;
00131                 }
00132         }
00133 
00134         labust::tools::vectorToNED(model.position(), nav->position);
00135         labust::tools::vectorToRPY(model.orientation(), nav->orientation);
00136         
00137         nav->orientation.roll = 0;
00138         nav->orientation.pitch = 0;
00139         nav->header.stamp = ros::Time::now();
00140         navsts.publish(nav);
00141 
00142         
00143         this->stepJoints(nav->body_velocity.x*4, hpan, htilt);
00144         jstate.header.stamp = ros::Time::now();
00145         joints.publish(jstate);
00146 }
00147 
00148 void DiverSim::stepJoints(double w, double hpan, double htilt)
00149 {
00150         const double FOOT_LAG(M_PI/2-M_PI/12);
00151         const double THIGH_LAG(-M_PI/12);
00152         static double t=0;
00153         static double w0=0;
00154         static double T=0.4;
00156         enum {LCALF=3*12+1, RCALF=3*17+1,
00157                 LFOOT=3*11+1, RFOOT=3*18+1,
00158                 LTHIGH=3*13+1, RTHIGH=3*16+1,
00159                 LBACKZ=3*14+2, LBACKX=3*14,
00160                 HEADZ = 3*3+2, HEADY = 3*3+1};
00161         double C = w0*t;
00162         w0 = (w*Ts + w0*T)/(Ts+T);
00163         t = ((fabs(w0) > 0.01)?C/w0:0);
00164         t += Ts;
00165 
00166         jstate.position[LCALF] = jdefaults[LCALF] + M_PI/12*sin(w0*t);
00167         jstate.position[LFOOT] = jdefaults[LFOOT] - M_PI/12*sin(w0*t+FOOT_LAG);
00168         jstate.position[LTHIGH] = jdefaults[LTHIGH] + M_PI/36*sin(w0*t+THIGH_LAG);
00169         jstate.position[RCALF] = jdefaults[RCALF] - M_PI/12*sin(w0*t);
00170         jstate.position[RFOOT] = jdefaults[RFOOT] + M_PI/12*sin(w0*t+FOOT_LAG);
00171         jstate.position[RTHIGH] = jdefaults[RTHIGH] - M_PI/36*sin(w0*t+THIGH_LAG);
00172 
00173         
00174         
00175 
00176         
00177         jstate.position[HEADZ] = labust::math::wrapRad(jdefaults[HEADZ] + hpan);
00178         jstate.position[HEADY] = labust::math::wrapRad(jdefaults[HEADY] + htilt);
00179 }
00180 
00181 int main(int argc, char* argv[])
00182 {
00183         ros::init(argc,argv,"diver_sim");
00184         ros::NodeHandle nh;
00185 
00186         labust::simulation::DiverSim diver_simulator;
00187 
00188         ros::spin();
00189         return 0;
00190 }