<> <> == Overview == micros_swarm_framework is a programming framework to facilitate application development involving robot swarms. It makes coding for swarms much easier by providing an adequate swarm-level abstraction, as well as tools for swarm management, various communication mechanisms and so on. Enlightened by the Buzz programming language for robot swarms, micros_swarm_framework also provides essential data structures, such as Neighbor, Swarm, and Virtual Stigmergy, to the user. Most importantly, it is completely compatible with ROS Indigo and presented in the form of a C++ library, which means that all resources in the ROS ecosystem are still available to the user. It is currently compatible with ROS Indigo, and is also extensible to Opensplice DDS. == Compile == {{{ mkdir -p catkin_ws/src cd catkin_ws/src catkin_init_workspace git clone https://github.com/xuefengchang/micros_swarm_framework.git cd .. catkin_make -j1 source devel/setup.bash }}} == Architecture == In order to make it modular and extensible, we chose to decompose the framework into a layered structure, as shown in Fig. 1. The Communication Interface layer is to implement an abstraction of the underlying communication mechanisms, and provides a set of unified interface to layer above. At the core of the framework is a runtime platform, based on which APIs including abstract data structures, such as Swarm, Neighbor, and Virtual Stigmergy, are provided to the user. Upon this core part, we are also trying to build a library of typical swarm algorithms to further facilitate the application development. {{attachment:framework.png}} == Experiments == === experiment1: Motion and Spatial Coordination === {{attachment:app1.png}} === experiment2: Separation into Multiple Swarms === {{attachment:app2.png}} === experiment3: Flocking === {{attachment:app3.png}} == Instructions == === Swarm === ==== create a swarm ==== {{{ Swarm s = Swarm(1); //create a swarm s with id 1 }}} ==== get swarm id ==== {{{ Swarm s = Swarm(1); //create a swarm s with id 1 int id=s.id(); }}} ==== get swarm members ==== {{{ Swarm s = Swarm(1); //create a swarm s with id 1 std::set m=s.members(); }}} ==== join in a swarm unconditionally ==== {{{ s.join(); //join in the swarm s }}} ==== leave a swarm unconditionally ==== {{{ s.leave(); //leave the swarm s }}} ==== join in a swarm according to a certain condition ==== {{{ bool checkID(unsigned int id) { if(id%2==0) return true; return false; } /* *you might need to learn the bind and function in boost libarary. */ boost::function bf=boost::bind(&checkID, self_id); s.select(bf); //the robot whose id is even join in the swarm s }}} ==== leave a swarm according to a certain condition ==== {{{ bool checkID(unsigned int id) { if(id%2==0) return true; return false; } boost::function bf=boost::bind(&checkID, self_id); s.unselect(bf); //the robot whose id is even leave the swarm s }}} ==== execute a swarm task ==== {{{ void printID(unsigned int id) { std::cout<<"id="< f = boost::bind(&printID, self_id); s.execute(f); //the robot in the swarm s print the id of themselves }}} ==== execute a swarm task ==== {{{ void printID(unsigned int id) { std::cout<<"id="< f = boost::bind(&printID, self_id); s.execute(f); //the robot in the swarm s print the id of themselves }}} ==== swarm break up operation ==== {{{ Swarm s = Swarm(1); s.breakup(); //break up an existing swarm }}} ==== swarm intersection operation ==== {{{ Swarm a = Swarm(1); Swarm b = Swarm(2); Swarm c = a.intersection(b, 3); //intersect swarm a and swarm b, generating a new swarm c with id 3 }}} ==== swarm union operation ==== {{{ Swarm a = Swarm(1); Swarm b = Swarm(2); Swarm c = a.swarm_union(b, 3); //union swarm a and swarm b, generating a new swarm c with id 3 }}} ==== swarm difference operation ==== {{{ Swarm a = Swarm(1); Swarm b = Swarm(2); Swarm c = a.difference(b, 3); //swarm a difference with swarm b, generating a new swarm c with id 3 }}} ==== swarm negation operation ==== {{{ Swarm a = Swarm(1); Swarm b = a.negation(2); //negate swarm a, generating a new swarm b with id 2 }}} === Neighbors === ==== create a default neighbors structure ==== {{{ Neighbors n; //NeighborBase type }}} ==== create a user-defined data type neighbors structure ==== {{{ Neighbors n1; //int Neighbors n2; //float Neighbors n3; //string Neighbors n4; //user-defined type }}} ==== neighbors foreach function ==== foreach function perform a function that has no return value on each robot's data {{{ Neighbors n; void testforeach(int a) { std::cout<<"testforeach."< bf_testforeach=boost::bind(&TestForeach::testforeach, tf, _1); n.foreach(bf_testforeach); }}} ==== neighbors map function ==== map function perform a function that has a return value on each robot's data. generating a new Neighbors structure. Key is robot's id and value is the new data after transforming. {{{ Neighbors n; float testmap(int a) { return a+3.14; } Neighbors b = n.map(testmap); //If using class member functions class TestMap{ public: float testmap(int a) { return a+3.14; } } TestMap tm; boost::function bf_testmap=boost::bind(&TestMap::testmap, tm, _1); n.map(bf_testmap); }}} ==== neighbors reduce function ==== reduce function perform a function on the whole neighbors data structure and get a single return value. {{{ Neighbors n; float testreduce(int a, float& b) { b=b+a*2; return b; } float t2=0; t2 = n.reduce(testreduce, t2); //If using class member functions class TestReduce{ public: float testreduce(int a, float &b) { b=b+a*2; return b; } } TestReduce tr; boost::function bf_testreduce=boost::bind(&TestReduce::testreduce, tr, _1, _2); n.reduce(bf_testreduce); }}} ==== neighbors filter function ==== filter function perform the filtering operation according to user-defined judging method on each tuple. generating a new neighbors structure. {{{ Neighbors n; bool testfilter(int a, NeighborBase b) { if(b.getX()>=5) return true; return false; } Neighbors c = n.filter(testfilter); //If using class member functions class TestFilter{ public: bool testfilter(int a, NeighborBase b) { if(b.getX()>=5) return true; return false; } } TestFilter tf; boost::function bf_testfilter=boost::bind(&TestFilter::testfilter, tf, _1, _2); n.filter(bf_testfilter); }}} ==== neighbors kin function ==== neighborsFilter function is a special filter essentially. generating a new neighbors structure. every robot in the new neighbors structure is in a specified swarm. {{{ Neighbors n; Neighbors c=n.kin(1); //the memeber of the neighbors n which belong to the swarm with id 1 at the same time form a new neighbors c }}} ==== neighbors nonkin function ==== opposite of the kin {{{ Neighbors n; Neighbors c=n.nonkin(1); //the memeber of the neighbors n which don't belong to the swarm with id 1 form a new neighbors c }}} === VirtualStigmergy === ==== create a VirtualStigmergy ==== {{{ VirtualStigmergy v(1); //data type is float,id is 1 }}} ==== virtualStigmergyPut ==== {{{ v.put("test", 3.14); //put <"test", 3.14> into the VirtualStigmergy v }}} ==== virtualStigmergyGet ==== {{{ v.get("test"); //query the value with the key "test" of the VirtualStigmergy v }}} ==== get the size of a VirtualStigmergy ==== {{{ v.size(); }}} note: we could define VirtualStigmergy structure using the simple type, for example int, float, string. For the user-defined data-type, we need to use the Macro definition defined in the micros_swarm_framework to serialize in order to store and transport data of this type. We provided two Macro definition:BOOST_SERIALIZE, MEMBER: {{{ class TestVstigDataType{ private: int a_; float b_; std::string c_; BOOST_SERIALIZE { MEMBER a_; MEMBER b_; MEMBER c_; } public: TestVstigDataType(){} TestVstigDataType(int a, float b, std::string c) { a_=a; b_=b; c_=c; } void printTestVstigDataType() { std::cout<<"a_ = "<