iCub-main
clustering.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT)
3  * Copyright (C) 2006-2010 RobotCub Consortium
4  * All rights reserved.
5  *
6  * This software may be modified and distributed under the terms
7  * of the BSD-3-Clause license. See the accompanying LICENSE file for
8  * details.
9 */
10 
11 #include <memory>
12 #include <vector>
13 #include <cmath>
14 #include <yarp/math/Math.h>
15 #include <iCub/ctrl/clustering.h>
16 
17 using namespace std;
18 using namespace yarp::os;
19 using namespace yarp::sig;
20 using namespace yarp::math;
21 using namespace iCub::ctrl;
22 
23 namespace iCub {
24  namespace ctrl {
25  namespace dbscan {
26  enum class PointType {
27  unclassified=-1,
28  noise=-2
29  };
30 
31  struct Data_t {
32  const vector<Vector> &points;
33  const double epsilon;
34  const size_t minpts;
35  vector<int> ids;
36  Data_t(const vector<Vector> &points_,
37  const double epsilon_,
38  const size_t minpts_) :
39  points(points_), epsilon(epsilon_), minpts(minpts_) {
40  ids.assign(points.size(),(int)PointType::unclassified);
41  }
42  };
43 
44  struct Node_t {
45  size_t index;
46  shared_ptr<Node_t> next;
47  };
48 
50  size_t num_members;
51  shared_ptr<Node_t> head;
52  weak_ptr<Node_t> tail;
53  };
54 
55  /**********************************************************************/
56  shared_ptr<Node_t> create_node(const size_t index)
57  {
58  shared_ptr<Node_t> node(new Node_t());
59  node->index=index;
60  node->next=nullptr;
61  return node;
62  }
63 
64  /**********************************************************************/
65  void append(const size_t index, shared_ptr<Epsilon_neighbours_t> en)
66  {
67  shared_ptr<Node_t> node=create_node(index);
68  if (en->head==nullptr)
69  {
70  en->head=node;
71  en->tail=node;
72  }
73  else
74  {
75  en->tail.lock()->next=node;
76  en->tail=node;
77  }
78  en->num_members++;
79  }
80 
81  /**********************************************************************/
82  shared_ptr<Epsilon_neighbours_t> get_epsilon_neighbours(const size_t index,
83  shared_ptr<Data_t> augData)
84  {
85  shared_ptr<Epsilon_neighbours_t> en(new Epsilon_neighbours_t());
86  for (size_t i=0; i<augData->points.size(); i++)
87  {
88  double d=0.0;
89  for (size_t j=0; j<augData->points[index].length(); j++)
90  {
91  d+=pow(augData->points[index][j]-augData->points[i][j],2.0);
92  }
93  if ((i!=index) && (sqrt(d)<=augData->epsilon))
94  {
95  append(i,en);
96  }
97  }
98  return en;
99  }
100 
101  /**********************************************************************/
102  void spread(const size_t index, shared_ptr<Epsilon_neighbours_t> seeds,
103  const size_t id, shared_ptr<Data_t> augData)
104  {
105  shared_ptr<Epsilon_neighbours_t> spread=get_epsilon_neighbours(index,augData);
106  if (spread->num_members>=augData->minpts)
107  {
108  for (shared_ptr<Node_t> node=spread->head; node!=nullptr; node=node->next)
109  {
110  if ((augData->ids[node->index]==(int)PointType::noise) ||
111  (augData->ids[node->index]==(int)PointType::unclassified))
112  {
113  if (augData->ids[node->index]==(int)PointType::unclassified)
114  {
115  append(node->index,seeds);
116  }
117  augData->ids[node->index]=(int)id;
118  }
119  }
120  }
121  }
122 
123  /**********************************************************************/
124  bool expand(const size_t index, const size_t id, shared_ptr<Data_t> augData)
125  {
126  shared_ptr<Epsilon_neighbours_t> seeds=get_epsilon_neighbours(index,augData);
127  if (seeds->num_members<augData->minpts)
128  {
129  augData->ids[index]=(int)PointType::noise;
130  return false;
131  }
132  else
133  {
134  augData->ids[index]=(int)id;
135  for (shared_ptr<Node_t> h=seeds->head; h!=nullptr; h=h->next)
136  {
137  augData->ids[h->index]=(int)id;
138  }
139  for (shared_ptr<Node_t> h=seeds->head; h!=nullptr; h=h->next)
140  {
141  spread(h->index,seeds,id,augData);
142  }
143  return true;
144  }
145  }
146  }
147  }
148 }
149 
150 
151 /**********************************************************************/
152 map<size_t,set<size_t>> DBSCAN::cluster(const vector<Vector> &data,
153  const Property &options)
154 {
155  double epsilon=options.check("epsilon",Value(1.0)).asFloat64();
156  size_t minpts=(size_t)options.check("minpts",Value(2)).asInt32();
157  shared_ptr<dbscan::Data_t> augData(new dbscan::Data_t(data,epsilon,minpts));
158 
159  size_t id=0;
160  for (size_t i=0; i<augData->points.size(); i++)
161  {
162  if (augData->ids[i]==(int)dbscan::PointType::unclassified)
163  {
164  if (dbscan::expand(i,id,augData))
165  {
166  id++;
167  }
168  }
169  }
170 
171  map<size_t,set<size_t>> clusters;
172  for (size_t i=0; i<augData->points.size(); i++)
173  {
174  if (augData->ids[i]!=(int)dbscan::PointType::noise)
175  {
176  clusters[augData->ids[i]].insert(i);
177  }
178  }
179  return clusters;
180 }
181 
@ data
shared_ptr< Epsilon_neighbours_t > get_epsilon_neighbours(const size_t index, shared_ptr< Data_t > augData)
Definition: clustering.cpp:82
shared_ptr< Node_t > create_node(const size_t index)
Definition: clustering.cpp:56
void append(const size_t index, shared_ptr< Epsilon_neighbours_t > en)
Definition: clustering.cpp:65
bool expand(const size_t index, const size_t id, shared_ptr< Data_t > augData)
Definition: clustering.cpp:124
void spread(const size_t index, shared_ptr< Epsilon_neighbours_t > seeds, const size_t id, shared_ptr< Data_t > augData)
Definition: clustering.cpp:102
This file contains the definition of unique IDs for the body parts and the skin parts of the robot.
const vector< Vector > & points
Definition: clustering.cpp:32
Data_t(const vector< Vector > &points_, const double epsilon_, const size_t minpts_)
Definition: clustering.cpp:36
shared_ptr< Node_t > next
Definition: clustering.cpp:46