ExecControl.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, LABUST, UNIZG-FER
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the LABUST nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  *  Author: Dula Nad
00035  *  Created: 30.10.2013.
00036  *********************************************************************/
00037 #include <labust/control/ExecControl.hpp>
00038 
00039 #include <boost/graph/graphviz.hpp>
00040 #include <boost/graph/dijkstra_shortest_paths.hpp>
00041 
00042 #include <std_msgs/String.h>
00043 
00044 #include <fstream>
00045 #include <iostream>
00046 
00047 using namespace labust::control;
00048 
00049 ExecControl::ExecControl():
00050                 tnum(0),
00051                 pnum(6),
00052                 marking(pnum)
00053 {
00054         this->onInit();
00055 }
00056 
00057 void ExecControl::onInit()
00058 {
00059         ros::NodeHandle nh,ph("~");
00060         depGraphPub = nh.advertise<std_msgs::String>("dependency_graph",1);
00061         pnGraphPub = nh.advertise<std_msgs::String>("petri_net_graph",1);
00062 
00063         registerController = nh.advertiseService("register_controller",
00064                         &ExecControl::onRegisterController, this);
00065 
00066         activateController = nh.subscribe<std_msgs::String>("activate_cnt",1,
00067                         &ExecControl::onActivateController, this);
00068 
00069         //Import main vertex names
00070         std::string dofs[]={"X","Y","Z","K","M","N"};
00071         //Add DOFs to the name list
00072         for (int i=X; i<=N;++i)
00073         {
00074                 boost::add_vertex(VertexProperty(dofs[i],VertexProperty::p),graph);
00075                 marking(i) = 1;
00076                 pname[i] = dofs[i];
00077         }
00078 }
00079 
00080 bool ExecControl::onRegisterController(
00081                 navcon_msgs::RegisterController::Request& req,
00082                 navcon_msgs::RegisterController::Response& resp)
00083 {
00084         //Check if controller with same name exists.
00085         if (controllers.find(req.name) != controllers.end())
00086         {
00087                 ROS_ERROR("The %s controller is already registered.", req.name.c_str());
00088                 resp.accepted = false;
00089                 return true;
00090         }
00091 
00092         //Check if other dependencies are satisfied
00093         for (int i=0; i<req.used_cnt.size(); ++i)
00094         {
00095                 if (controllers.find(req.used_cnt[i]) == controllers.end())
00096                 {
00097                         ROS_ERROR("The controller %s is missing dependency %s.",
00098                                         req.name.c_str(),
00099                                         req.used_cnt[i].c_str());
00100                         resp.unmet_cnt.push_back(req.used_cnt[i]);
00101                 }
00102         }
00103 
00104         if (resp.unmet_cnt.size())
00105         {
00106                 resp.accepted = false;
00107                 return true;
00108         }
00109 
00110         //Add the controller
00111         ROS_INFO("Adding controller %s.",req.name.c_str());
00112         resp.accepted = true;
00113         controllers[req.name].info = req;
00114         depGraph.addToGraph(req);
00115         //pnGraph.addToGraph(req);
00116         //pnCon.addToPNGraph(req);
00117 
00118         ros::Time now = ros::Time::now();
00119         pnCon.addToGraph(req);
00120         double addgraph_dT = (ros::Time::now() - now).toSec();
00121         now = ros::Time::now();
00122         pnCon.addToPNGraph(req);
00123         double addpngraph_dT = (ros::Time::now() - now).toSec();
00124         //pnCon.reachability();
00125         double classic_dT = (ros::Time::now() - now).toSec();
00126         now = ros::Time::now();
00127         //pnCon.addToRGraph2(req.name);
00128         pnCon.addToRGraph(req.name);
00129         double incremental_dT = (ros::Time::now() - now).toSec();
00130 
00131         //pnCon.addToRGraph();
00132         //addToMatrix(req.name);
00133         names.push_back(req.name);
00134 
00135         std_msgs::String out;
00136         std::fstream dep_file("dep_graph.dot",std::ios::out);
00137         std::fstream pn_file("pn_graph.dot",std::ios::out);
00138         std::fstream r_file("r_graph.dot",std::ios::out);
00139         std::string temp;
00140         depGraph.getDotDesc(temp);
00141         dep_file<<temp;
00142         out.data = temp;
00143         depGraphPub.publish(out);
00144         pnCon.getDotDesc2(temp);
00145         pn_file<<temp;
00146         out.data = temp;
00147         pnGraphPub.publish(out);
00148         pnCon.getDotDesc(temp);
00149         r_file<<temp;
00150 
00151         std::ofstream prof_file("profile.csv", std::ios::app);
00152         prof_file<<addgraph_dT<<","<<addpngraph_dT<<","<<classic_dT<<","<<incremental_dT<<std::endl;
00153 
00154         return true;
00155 }
00156 
00157 void ExecControl::addToMatrix(const std::string& name)
00158 {
00159         //Build from scratch
00160         using namespace boost;
00161         ControllerInfo& newcon = controllers[name];
00162         newcon.place_num = pnum++;
00163         pname[newcon.place_num] = name;
00164         marking.conservativeResize(pnum);
00165         marking(newcon.place_num) = 0;
00166         newcon.en_t_num = tnum++;
00167         newcon.dis_t_num = tnum++;
00168         std::cout<<"Resize matrix 2."<<std::endl;
00169         Dm.conservativeResize(pnum, tnum);
00170         Dp.conservativeResize(pnum, tnum);
00171         Dm.row(newcon.place_num) = Eigen::VectorXi::Zero(tnum);
00172         Dp.row(newcon.place_num) = Eigen::VectorXi::Zero(tnum);
00173         Dm.col(newcon.en_t_num)= Eigen::VectorXi::Zero(pnum);
00174         Dp.col(newcon.en_t_num)= Eigen::VectorXi::Zero(pnum);
00175         Dm.col(newcon.dis_t_num)= Eigen::VectorXi::Zero(pnum);
00176         Dp.col(newcon.dis_t_num)= Eigen::VectorXi::Zero(pnum);
00177 
00178         //Add local connection
00179         Dm(newcon.place_num, newcon.dis_t_num) = 1;
00180         Dp(newcon.place_num, newcon.en_t_num) = 1;
00181         //Add basic dependencies.
00182         for (int i=0; i<newcon.info.used_dofs.size(); ++i)
00183         {
00184                 if (newcon.info.used_dofs[i])
00185                 {
00186                         Dm(i, newcon.en_t_num) = 1;
00187                         Dp(i, newcon.dis_t_num) = 1;
00188                 }
00189         }
00190 
00191         //Add basic dependencies.
00192         for (int i=0; i<newcon.info.used_cnt.size(); ++i)
00193         {
00194                 const std::string& dep = newcon.info.used_cnt[i];
00195                 ControllerMap::iterator it = controllers.end();
00196                 if ((it = controllers.find(dep)) != controllers.end())
00197                 {
00198                         //ROS_INFO("Add edge %d -> %d.",it->second.graph_idx,newcon.graph_idx);
00199                         //boost::add_edge(newcon.graph_idx, it->second.graph_idx, graph);
00200                         Dm(it->second.place_num, newcon.en_t_num) = 1;
00201                         Dp(it->second.place_num, newcon.dis_t_num) = 1;
00202                 }
00203         }
00204 
00205         std::cout<<"Current marking:"<<marking<<std::endl;
00206         std::cout<<"Current Dm matrix:"<<Dm<<std::endl;
00207         std::cout<<"Current Dp matrix:"<<Dp<<std::endl;
00208         std::cout<<"Current I matrix:"<<Dp-Dm<<std::endl;
00209 
00210         reachability();
00211 }
00212 
00213 void ExecControl::onActivateController(const std_msgs::String::ConstPtr& name)
00214 {
00215         if (controllers.find(name->data) != controllers.end())
00216         {
00217                 //firing_seq.clear();
00218                 //this->get_firing2(name->data);
00219                 //pnCon.get_firing(name->data);
00220                 //pnCon.get_firing_r(name->data);
00221                 pnCon.get_firing_pn(name->data);
00222         }
00223         else
00224         {
00225                 //A testing example, we can try setting a PN place directly.
00226                 std::string dofs[]={"X","Y","Z","K","M","N"};
00227                 //Add DOFs to the name list
00228                 for (int i=X; i<=N;++i)
00229                 {
00230                         if (name->data == dofs[i])
00231                         {
00232                                 //pnCon.get_firing_r(name->data);
00233                                 pnCon.get_firing_pn(name->data);
00234                                 break;
00235                         }
00236                 }
00237         }
00238 }
00239 
00240 bool ExecControl::firing_rec2(int des_place, std::vector<int>& skip_transitions, std::vector<int>& visited_places)
00241 {
00242         visited_places.push_back(des_place);
00243 
00244         //Find all possible transition activators for this place
00245         Eigen::VectorXi transitions = Dp.row(des_place);
00246         std::vector<int> activators;
00247         for (int i=0; i<transitions.size(); ++i)
00248         {
00249                 if (transitions(i))
00250                 {
00251                         bool skipped = false;
00252                         //Filter skipped transitions
00253                         for (int j=0; j< skip_transitions.size(); ++j)
00254                         {
00255                                 if ((skipped = (skip_transitions[j] == i))) break;
00256                         }
00257 
00258                         if (!skipped) activators.push_back(i);
00259                 }
00260         }
00261 
00262         std::cout<<"Place "<<pname[des_place]<<" depends on transitions:";
00263         for (int i=0; i<activators.size(); ++i)
00264         {
00265                 std::cout<<activators[i]<<", ";
00266         }
00267         std::cout<<std::endl;
00268 
00269         //If no activators this is a dead-end.
00270         if (activators.empty())
00271         {
00272                 std::cout<<"Dead-end."<<std::endl;
00273                 return false;
00274         }
00275 
00276         //For each activator find places
00277         bool add_seq = false;
00278         for (int i=0; i<activators.size(); ++i)
00279         {
00280                 Eigen::VectorXi t_en = Dm.col(activators[i]);
00281                 std::vector<int> places;
00282                 for (int j=0; j<t_en.size(); ++j)
00283                 {
00284                         if (t_en(j))
00285                         {
00286 
00287                                 bool skipped = false;
00288                                 //Filter skipped transitions
00289                                 for (int k=0; k< visited_places.size(); ++k)
00290                                 {
00291                                         if ((skipped = (visited_places[k] == j))) break;
00292                                 }
00293 
00294                                 if (!skipped) places.push_back(j);
00295                         }
00296                 }
00297 
00298                 std::cout<<"Transition "<<activators[i]<<" depends on places:";
00299                 for (int j=0; j<places.size(); ++j)
00300                 {
00301                         std::cout<<pname[places[j]]<<", ";
00302                 }
00303                 std::cout<<std::endl;
00304 
00305                 bool add_cur_seq=true;
00306                 for (int j=0; j<places.size(); ++j)
00307                 {
00308                         //If place is active add
00309                         if (!marking(places[j]))
00310                         {
00311                                 if (!firing_rec2(places[j], skip_transitions, visited_places))
00312                                 {
00313                                         add_cur_seq = false;
00314                                         break;
00315                                 }
00316                         }
00317                 }
00318 
00319                 if (add_cur_seq && !places.empty())
00320                 {
00321                         bool add = true;
00322                         for (int j=0; j<firing_seq.size(); ++j)
00323                         {
00324                                 if (firing_seq[j] == activators[i])
00325                                 {
00326                                         add = false;
00327                                         break;
00328                                 }
00329                         }
00330                         if (add)
00331                         {
00332                                 std::cout<<"Adding to firing sequence:"<<activators[i]<<std::endl;
00333                                 firing_seq.push_back(activators[i]);
00334                                 add_seq = true;
00335                                 if (activators[i]%2 == 0)
00336                                 {
00337                                         skip_transitions.push_back(activators[i]+1);
00338                                 }
00339                                 else
00340                                 {
00341                                         skip_transitions.push_back(activators[i]-1);
00342                                 }
00343                         }
00344                 }
00345         }
00346         return add_seq;
00347 }
00348 
00349 bool ExecControl::firing_rec(int des_place, std::vector<int>& skip_transitions, std::vector<int>& visited_places){}
00350 
00351 void ExecControl::get_firing(const std::string& name)
00352 {}
00353 
00354 void ExecControl::get_firing2(const std::string& name)
00355 {
00356         std::vector<int> skip_transitions;
00357         std::vector<int> visited_places;
00358 
00359         //Desired place to activate
00360         int des_place = controllers[name].place_num;
00361         firing_rec2(des_place, skip_transitions, visited_places);
00362 
00363         std::cout<<"The firing sequence is:";
00364         for (int i=0; i<firing_seq.size(); ++i)
00365         {
00366                 std::cout<<firing_seq[i]<<" ,";
00367         }
00368         std::cout<<std::endl;
00369 
00370         //Do the firing
00371         //Add testing "simulation" of the firing before applying.
00372         //Add enable/disable service calls for these.
00373         for(int i=0; i<firing_seq.size(); ++i)
00374         {
00375                 Eigen::VectorXi fire = Eigen::VectorXi::Zero(Dm.cols());
00376                 fire(firing_seq[i]) = 1;
00377                 marking = marking + (Dp-Dm)*fire;
00378                 std::cout<<"Transition "<<firing_seq[i]<<" fired, new marking:"<<marking<<std::endl;
00379                 if (marking(des_place)) break;
00380         }
00381 }
00382 
00383 
00384 void ExecControl::reachability()
00385 {
00386         rgraph.clear();
00387         Eigen::VectorXi trans = marking.transpose()*Dm;
00388 
00389         std::cout<<"Transition matrix:"<<trans<<std::endl;
00390 
00391         int last_m = boost::add_vertex(rgraph);
00392         rgraph[last_m].marking = marking;
00393 
00394         Eigen::VectorXi fire = Eigen::VectorXi::Zero(trans.size());
00395         int tnum = -1;
00396         for (int i=0; i<trans.size(); ++i)
00397         {
00398                 if (trans(i)>0)
00399                 {
00400                         std::cout<<"Transition "<<i<<" can fire."<<std::endl;
00401                         fire(i) = 1;
00402                         tnum = i;
00403                         break;
00404                 }
00405         }
00406 
00407         //marking = marking + (Dp-Dm)*fire;
00408 
00409         int new_m = boost::add_vertex(rgraph);
00410         rgraph[new_m].marking = marking;
00411         REdgeProperty prop;
00412         prop.t = tnum;
00413         prop.weight = 1;
00414         //Enable edge
00415         boost::add_edge(last_m, new_m, prop, rgraph);
00416         prop.t+=1;
00417         //Disable edge added so we can skip it in next iteration.
00418         boost::add_edge(new_m, last_m, prop, rgraph);
00419 
00420 
00421         std::cout<<"Transition fired, new marking:"<<marking<<std::endl;
00422 }
00423 
00424 int main(int argc, char* argv[])
00425 {
00426         ros::init(argc,argv,"exec_control");
00427         labust::control::ExecControl exec;
00428         ros::spin();
00429         return 0;
00430 }


labust_execution
Author(s): Gyula Nagy
autogenerated on Fri Aug 28 2015 11:23:25