bitrl & cuberl Documentation
Simulation engine for reinforcement learning agents
Loading...
Searching...
No Matches
rapidly_exploring_random_tree.h
Go to the documentation of this file.
1#ifndef RAPIDLY_EXPLORING_RANDOM_TREE_H
2#define RAPIDLY_EXPLORING_RANDOM_TREE_H
3
4#include "cubic_engine/base/cubic_engine_types.h"
5#include "kernel/data_structs/boost_serial_graph.h"
6#include "kernel/base/kernel_consts.h"
7
8#include"boost/noncopyable.hpp"
9#include <chrono>
10#include <iostream>
11
12
13namespace cengine {
14namespace search {
15
26template<typename NodeData, typename EdgeData>
27class RRT: private boost::noncopyable
28{
29public:
30
34 typedef NodeData vertex_data_t;
35
39 typedef EdgeData edge_data_t;
40
44 typedef typename kernel::BoostSerialGraph<vertex_data_t,
46
50 typedef typename kernel::BoostSerialGraph<vertex_data_t,
52
56 typedef typename kernel::BoostSerialGraph<vertex_data_t,
58
62 typedef typename kernel::BoostSerialGraph<vertex_data_t,
64
68 RRT();
69
73 vertex_t& get_vertex(uint_t v){ return tree_.get_vertex(v);}
74
78 const vertex_t& get_vertex(uint_t v)const{return tree_.get_vertex(v);}
79
84 vertex_t& get_vertex(adjacency_iterator itr){return tree_.get_vertex(itr);}
85
90 const vertex_t& get_vertex(adjacency_iterator itr)const{return tree_.get_vertex(itr);}
91
95 std::pair<adjacency_iterator, adjacency_iterator>
96 get_vertex_neighbors(uint_t id)const{
97 return tree_.get_vertex_neighbors(id);
98 }
99
103 std::pair<adjacency_iterator, adjacency_iterator>
105 return tree_.get_vertex_neighbors(v);
106 }
107
112 vertex_t& add_vertex(const vertex_t& node){ return tree_.add_vertex(node.data);}
113
117 vertex_t& add_vertex(const vertex_data_t& data);
118
124 edge_t& get_edge(uint_t v1, uint_t v2){
125 return tree_.get_edge(v1, v2);
126 }
127
133 const edge_t& get_edge(uint_t v1, uint_t v2)const{
134 return tree_.get_edge(v1, v2);
135 }
136
140 std::pair<edge_iterator, edge_iterator> edges()const{
141 return tree_.edges();
142 }
143
149 edge_t& add_edge(uint_t v1, uint_t v2){
150 return tree_.add_edge(v1, v2);
151 }
152
158 template<typename MetricTp>
159 const vertex_t& find_nearest_neighbor(const vertex_t& other,
160 const MetricTp& metric)const;
161
167 template<typename MetricTp>
168 const vertex_t& find_nearest_neighbor(const vertex_data_t& other,
169 const MetricTp& metric)const;
170
174 void clear(){tree_.clear();}
175
180 uint_t n_vertices()const{return tree_.n_vertices();}
181
186 uint_t n_edges()const{return tree_.n_edges();}
187
191 void set_show_iterations_flag(bool val){show_iterations_ = val;}
192
196 template<typename StateSelector,
197 typename MetricTp, typename DynamicsTp>
198 void build(uint_t nitrs, const vertex_t& xinit,
199 const StateSelector& state_selector,
200 const MetricTp& metric,
201 DynamicsTp& dynamics);
202
210 template<typename StateSelector, typename MetricTp, typename DynamicsTp>
211 std::tuple<bool, uint_t, uint_t>
212 build(uint_t nitrs, const vertex_t& xinit,
213 const vertex_t& goal, const StateSelector& state_selector,
214 const MetricTp& metric, DynamicsTp& dynamics, real_t goal_radius);
215
216private:
217
221 kernel::BoostSerialGraph<vertex_data_t, edge_data_t> tree_;
222
227 bool show_iterations_;
228
229};
230
231template<typename NodeData, typename EdgeData>
233 :
234 tree_(),
235 show_iterations_(false)
236{}
237
238template<typename NodeData, typename EdgeData>
241 return tree_.add_vertex(data);
242}
243
244template<typename NodeTp, typename EdgeTp>
245template<typename StateSelector, typename MetricTp, typename DynamicsTp>
246void
247RRT<NodeTp, EdgeTp>::build(uint_t nitrs, const vertex_t& xinit,
248 const StateSelector& state_selector,
249 const MetricTp& metric,
250 DynamicsTp& dynamics){
251
252 std::chrono::time_point<std::chrono::system_clock> start, end;
253 start = std::chrono::system_clock::now();
254
255 // just in case clear what the tree has
256 clear();
257
258 // initialize the tree. This is the root node
259 tree_.add_vertex(xinit.data);
260
261 // loop over the states and create
262 // the tree
263 for(uint_t itr=0; itr<nitrs; ++itr){
264
265 if(show_iterations_){
266 std::cout<<"At iteration: "<<itr<<std::endl;
267 }
268
269 // select a new random state
270 auto xrand = state_selector();
271
272 // find the nearest neighbor between this tree
273 // and the randomly selected state
274 auto& xnear = find_nearest_neighbor(xrand, metric);
275
276 // determine the new state. Move xnear
277 // towards xrand according to the prescribed dynamics
278 // also return the data required for the edge
279 // connecting xnew and xnear
280 auto [xnew, u] = dynamics(xnear, xrand);
281
282 // add a new vertex out of xnew
283 auto& new_v = add_vertex(xnew);
284
285 // add a new edge
286 auto new_e = add_edge(xnear.id, new_v.id);
287 new_e.set_data(u);
288 }
289
290 end = std::chrono::system_clock::now();
291
292 if(show_iterations_){
293 std::chrono::duration<real_t> dur = end - start;
294 std::cout<<"Total build time: "<<dur.count()<<std::endl;
295 }
296}
297
298template<typename NodeData, typename EdgeData>
299template<typename StateSelector, typename MetricTp, typename DynamicsTp>
300std::tuple<bool, uint_t, uint_t>
301RRT<NodeData, EdgeData>::build(uint_t nitrs, const vertex_t& xinit,
302 const vertex_t& goal, const StateSelector& state_selector,
303 const MetricTp& metric, DynamicsTp& dynamics, real_t goal_radius){
304
305
306 std::chrono::time_point<std::chrono::system_clock> start, end;
307 start = std::chrono::system_clock::now();
308
309 // just in case clear what the tree has
310 clear();
311
312 // start and goal are the same
313 // then there is nothing to do
314 if( metric(xinit, goal) < goal_radius ){
315 return std::make_tuple(true, 0, 0);
316 }
317
318 // initialize the tree. This is the root node
319 auto& root = tree_.add_vertex(xinit.data);
320
321 // flag indicating that the goal is found
322 bool goal_found = false;
323
324 // the uid of the last vertex
325 uint_t last_v_id = kernel::KernelConsts::invalid_size_type();
326
327 // loop over the states and create
328 // the tree
329 for(uint_t itr=0; (itr<nitrs && !goal_found); ++itr){
330
331 //if(show_iterations_){
332 // std::cout<<"At iteration: "<<itr<<std::endl;
333 //}
334
335 // select a new random state
336 auto xrand = state_selector();
337
338 // find the nearest neighbor between this tree
339 // and the randomly selected state
340 auto& xnear = find_nearest_neighbor(xrand, metric);
341
342 // determine the new state. Move xnear
343 // towards xrand according to the prescribed dynamics
344 // also return the data required for the edge
345 // connecting xnew and xnear
346 auto [xnew, u] = dynamics(xnear, xrand);
347
348 // add a new vertex out of xnew
349 auto& new_v = add_vertex(xnew);
350
351 // add a new edge
352 auto new_e = add_edge(xnear.id, new_v.id);
353 new_e.set_data(u);
354
355 // if this new node is the goal then
356 // exit the loop
357 if(metric(new_v, goal) < goal_radius ){
358 last_v_id = new_v.id;
359 goal_found = true;
360 break;
361 }
362 }
363
364 end = std::chrono::system_clock::now();
365
366 //if(show_iterations_){
367 std::chrono::duration<real_t> dur = end - start;
368 std::cout<<"Total build time: "<<dur.count()<<std::endl;
369 //}
370
371 return std::make_tuple(goal_found, root.id, last_v_id);
372}
373
374template<typename NodeData, typename EdgeData>
375template<typename MetricTp>
378 const MetricTp& metric)const{
379
380 auto dist = metric(tree_.get_vertex(0), other);
381 auto result = 0;
382
383 for(uint_t v=1; v< tree_.n_vertices(); ++v){
384 auto vertex_data = tree_.get_vertex(v);
385
386 auto new_dist = metric(vertex_data, other);
387
388 if(new_dist < dist){
389 dist = new_dist;
390 result = v;
391 }
392 }
393
394 return tree_.get_vertex(result);
395}
396
397template<typename NodeData, typename EdgeData>
398template<typename MetricTp>
401 const MetricTp& metric)const{
402
404 vertex_t dummy;
405 dummy.data = other;
406
407 auto dist = metric(tree_.get_vertex(0), dummy);
408 auto result = 0;
409
410 for(uint_t v=1; v< tree_.n_vertices(); ++v){
411 auto vertex_data = tree_.get_vertex(v);
412
413 auto new_dist = metric(vertex_data, dummy);
414
415 if(new_dist < dist){
416 dist = new_dist;
417 result = v;
418 }
419 }
420
421 return tree_.get_vertex(result);
422
423}
424
425
426
427}
428
429}
430
431#endif // RAPIDLY_EXPLORING_RANDOM_TREE_H
The RRT class models a Rapidly-Exploring Random Tree see: http://msl.cs.uiuc.edu/~lavalle/papers/Lav9...
Definition rapidly_exploring_random_tree.h:28
std::pair< adjacency_iterator, adjacency_iterator > get_vertex_neighbors(const vertex_t &v) const
Returns the neighboring vertices for the given vertex id.
Definition rapidly_exploring_random_tree.h:104
RRT()
RRT Default constructor. Creates an empty tree.
Definition rapidly_exploring_random_tree.h:232
const edge_t & get_edge(uint_t v1, uint_t v2) const
get_edge Returns the edge between the vertices v1 and v2
Definition rapidly_exploring_random_tree.h:133
vertex_t & add_vertex(const vertex_t &node)
add_vertex Add a new vertex to the tree
Definition rapidly_exploring_random_tree.h:112
const vertex_t & get_vertex(uint_t v) const
get_vertex Returns the v-th vertex
Definition rapidly_exploring_random_tree.h:78
edge_t & get_edge(uint_t v1, uint_t v2)
get_edge Returns the edge between the vertices v1 and v2
Definition rapidly_exploring_random_tree.h:124
kernel::BoostSerialGraph< vertex_data_t, edge_data_t >::edge_iterator edge_iterator
edge_iterator Edge iterator
Definition rapidly_exploring_random_tree.h:57
EdgeData edge_data_t
edge_data_t The type of the edge data
Definition rapidly_exploring_random_tree.h:39
kernel::BoostSerialGraph< vertex_data_t, edge_data_t >::edge_t edge_t
edge_t The edge type
Definition rapidly_exploring_random_tree.h:51
NodeData vertex_data_t
vertex_data_t The type of node data
Definition rapidly_exploring_random_tree.h:34
edge_t & add_edge(uint_t v1, uint_t v2)
add_edge Add a new edge between the vertices v1 and v2
Definition rapidly_exploring_random_tree.h:149
uint_t n_vertices() const
n_vertices. Returns the number of vertices of the tree
Definition rapidly_exploring_random_tree.h:180
uint_t n_edges() const
n_edges. Returns the number of edges of the tree
Definition rapidly_exploring_random_tree.h:186
void set_show_iterations_flag(bool val)
set_show_iterations_flag Set the show_iterations_ flag
Definition rapidly_exploring_random_tree.h:191
std::pair< edge_iterator, edge_iterator > edges() const
edges Access the edges of the tree
Definition rapidly_exploring_random_tree.h:140
void clear()
clear Clear the underlying tree
Definition rapidly_exploring_random_tree.h:174
vertex_t & get_vertex(uint_t v)
get_vertex Returns the v-th vertex
Definition rapidly_exploring_random_tree.h:73
const vertex_t & find_nearest_neighbor(const vertex_t &other, const MetricTp &metric) const
find_nearest_neighbor find the nearest neighbor of other node in this tree
Definition rapidly_exploring_random_tree.h:377
vertex_t & get_vertex(adjacency_iterator itr)
Access the vertex given the vertex descriptor This is needed when accessing the vertices using the ad...
Definition rapidly_exploring_random_tree.h:84
kernel::BoostSerialGraph< vertex_data_t, edge_data_t >::adjacency_iterator adjacency_iterator
adjacency_iterator Adjacency iterator
Definition rapidly_exploring_random_tree.h:63
std::pair< adjacency_iterator, adjacency_iterator > get_vertex_neighbors(uint_t id) const
Returns the neighboring vertices for the given vertex id.
Definition rapidly_exploring_random_tree.h:96
kernel::BoostSerialGraph< vertex_data_t, edge_data_t >::vertex_t vertex_t
vertex_t the vertex type
Definition rapidly_exploring_random_tree.h:45
const vertex_t & get_vertex(adjacency_iterator itr) const
Access the vertex given the vertex descriptor This is needed when accessing the vertices using the ad...
Definition rapidly_exploring_random_tree.h:90
void build(uint_t nitrs, const vertex_t &xinit, const StateSelector &state_selector, const MetricTp &metric, DynamicsTp &dynamics)
Build the tree.
Definition rapidly_exploring_random_tree.h:247
Definition rapidly_exploring_random_tree.h:13