iCub-main
Loading...
Searching...
No Matches
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>
16
17using namespace std;
18using namespace yarp::os;
19using namespace yarp::sig;
20using namespace yarp::math;
21using namespace iCub::ctrl;
22
23namespace 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
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/**********************************************************************/
152map<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
std::map< size_t, std::set< size_t > > cluster(const std::vector< yarp::sig::Vector > &data, const yarp::os::Property &options) override
Cluster the provided data.
shared_ptr< Epsilon_neighbours_t > get_epsilon_neighbours(const size_t index, shared_ptr< Data_t > augData)
void append(const size_t index, shared_ptr< Epsilon_neighbours_t > en)
bool expand(const size_t index, const size_t id, shared_ptr< Data_t > augData)
void spread(const size_t index, shared_ptr< Epsilon_neighbours_t > seeds, const size_t id, shared_ptr< Data_t > augData)
shared_ptr< Node_t > create_node(const size_t index)
This file contains the definition of unique IDs for the body parts and the skin parts of the robot.
const vector< Vector > & points
Data_t(const vector< Vector > &points_, const double epsilon_, const size_t minpts_)
shared_ptr< Node_t > next