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
00038
00039
00040
00041
00042
00043 #include <labust_mission/labustMission.hpp>
00044 #include <labust_mission/maneuverGenerator.hpp>
00045
00046 #include <sensor_msgs/NavSatFix.h>
00047 #include <geometry_msgs/TransformStamped.h>
00048 #include <misc_msgs/StartNeptusParser.h>
00049
00050 #include <tf2_ros/transform_listener.h>
00051 #include <labust/tools/conversions.hpp>
00052 #include <labust/tools/GeoUtilities.hpp>
00053 #include <tinyxml2.h>
00054
00055 using namespace std;
00056 using namespace tinyxml2;
00057 using namespace labust::utils;
00058
00059
00060
00061
00062
00063 class NeptusParser{
00064
00065 public:
00066
00067
00068
00069
00070
00071 NeptusParser():startPointSet(false),
00072 startRelative(true),
00073 latLonAbs(false),
00074 underactuated(true),
00075 speed(0.5),
00076 heading(0.0),
00077 victory_radius(1.0){
00078
00079 offset.north = offset.east = 0;
00080 xmlSavePath = "";
00081 }
00082
00083 void neptusParserReset(){
00084
00085 startPointSet = false;
00086 startRelative = true;
00087 latLonAbs = false;
00088
00089 offset.north = offset.east = 0;
00090 xmlSavePath = "";
00091
00092 }
00093
00094 int parseNeptus(string xmlFile){
00095
00096
00097 if(xmlDoc.LoadFile(xmlFile.c_str()) == XML_SUCCESS) {
00098
00099 ROS_INFO("*.nmis mission file successfully loaded.");
00100
00101 MG.writeXML.addMission();
00102
00103
00104 XMLElement *graph = xmlDoc.FirstChildElement("mission-def")->FirstChildElement("body")
00105 ->FirstChildElement("plan")->FirstChildElement("graph");
00106
00107 for (XMLElement* node = graph->FirstChildElement(); node != NULL; node = node->NextSiblingElement()){
00108
00109
00110 if( XMLElement *maneuver = node->FirstChildElement("maneuver")){
00111
00112
00113 for (XMLElement* maneuverType = maneuver->FirstChildElement(); maneuverType != NULL; maneuverType = maneuverType->NextSiblingElement()){
00114
00115
00116 if(strcmp(maneuverType->ToElement()->Name(),"Goto") == 0){
00117
00118 ROS_ERROR("GoTo manevar");
00119 parseGoto(maneuverType);
00120
00121 } else if(strcmp(maneuverType->ToElement()->Name(),"Loiter") == 0){
00122
00123 ROS_ERROR("loiter manevar");
00124 parseLoiter(maneuverType);
00125
00126 } else if(strcmp(maneuverType->ToElement()->Name(),"RowsManeuver") == 0){
00127
00128 ROS_ERROR("lawnmower manevar");
00129 parseRows(maneuverType);
00130
00131 } else if(strcmp(maneuverType->ToElement()->Name(),"StationKeeping") == 0){
00132
00133 ROS_ERROR("DP manevar");
00134 parseStationKeeping(maneuverType);
00135 }
00136 }
00137 }
00138 }
00139
00140
00141 MG.writeXML.saveXML(xmlSavePath);
00142 return 1;
00143 } else {
00144 ROS_ERROR("Cannot open XML file!");
00145 return -1;
00146 }
00147 }
00148
00149
00150 void parseGoto(XMLElement *maneuverType){
00151
00152 ROS_INFO("Parsing goto maneuver...");
00153
00154 XMLElement *LatLonPoint = maneuverType->FirstChildElement("finalPoint")->FirstChildElement("point")->
00155 FirstChildElement("coordinate")->FirstChildElement("latitude");
00156
00157 ROS_ERROR("Lat: %s", LatLonPoint->ToElement()->GetText());
00158 string lat = LatLonPoint->ToElement()->GetText();
00159
00160 LatLonPoint = LatLonPoint->NextSiblingElement();
00161
00162 ROS_ERROR("Lon: %s", LatLonPoint->ToElement()->GetText());
00163 string lon = LatLonPoint->ToElement()->GetText();
00164
00165 auv_msgs::NED position;
00166 position = str2NED(lat,lon);
00167 ROS_ERROR("Preracunato: %f,%f", position.north, position.east);
00168
00169
00170 setStartPoint(position);
00171
00172
00173 double duration = 0;
00174
00175
00176 for (XMLElement* param = maneuverType->FirstChildElement("duration"); param != NULL; param = param->NextSiblingElement()){
00177
00178
00179 if( strcmp(param->ToElement()->Name(),"duration") == 0){
00180
00181 duration = atof(param->ToElement()->GetText());
00182 ROS_ERROR("Duration: %s", param->ToElement()->GetText());
00183
00184 }
00185 }
00186
00187
00188 if(underactuated)
00189 MG.writeXML.addGo2point_UA(position.north-offset.north, position.east-offset.east,speed,victory_radius);
00190 else
00191 MG.writeXML.addGo2point_FA(position.north-offset.north, position.east-offset.east,speed,victory_radius);
00192 }
00193
00194 void parseRows(XMLElement *maneuverType){
00195
00196 ROS_INFO("Parsing rows maneuver...");
00197
00198 XMLElement *LatLonPoint = maneuverType->FirstChildElement("basePoint")->FirstChildElement("point")->
00199 FirstChildElement("coordinate")->FirstChildElement("latitude");
00200
00201 ROS_ERROR("Lat: %s", LatLonPoint->ToElement()->GetText());
00202 string lat = LatLonPoint->ToElement()->GetText();
00203
00204 LatLonPoint = LatLonPoint->NextSiblingElement();
00205
00206 ROS_ERROR("Lon: %s", LatLonPoint->ToElement()->GetText());
00207 string lon = LatLonPoint->ToElement()->GetText();
00208
00209 auv_msgs::NED position;
00210 position = str2NED(lat,lon);
00211 ROS_ERROR("Preracunato: %f,%f", position.north, position.east);
00212
00213
00214 setStartPoint(position);
00215
00216
00217 double width = 100;
00218 double length = 200;
00219 double hstep = 27;
00220 double bearing = 0;
00221 double alternationPercent = 100;
00222 double curvOff = 15;
00223 double crossAngle = 0;
00224 bool squareCurve = true;
00225 bool invertY = false;
00226
00227
00228 for (XMLElement* param = maneuverType->FirstChildElement("width"); param != NULL; param = param->NextSiblingElement()){
00229
00230
00231 if( strcmp(param->ToElement()->Name(),"width") == 0){
00232
00233 width = atof(param->ToElement()->GetText());
00234 ROS_ERROR("Width: %s", param->ToElement()->GetText());
00235
00236 } else if(strcmp(param->ToElement()->Name(),"length") == 0){
00237
00238 length = atof(param->ToElement()->GetText());
00239 ROS_ERROR("length: %s", param->ToElement()->GetText());
00240
00241 } else if(strcmp(param->ToElement()->Name(),"hstep") == 0){
00242
00243 hstep = atof(param->ToElement()->GetText());
00244 ROS_ERROR("Hstep: %s", param->ToElement()->GetText());
00245
00246 } else if(strcmp(param->ToElement()->Name(),"bearing") == 0){
00247
00248 bearing = atof(param->ToElement()->GetText());
00249 ROS_ERROR("bearing: %s", param->ToElement()->GetText());
00250
00251
00252 } else if(strcmp(param->ToElement()->Name(),"crossAngle") == 0){
00253
00254 crossAngle = atof(param->ToElement()->GetText());
00255 ROS_ERROR("crossAngle: %s", param->ToElement()->GetText());
00256
00257 } else if(strcmp(param->ToElement()->Name(),"alternationPrecentage") == 0){
00258
00259 alternationPercent = atof(param->ToElement()->GetText());
00260 ROS_ERROR("alternationPercent: %s", param->ToElement()->GetText());
00261
00262 } else if(strcmp(param->ToElement()->Name(),"squareCurve") == 0){
00263
00264 if(strcmp(param->ToElement()->GetText(),"false")==0){
00265 squareCurve = false;
00266 } else {
00267 squareCurve = true;
00268 }
00269 ROS_ERROR("squareCurve: %s", param->ToElement()->GetText());
00270
00271 } else if(strcmp(param->ToElement()->Name(),"firstCurveRight") == 0){
00272
00273 if(strcmp(param->ToElement()->GetText(),"false")==0){
00274 invertY = true;
00275 } else {
00276 invertY = false;
00277 }
00278 ROS_ERROR("firstCurveRight: %s", param->ToElement()->GetText());
00279
00280 } else if(strcmp(param->ToElement()->Name(),"curveOffset") == 0){
00281
00282 curvOff = atof(param->ToElement()->GetText());
00283 ROS_ERROR("curveoffset: %s", param->ToElement()->GetText());
00284
00285 } else if(strcmp(param->ToElement()->Name(),"speed") == 0){
00286
00287 if(strcmp(param->ToElement()->Attribute("unit"),"RPM") == 0) {
00288
00289 ROS_ERROR("Speed units RPM. Leaving default speed: %f m/s", speed);
00290
00291 } else {
00292 speed = atof(param->ToElement()->GetText());
00293 ROS_ERROR("speed: %s", param->ToElement()->GetText());
00294 }
00295 }
00296 }
00297
00298 ROS_ERROR("width: %f, length: %f, hstep: %f, bearing: %f, alternationPercent: %f, curvOff: %f, crossAngle: %f, speed: %f, squareCurve: %d, invertY: %d", width, length, hstep, bearing, alternationPercent,curvOff, crossAngle,speed, squareCurve, invertY);
00299
00300
00301
00302 std::vector<Eigen::Vector4d> tmpPoints;
00303 tmpPoints = MG.calcRowsPoints(width, length, hstep,
00304 alternationPercent/100, curvOff, squareCurve, bearing*M_PI/180,
00305 crossAngle*M_PI/180, invertY);
00306
00307
00308 for(std::vector<Eigen::Vector4d>::iterator it = tmpPoints.begin(); it != tmpPoints.end(); ++it){
00309
00310 Eigen::Vector4d vTmp = *it;
00311 vTmp[X] += -offset.north + position.north;
00312 vTmp[Y] += -offset.east + position.east;
00313
00314 *it = vTmp;
00315 }
00316
00317
00318 if(underactuated)
00319 MG.writePrimitives(go2point_UA, tmpPoints, heading, speed, victory_radius);
00320 else
00321 MG.writePrimitives(go2point_FA, tmpPoints, heading, speed, victory_radius);
00322 }
00323
00324 void parseStationKeeping(XMLElement *maneuverType){
00325
00326 ROS_INFO("Parsing StationKeeping maneuver...");
00327
00328 XMLElement *LatLonPoint = maneuverType->FirstChildElement("basePoint")->FirstChildElement("point")->
00329 FirstChildElement("coordinate")->FirstChildElement("latitude");
00330
00331 ROS_ERROR("Lat: %s", LatLonPoint->ToElement()->GetText());
00332 string lat = LatLonPoint->ToElement()->GetText();
00333
00334 LatLonPoint = LatLonPoint->NextSiblingElement();
00335
00336 ROS_ERROR("Lon: %s", LatLonPoint->ToElement()->GetText());
00337 string lon = LatLonPoint->ToElement()->GetText();
00338
00339 auv_msgs::NED position;
00340 position = str2NED(lat,lon);
00341 ROS_ERROR("Preracunato: %f,%f", position.north, position.east);
00342
00343
00344 setStartPoint(position);
00345
00346
00347 MG.writeXML.addDynamic_positioning(position.north-offset.north, position.east-offset.east, heading);
00348
00349
00350 }
00351
00352 void parseLoiter(XMLElement *maneuverType){
00353
00354 }
00355
00356
00357
00358
00359
00360 auv_msgs::NED str2NED(string Lat, string Lon){
00361
00362 auv_msgs::NED position;
00363 sensor_msgs::NavSatFix LatLon;
00364 std::pair<double, double> posxy;
00365
00366 double DLat = atof(Lat.substr(0,2).c_str());
00367 double MLat = atof(Lat.substr(3,2).c_str());
00368 double SLat = atof(Lat.substr(6,17).c_str());
00369
00370 ROS_ERROR("DMS %f, %f, %f", DLat, MLat, SLat);
00371
00372 double DLon = atof(Lon.substr(0,2).c_str());
00373 double MLon = atof(Lon.substr(3,2).c_str());
00374 double SLon = atof(Lon.substr(6,17).c_str());
00375
00376 ROS_ERROR("DMS %f, %f, %f", DLon, MLon, SLon);
00377
00378 LatLon.latitude = DLat+MLat/60+SLat/3600;
00379 LatLon.longitude = DLon+MLon/60+SLon/3600;
00380
00381 ROS_ERROR("LAT LON %f, %f", LatLon.latitude, LatLon.longitude);
00382 ROS_ERROR("Origin LAT LON %f, %f", origin.latitude, origin.longitude);
00383
00384
00385
00386
00387 posxy = labust::tools::deg2meter(LatLon.latitude - origin.latitude, LatLon.longitude - origin.longitude, origin.latitude);
00388
00389 position.north = posxy.first;
00390 position.east = posxy.second;
00391 position.depth = 0;
00392
00393 return position;
00394 }
00395
00396 void setStartPoint(auv_msgs::NED position){
00397 if(!startPointSet){
00398 if(latLonAbs){
00399 offset.north = 0;
00400 offset.east = 0;
00401 ROS_ERROR("LATLON ABS prva tocka");
00402 }else{
00403 offset.north += position.north;
00404 offset.east += position.east;
00405 }
00406 startPointSet = true;
00407 }
00408 }
00409
00410
00411
00412
00413
00414 labust::maneuver::ManeuverGenerator MG;
00415 XMLDocument xmlDoc;
00416 sensor_msgs::NavSatFix startPoint;
00417
00418 auv_msgs::DecimalLatLon origin;
00419
00420 auv_msgs::NED offset;
00421 bool startPointSet;
00422 bool startRelative;
00423 bool latLonAbs;
00424 string xmlSavePath;
00425
00426
00427 bool underactuated;
00428 double speed, heading, victory_radius;
00429 };
00430
00431 void startParseCallback(ros::Publisher &pubStartDispatcher, const misc_msgs::StartNeptusParser::ConstPtr& msg){
00432
00433 ros::NodeHandle ph("~");
00434 NeptusParser NP;
00435 ph.param("xml_save_path", NP.xmlSavePath, NP.xmlSavePath);
00436 ROS_ERROR("%s",NP.xmlSavePath.c_str());
00437
00438 NP.startRelative = msg->relative;
00439 NP.latLonAbs = msg->customStartFlag;
00440 NP.startPoint.latitude = msg->customStart.latitude;
00441 NP.startPoint.longitude = msg->customStart.longitude;
00442
00443 NP.origin = msg->origin;
00444
00445 if(NP.startRelative){
00446 NP.offset.north = -NP.startPoint.latitude;
00447 NP.offset.east = -NP.startPoint.longitude;
00448 } else {
00449 NP.offset.north = NP.offset.east = 0;
00450 }
00451
00452 NP.underactuated = msg->underactuated;
00453 NP.speed = msg->speed;
00454 NP.heading = msg->heading;
00455
00456 NP.victory_radius = msg->victory_radius;
00457
00458
00459 if(NP.parseNeptus(msg->fileName) == 1){
00460 std_msgs::String tmp;
00461 tmp.data = "/START_DISPATCHER";
00462 pubStartDispatcher.publish(tmp);
00463 NP.neptusParserReset();
00464 }
00465 }
00466
00467 int main(int argc, char** argv){
00468
00469 ros::init(argc, argv, "neptusParser");
00470 ros::NodeHandle nh;
00471
00472
00473 ros::Publisher pubStartDispatcher = nh.advertise<std_msgs::String>("eventString",1);
00474
00475
00476 ros::Subscriber subStartParse = nh.subscribe<misc_msgs::StartNeptusParser>("startNeptusParse",1, boost::bind(&startParseCallback, boost::ref(pubStartDispatcher), _1));
00477
00478 ros::spin();
00479 return 0;
00480 }
00481
00482
00483
00484