navigation_master.cpp
Go to the documentation of this file.
00001 #include "ros/ros.h"
00002 #include "visualization_msgs/MarkerArray.h"
00003 #include "visualization_msgs/Marker.h"
00004 #include "tf/transform_broadcaster.h"
00005 #include "tf/transform_listener.h"
00006 #include "bipedRobin_msgs/InitialStepsService.h"
00007 #include "bipedRobin_msgs/SetModeService.h"
00008 #include "bipedRobin_msgs/StepTarget3DService.h"
00009 #include "std_srvs/Empty.h"
00010 #include "std_msgs/UInt8.h"
00011 #include <string.h>
00012  /*
00013                 Dieser Knoten übernimmt die Koordinierung zwischen Roboter und FootstepPlanner
00014                 Services die Angeboten werden:
00015                 Statische Planung
00016                 Dynamsiche Planung
00017                 Replan: Neuplanung der Schritte
00018                 CreateMap: Neu Karte erstellen
00019                 Localize: Lokalisieren des Roboters im Raum
00020                 Walk: Durchführen der geplanten Schritte
00021  */
00022 #define DEFAULT_VARIABLE_NUMBER 150
00023 #define DEFAULT_WORDLENGTH 20   /* multible of 4 and compatible with simulink receiving file */
00024 
00025 //Funktionen
00026 void staticInitialSteps();
00027 void setInitialSteps(tf::StampedTransform left, tf::StampedTransform right);
00028 void setInitialStep();
00029 void staticPlanning();
00030 void dynamicPlanning();
00031 void localize();
00032 void createMap();
00033 void goalpose();
00034 void replan();
00035 void restart();
00036 void pub_goal();
00037 void sendMarker(visualization_msgs::Marker step, tf::StampedTransform map);
00038 void setdynamicInitialSteps(visualization_msgs::Marker left, visualization_msgs::Marker right, tf::StampedTransform map);
00039 
00040 //Clients Subscriber Publisher
00041 ros::ServiceClient initialStep_client;
00042 ros::ServiceClient initialSteps_client;
00043 ros::ServiceClient localize_client;
00044 ros::ServiceClient createMap_client;
00045 ros::ServiceClient footstep_client;
00046 ros::ServiceClient goalpose_client;
00047 ros::ServiceClient restart_client;
00048 ros::Subscriber markerArray;
00049 ros::Subscriber goalpose_sub;
00050 ros::Publisher goal_pub;
00051 
00052 //Flags
00053 bool isReal;
00054 bool sendStep_flag = false;
00055 bool first_call_flag = true;
00056 bool newMarkerArray_flag = false;
00057 bool walk_flag = false;
00058 bool plan_flag = false;
00059 bool staticPlanner_flag = false;
00060 bool finished = false;
00061 bool random_flag = true;
00062 
00063 int dynamic_left_right = 1;
00064 int stepsLeftInBuffer = 0;
00065 int dynamicBufferSize = 0;
00066 int stepBufferSize = 0;
00067 
00068 visualization_msgs::MarkerArray currentFootsteps;
00069 geometry_msgs::PoseStamped currentGoalpose;
00070 tf::StampedTransform old_left;
00071 tf::StampedTransform old_right;
00072 
00073 static tf::TransformListener* pListener = NULL;
00074 static tf::TransformBroadcaster* pBroadcaster = NULL;
00075 
00076 void localize(){ //Ruft die Lokalisierung auf
00077         ROS_INFO("localize Service called");
00078         std_srvs::Empty srv;
00079         localize_client.call(srv);
00080 }
00081 
00082 void createMap(){ //Erstellt eine neue Karte
00083         ROS_INFO("createMap Service called");
00084         std_srvs::Empty srv;    
00085         createMap_client.call(srv);             
00086 }
00087 
00088 void goalpose(){ //Published die Koordinaten des Zielmarkers falls vorhanden
00089         ROS_INFO("Automatic Goalpose Service called");
00090         std_srvs::Empty srv;
00091         goalpose_client.call(srv);
00092 }
00093 
00094 void restart(){ //Startet den FootstepPlanner neue
00095         ROS_INFO("Planner restart Service called");
00096         std_srvs::Empty srv;
00097         restart_client.call(srv);
00098 }
00099 
00100 void replan(){
00101         ROS_INFO("replan Service called");
00102         newMarkerArray_flag = false;    //neue Schritte zu lassen
00103         setInitialSteps(old_left, old_right); //alte Startschritte setzen       
00104         ros::spinOnce();        
00105         goalpose();  //einlesen der Zielmarker Position
00106         ros::spinOnce();                        
00107         createMap(); //Neu erstellen der Karte
00108         ros::spinOnce();
00109         pub_goal(); //Ziel erneut an den FootstepPlanner schicken um neuPlanung zu starten.
00110 }
00111 
00112 void pub_goal(){ //Published das Ziel um eine neuplanung zu erwirken
00113         ROS_INFO("Goal republished");
00114         geometry_msgs::PoseStamped goalpose = currentGoalpose;  
00115         if(random_flag){ //Selbes Ziel führt zu keiner Neuplanung deswegen zufalls zahlen hinzu addieren
00116                 goalpose.pose.position.x += (rand()%5) * 0.01;
00117                 goalpose.pose.position.y += (rand()%5) * 0.01;
00118         }
00119         goalpose.header.stamp = ros::Time::now();
00120         goal_pub.publish(goalpose);     
00121 }
00122 
00123 //Sender einen als Schritt Koordinaten an den Roboter
00124 void sendMarker(visualization_msgs::Marker step, tf::StampedTransform map){     
00125         tf::StampedTransform marker;
00126         tf::Vector3 marker_Vector;
00127         tf::Quaternion marker_Rotation; 
00128         marker_Vector.setX(step.pose.position.x);
00129         marker_Vector.setY(step.pose.position.y);
00130         marker_Vector.setZ(step.pose.position.z);
00131         marker_Rotation.setX(step.pose.orientation.x);
00132         marker_Rotation.setY(step.pose.orientation.y);
00133         marker_Rotation.setZ(step.pose.orientation.z);
00134         marker_Rotation.setW(step.pose.orientation.w);
00135         marker.setOrigin(marker_Vector);
00136         marker.setRotation(marker_Rotation);            
00137         marker.mult(map, marker);
00138         bipedRobin_msgs::StepTarget3DService srv;
00139         //unterscheiden zwischen linken und rechten fuß
00140         if(step.color.r > 0) { //links
00141                 srv.request.step.leg = 1;
00142         } else { //rechts
00143                 srv.request.step.leg = 0;
00144         }
00145         srv.request.step.pose.position.x = marker.getOrigin().x();
00146         srv.request.step.pose.position.y = marker.getOrigin().y();
00147         srv.request.step.pose.position.z = 0;
00148         srv.request.step.pose.orientation.x = marker.getRotation().x();
00149         srv.request.step.pose.orientation.y = marker.getRotation().y();
00150         srv.request.step.pose.orientation.z = marker.getRotation().z();
00151         srv.request.step.pose.orientation.w = marker.getRotation().w();                                                                 
00152         footstep_client.call(srv);
00153 }
00154 
00155 //Funktion für die eigentliche Schrittplanung
00156 void dynamicPlanning(){
00157         restart();      //neustarten des Planners
00158         ros::Duration(3).sleep();
00159         ros::spinOnce();
00160         if(first_call_flag) {   //nur beim aller ersten Aufruf durchführen
00161                 setInitialStep(); 
00162                 localize();     
00163                 ros::Duration(2).sleep();                               
00164         } else {
00165                 sendStep_flag = true;
00166         }               
00167         createMap();
00168         staticInitialSteps();   //Wirkliche Fuß Posiotenen als StartSchritte setzen.
00169         int currentStep = 0;  //Aktueller Schritt der gesendet werden soll
00170         tf::StampedTransform map;  //Transformation zu map Koordinaten
00171         visualization_msgs::Marker temp[stepBufferSize];
00172         visualization_msgs::Marker Buffer[stepBufferSize];  //dynamischer Buffer
00173         visualization_msgs::Marker left;
00174         visualization_msgs::Marker right;
00175         int stepsInDynamicBuffer = 0; //Schritte die noch im dynamischen Buffer liegen
00176         finished = false;  //Variable ob Zielposition erreicht 
00177         bool replan_flag = true;
00178         first_call_flag = true;
00179         walk_flag = false;
00180         ros::Rate loop_rate(100);
00181         try {                           
00182                 pListener->lookupTransform("/odom", "/map", ros::Time(0), map);
00183         } catch (tf::TransformException ex) {                                                   
00184         }
00185         while(ros::ok){
00186                 if(replan_flag){                                
00187                         ROS_INFO("Planning started");                   
00188                         goalpose();                     
00189                         createMap();
00190                         ros::spinOnce();
00191                         pub_goal();
00192                         newMarkerArray_flag = false;
00193                         ROS_INFO("Waiting for walk approval");
00194                         if(walk_flag){
00195                                 ROS_INFO("Waiting for new Footsteps from Planner");             
00196                                 while(!newMarkerArray_flag) ros::spinOnce(); loop_rate.sleep(); 
00197                                 newMarkerArray_flag = false;
00198                                 int count = 0;
00199                                 while(!newMarkerArray_flag && (count < 30)){
00200                                         ros::spinOnce(); 
00201                                         loop_rate.sleep();      
00202                                         count++; 
00203                                 }
00204                 ROS_INFO("Footsteps received. executing");      
00205                         }
00206                         while(!walk_flag) {                     
00207                                 ros::spinOnce(); 
00208                                 loop_rate.sleep();      
00209                         }                               
00210                         first_call_flag = false;                
00211                         replan_flag = false;                    
00212                         
00213                         visualization_msgs::MarkerArray footsteps = currentFootsteps;
00214                         int startStep = 2;
00215 
00216                         if(fabs(footsteps.markers[2].pose.position.x - footsteps.markers[0].pose.position.x) < 0.05 && fabs(footsteps.markers[2].pose.position.y - footsteps.markers[0].pose.position.y) < 0.05){
00217                                 if(footsteps.markers.size() > 3){                               
00218                                         startStep = 3;  
00219                                 }               
00220                         }       
00221                         if(((footsteps.markers[startStep].color.r > 0) && (dynamic_left_right == 1)) || ((footsteps.markers[startStep].color.g > 0) && (dynamic_left_right == 0))){
00222                                 startStep--;
00223                         }                               
00224                         int i = startStep;
00225                         int k = 0;                      
00226                         while(i < startStep+stepBufferSize && i < footsteps.markers.size()){
00227                                 temp[k] = footsteps.markers[i];                         
00228                                 i++; k++; stepsInDynamicBuffer++;               
00229                         }
00230                         if(i == footsteps.markers.size()){
00231                                 finished = true;        
00232                                 if(temp[k-1].color.r > 0) {
00233                                         left = temp[k-1];
00234                                         dynamic_left_right = 1; 
00235                                 } else {
00236                                         right = temp[k-1];
00237                                         dynamic_left_right = 0;
00238                                 }
00239                         }       else {
00240                                 finished = false;                       
00241                                 if(temp[k-1].color.r > 0) {
00242                                         left = temp[k-1];
00243                                         right = temp[k-2];
00244                                         dynamic_left_right = 1;
00245                                 } else {
00246                                         right = temp[k-1];
00247                                         left = temp[k-2];
00248                                         dynamic_left_right = 0;
00249                                 }
00250                         }
00251                                                         
00252                 }                       
00253                 
00254                 if(currentStep == 0){
00255                         for(int p = 0; p < stepBufferSize; p++){
00256                                 Buffer[p] = temp[p];                            
00257                         }                       
00258                         setdynamicInitialSteps(left, right, map);               
00259                 }       
00260                 
00261                 if(currentStep == stepBufferSize) {
00262                         currentStep = 0;
00263                         replan_flag = true;
00264                 }       
00265 
00266                 if(finished && stepsInDynamicBuffer == 0){
00267                         ROS_INFO("Reached Target destination");
00268                         walk_flag = false;
00269                         break;
00270                 }
00271                 
00272                 if(sendStep_flag && !replan_flag){      
00273                         sendStep_flag = false;
00274                         sendMarker(Buffer[currentStep], map);
00275                         currentStep++;
00276                         stepsInDynamicBuffer--;
00277                 }
00278                 loop_rate.sleep();      
00279                 ros::spinOnce();                                
00280         }
00281         ros::spinOnce();
00282 }
00283 
00284 //Funktion zum setzen der Startschritte des FootstepPlanners auf bestimmte Positionen
00285 void setdynamicInitialSteps(visualization_msgs::Marker leftMarker, visualization_msgs::Marker rightMarker,      tf::StampedTransform map){
00286         ROS_INFO("setdynamicInitialSteps Service called");
00287         tf::StampedTransform left;
00288         tf::StampedTransform right;
00289         tf::Vector3 marker_Vector;
00290         tf::Quaternion marker_Rotation; 
00291         marker_Vector.setX(leftMarker.pose.position.x);
00292         marker_Vector.setY(leftMarker.pose.position.y);
00293         marker_Vector.setZ(leftMarker.pose.position.z);
00294         marker_Rotation.setX(leftMarker.pose.orientation.x);
00295         marker_Rotation.setY(leftMarker.pose.orientation.y);
00296         marker_Rotation.setZ(leftMarker.pose.orientation.z);
00297         marker_Rotation.setW(leftMarker.pose.orientation.w);
00298         left.setOrigin(marker_Vector);
00299         left.setRotation(marker_Rotation);
00300         bipedRobin_msgs::InitialStepsService srv;
00301 
00302         marker_Vector.setX(rightMarker.pose.position.x);
00303         marker_Vector.setY(rightMarker.pose.position.y);
00304         marker_Vector.setZ(rightMarker.pose.position.z);
00305         marker_Rotation.setX(rightMarker.pose.orientation.x);
00306         marker_Rotation.setY(rightMarker.pose.orientation.y);
00307         marker_Rotation.setZ(rightMarker.pose.orientation.z);
00308         marker_Rotation.setW(rightMarker.pose.orientation.w);
00309         right.setOrigin(marker_Vector);
00310         right.setRotation(marker_Rotation);     
00311 
00312         setInitialSteps(left, right);   
00313 }
00314 
00315 //Funktion zum Setzen der Startschritte des FootstepPlanners auf die aktuellen Positionen
00316 void staticInitialSteps(){
00317         ROS_INFO("set staticInitialSteps Service called");
00318         tf::StampedTransform left;
00319         tf::StampedTransform right;
00320 
00321         try {
00322                 pListener->lookupTransform("/map", "l_sole", ros::Time(0), left);
00323         } catch (tf::TransformException ex) {
00324         }
00325 
00326         try {
00327                 pListener->lookupTransform("/map", "r_sole", ros::Time(0), right);
00328         } catch (tf::TransformException ex) {
00329         }
00330         setInitialSteps(left, right);   
00331 }
00332 
00333 
00334 //Funktion zum Senden der Startschritte des FootstepPlanners and den Planner
00335 void setInitialSteps(tf::StampedTransform left, tf::StampedTransform right){
00336         
00337         old_left = left;  
00338         old_right = right;
00339 
00340         bipedRobin_msgs::InitialStepsService srv;
00341         
00342         srv.request.left.leg=1; 
00343         srv.request.left.pose.position.x = left.getOrigin().x();
00344         srv.request.left.pose.position.y = left.getOrigin().y();
00345         srv.request.left.pose.position.z = left.getOrigin().z();
00346         srv.request.left.pose.orientation.x = left.getRotation().x();
00347         srv.request.left.pose.orientation.y = left.getRotation().y();
00348         srv.request.left.pose.orientation.z = left.getRotation().z();
00349         srv.request.left.pose.orientation.w = left.getRotation().w();
00350         
00351         srv.request.right.leg=0;
00352         srv.request.right.pose.position.x = right.getOrigin().x();
00353         srv.request.right.pose.position.y = right.getOrigin().y();
00354         srv.request.right.pose.position.z = right.getOrigin().z();
00355         srv.request.right.pose.orientation.x = right.getRotation().x();
00356         srv.request.right.pose.orientation.y = right.getRotation().y();
00357         srv.request.right.pose.orientation.z = right.getRotation().z();
00358         srv.request.right.pose.orientation.w = right.getRotation().w();
00359         
00360         initialSteps_client.call(srv); 
00361 }
00362 
00363 //Funktion zum Setzen des InitialStep
00364 void setInitialStep(){
00365         ROS_INFO("setInitialStep Service called");      
00366         tf::StampedTransform step;
00367         try {
00368                 pListener->lookupTransform("/odom", "/l_sole", ros::Time(0), step);
00369         } catch (tf::TransformException ex) {
00370         }       
00371         bipedRobin_msgs::StepTarget3DService srv;       
00372         srv.request.step.leg=1; 
00373         srv.request.step.pose.position.x = step.getOrigin().x();
00374         srv.request.step.pose.position.y = step.getOrigin().y();
00375         srv.request.step.pose.position.z = step.getOrigin().z();
00376         srv.request.step.pose.orientation.x = step.getRotation().x();
00377         srv.request.step.pose.orientation.y = step.getRotation().y();
00378         srv.request.step.pose.orientation.z = step.getRotation().z();
00379         srv.request.step.pose.orientation.w = step.getRotation().w();
00380         initialStep_client.call(srv);
00381 }
00382 
00383 //Callback um statischen Planner zu starten
00384 bool staticPlanningCallback(std_srvs::Empty::Request &req, std_srvs::Empty::Request &res) {
00385         if(!plan_flag){ //Verhindern das Planner gestartet wird wenn ein andere läuft  
00386                 ROS_INFO("staticPlanning Service started");
00387                 stepBufferSize = 100; //Anzahl der Schritt bevor eine Neuplanung statt findet -> statisch
00388                 staticPlanner_flag = true;      
00389                 plan_flag = true; //flag um planner aufzurufen
00390         }
00391         return true;
00392 }
00393 
00394 //Callback um dynamischen Planner zu starten
00395 bool dynamicPlanningCallback(std_srvs::Empty::Request &req, std_srvs::Empty::Request &res) {
00396         if(!plan_flag){         
00397                 ROS_INFO("dynamicPlanning Service started");
00398                 stepBufferSize = dynamicBufferSize; //Anzahl der Schritte bevor Neuplanung statt findet default 3               
00399                 staticPlanner_flag = false;
00400                 plan_flag = true; //flag um planner aufzurufen
00401         }
00402         return true;
00403 }
00404 
00405 //Callback um freigabe zum Gehen zu erteilen
00406 bool walkCallback(std_srvs::Empty::Request &req, std_srvs::Empty::Request &res){
00407         walk_flag = true;
00408         return true;
00409 }
00410 
00411 //Calback für neue Schritt aus FootstepPlanner
00412 void newStepsArrayCallback(const visualization_msgs::MarkerArray markerArray) {
00413         bool ignore = false;
00414         //Verhindern das leere Schritte akzeptiert werden:
00415         for(int i=0; i < markerArray.markers.size(); i++){
00416                 if(markerArray.markers[i].color.r == 0 && markerArray.markers[i].color.g == 0) ignore = true;   
00417         }
00418         //Nur wenn mindestens 3 Schritte und neue Schritte gefordert sind bzw. der staticPlanner läuft die Schritte abspeichern
00419         if(markerArray.markers.size() > 2 && !ignore && (!newMarkerArray_flag || staticPlanner_flag)){
00420                 ROS_INFO("New Footsteps received");
00421                 //Wenn noch mehr als 6 Schritte zu gehen sind (2 sind Startposition) dann das Ziel random Posten.               
00422                 if(markerArray.markers.size() < 7){
00423                         random_flag = false;
00424                 } else {
00425                         random_flag = true;
00426                 }
00427                 currentFootsteps = markerArray;
00428                 newMarkerArray_flag = true;
00429         }       
00430 }
00431 
00432 //Callback für Aktuellen Schrittpuffer am Roboter
00433 void stepsLeftCallback(std_msgs::UInt8 stepsLeft) {
00434         stepsLeftInBuffer = stepsLeft.data;     //Schritte für dynamischen Planner setzen
00435         if(stepsLeft.data == 0){ //keine Schritte mehr im Buffer
00436                 ros::Duration(0.8).sleep(); //warten bevor neuer Schritt gesendet wird
00437                 sendStep_flag = true; //neuen Schritt senden
00438         }
00439 }
00440 
00441 //Callback für aktuelles Ziel
00442 void goalCallback(geometry_msgs::PoseStamped pose){
00443         newMarkerArray_flag = false;
00444         currentGoalpose = pose; //speichert das Ziel ab um es bei Bedarf neu im Planner zu setzen
00445         //replan();
00446 }
00447 
00448 //Callback um neuplanen der Schritte zu erzwingen
00449 bool replanCallback(std_srvs::Empty::Request &req, std_srvs::Empty::Request &res)       {
00450         replan();
00451         return true;
00452 }
00453 
00454 int main(int argc, char **argv)
00455 {
00456   /* init ROS */  
00457   
00458         ros::init(argc, argv, "navigation_master");
00459         pListener = new(tf::TransformListener);
00460         pBroadcaster = new(tf::TransformBroadcaster);   
00461 
00462         ros::NodeHandle n;
00463         
00464         n.param("/par_isRealEnvironment", isReal, false); //real oder simulated
00465         n.param("/par_stepBufferSize", dynamicBufferSize, 5); //Anzahl der Schritt bevor Neuplanung stattfindet
00466 
00467         //Service Server
00468         ros::ServiceServer staticPlanning_srv = n.advertiseService("staticPlanning_srv", staticPlanningCallback);
00469         ros::ServiceServer dynamicPlanning_srv = n.advertiseService("dynamicPlanning_srv", dynamicPlanningCallback);
00470         ros::ServiceServer walk_srv = n.advertiseService("walk_srv", walkCallback);
00471         ros::ServiceServer replan_srv = n.advertiseService("replan_srv", replanCallback);
00472         
00473         //subscriber
00474         markerArray = n.subscribe<visualization_msgs::MarkerArray>("bipedRobin_footstep_planner/footsteps_array", 1, newStepsArrayCallback);
00475         ros::Subscriber stepsLeftInBuffer_sub = n.subscribe<std_msgs::UInt8>("stepsLeftInBuffer", 1, stepsLeftCallback);
00476         goalpose_sub = n.subscribe<geometry_msgs::PoseStamped>("goal2", 0, goalCallback);
00477 
00478         //Service clients
00479         initialStep_client = n.serviceClient<bipedRobin_msgs::StepTarget3DService>("initialstep_srv");  
00480         initialSteps_client = n.serviceClient<bipedRobin_msgs::InitialStepsService>("initialSteps_srv");                
00481         localize_client = n.serviceClient<std_srvs::Empty>("localize_srv");                     
00482         restart_client = n.serviceClient<std_srvs::Empty>("restart_srv");
00483         createMap_client = n.serviceClient<std_srvs::Empty>("createMap_srv");
00484         footstep_client = n.serviceClient<bipedRobin_msgs::StepTarget3DService>("footstep3D_srv");      
00485         goalpose_client = n.serviceClient<std_srvs::Empty>("goalpose_srv");
00486         
00487         //publisher
00488         goal_pub = n.advertise<geometry_msgs::PoseStamped>("goal", 1000);
00489         
00490 
00491         //Schleife um Planung zu starten, notwendig damit Service return sendet ohne auf Fertigstellung des Planners zu warten.
00492         while(ros::ok()){
00493                 if(plan_flag){
00494                         dynamicPlanning();
00495                 }
00496                 plan_flag = false;
00497                 ros::spinOnce();
00498         }
00499 
00500         return 0; 
00501 }
00502 
00503 


biped_robin_navigation
Author(s): Johannes Mayr, Johannes Mayr
autogenerated on Mon Jan 6 2014 11:09:45