Skip to content

Commit 0f4a797

Browse files
committed
Graph terminal
Signed-off-by: Francisco Martin Rico <[email protected]>
1 parent fd7c2cb commit 0f4a797

File tree

2 files changed

+332
-0
lines changed

2 files changed

+332
-0
lines changed

bica_graph/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ add_executable(test_subscriber_node test/test_subscriber_node.cpp)
7575
add_dependencies(test_subscriber_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
7676
target_link_libraries(test_subscriber_node ${catkin_LIBRARIES} ${PROJECT_NAME} )
7777

78+
add_executable(graph_terminal src/graph_terminal.cpp)
79+
add_dependencies(graph_terminal ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
80+
target_link_libraries(graph_terminal ${catkin_LIBRARIES} ${PROJECT_NAME} )
81+
7882

7983
install(DIRECTORY include/${PROJECT_NAME}/
8084
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}

bica_graph/src/graph_terminal.cpp

Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
/*********************************************************************
2+
* Software License Agreement (BSD License)
3+
*
4+
* Copyright (c) 2019, Intelligent Robotics Core S.L.
5+
* All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions
9+
* are met:
10+
*
11+
* * Redistributions of source code must retain the above copyright
12+
* notice, this list of conditions and the following disclaimer.
13+
* * Redistributions in binary form must reproduce the above
14+
* copyright notice, this list of conditions and the following
15+
* disclaimer in the documentation and/or other materials provided
16+
* with the distribution.
17+
* * Neither the name of Intelligent Robotics Core nor the names of its
18+
* contributors may be used to endorse or promote products derived
19+
* from this software without specific prior written permission.
20+
*
21+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32+
* POSSIBILITY OF SUCH DAMAGE.
33+
**********************************************************************/
34+
35+
/* Author: Francisco Martín Rico - [email protected] */
36+
37+
#include "ros/ros.h"
38+
39+
#include <bica_graph/graph_client.h>
40+
41+
#include <vector>
42+
#include <list>
43+
44+
std::vector<std::string> tokenize(const std::string& text)
45+
{
46+
std::vector<std::string> ret;
47+
size_t start = 0, end = 0;
48+
49+
while (end != std::string::npos)
50+
{
51+
end = text.find(" ", start);
52+
ret.push_back(text.substr(start, (end == std::string::npos) ? std::string::npos : end - start));
53+
start = ((end > (std::string::npos - 1)) ? std::string::npos : end + 1);
54+
}
55+
return ret;
56+
}
57+
58+
59+
class GraphTerminal
60+
{
61+
public:
62+
GraphTerminal() : spinner_(4)
63+
{
64+
spinner_.start();
65+
}
66+
67+
void run_console()
68+
{
69+
std::string line;
70+
bool success = true;
71+
72+
std::cout<<"BICA Graph console. Type \"quit\" to finish"<<std::endl;
73+
std::cout<<"> ";
74+
while (std::getline(std::cin, line))
75+
{
76+
if (line == "quit")
77+
break;
78+
79+
process_command(line);
80+
std::cout<<"> ";
81+
}
82+
83+
std::cout<<"Finishing..."<<std::endl;
84+
ros::shutdown();
85+
}
86+
87+
void list_nodes(void)
88+
{
89+
const std::list<bica_graph::Node>&nodes = graph_.get_nodes();
90+
91+
std::cout << "total nodes: " << nodes.size() << std::endl;
92+
for (auto node : nodes)
93+
{
94+
std::cout << "\t[" << node.get_id() << "]\t(type: [" << node.get_type() << "])" << std::endl;
95+
}
96+
}
97+
98+
void list_edges(void)
99+
{
100+
const std::list<bica_graph::StringEdge>&string_edges = graph_.get_string_edges();
101+
const std::list<bica_graph::DoubleEdge>&double_edges = graph_.get_double_edges();
102+
const std::list<bica_graph::TFEdge>&tf_edges = graph_.get_tf_edges();
103+
104+
std::cout << "total string edges: " << string_edges.size() << std::endl;
105+
for (auto edge : string_edges)
106+
{
107+
std::cout << "\t(" << edge.get_source() << ") --[" << edge.get()
108+
<< "]--> (" << edge.get_target() << ")" << std::endl;
109+
}
110+
111+
std::cout << "total double edges: " << double_edges.size() << std::endl;
112+
for (auto edge : double_edges)
113+
{
114+
std::cout << "\t(" << edge.get_source() << ") --[" << edge.get()
115+
<< "]--> (" << edge.get_target() << ")" << std::endl;
116+
}
117+
118+
std::cout << "total tf edges: " << tf_edges.size() << std::endl;
119+
for (auto edge : tf_edges)
120+
{
121+
std::cout << "\t(" << edge.get_source() << ") --["
122+
<< edge.get().getOrigin().x() << " " << edge.get().getOrigin().y() << " "
123+
<< edge.get().getOrigin().z() << " " << edge.get().getRotation().x() << " "
124+
<< edge.get().getRotation().y() << " " << edge.get().getRotation().z() << " "
125+
<< edge.get().getRotation().w()
126+
<< "]--> (" << edge.get_target() << ")" << std::endl;
127+
}
128+
}
129+
130+
void process_list(const std::vector<std::string>& command)
131+
{
132+
if (command.size() == 1)
133+
{
134+
list_nodes();
135+
list_edges();
136+
}
137+
else if ((command.size() == 2) && (command[1] == "nodes"))
138+
{
139+
list_nodes();
140+
}
141+
else if ((command.size() == 2) && (command[1] == "edges"))
142+
{
143+
list_edges();
144+
} else
145+
std::cout<<"\tUsage: list [nodes|edges]"<<std::endl;
146+
}
147+
148+
void process_add(const std::vector<std::string>& command)
149+
{
150+
if (command.size() > 1)
151+
{
152+
if (command[1] == "node")
153+
{
154+
if (command.size() != 4)
155+
std::cout<<"\tUsage: \n\t\tadd node id type"<<std::endl;
156+
else
157+
graph_.add_node(command[2], command[3]);
158+
}
159+
else if (command[1] == "edge")
160+
{
161+
162+
if ((command.size() == 2) ||
163+
((command.size() > 2) &&
164+
((command[2] != "string") && (command[2] != "double") && (command[2] != "tf"))))
165+
std::cout<<"\t\tadd edge [string|double|tf] source target data"<<std::endl;
166+
else if (command[2] == "string")
167+
{
168+
169+
if (command.size() >= 6)
170+
{
171+
std::string data = command[5];
172+
for (int i = 6; i < command.size(); i++) data = data + " " + command[i];
173+
graph_.add_edge(command[3], data, command[4]);
174+
}
175+
else
176+
std::cout<<"\t\tadd edge string source target data"<<std::endl;
177+
}
178+
else if (command[2] == "double")
179+
{
180+
if (command.size() == 6)
181+
{
182+
try
183+
{
184+
graph_.add_edge(command[3], std::stod(command[5]), command[4]);
185+
} catch (std::invalid_argument& e)
186+
{
187+
std::cout<<"Please, introduce a correct double number: "<<e.what()<<std::endl;
188+
std::cout<<"\t\tadd edge [string|double|tf] source target data"<<std::endl;
189+
}
190+
} else
191+
std::cout<<"\t\tadd edge double source target data"<<std::endl;
192+
} else if (command[2] == "tf")
193+
{
194+
if (command.size() != 11)
195+
std::cout<<"Please, introduce a correct coordinate in format x y z y p r: "
196+
<< std::endl;
197+
else
198+
{
199+
try
200+
{
201+
double x = std::stod(command[5]);
202+
double y = std::stod(command[6]);
203+
double z = std::stod(command[7]);
204+
double ry = std::stod(command[8]);
205+
double rp = std::stod(command[9]);
206+
double rr = std::stod(command[10]);
207+
tf2::Quaternion q;
208+
q.setRPY(rr, rp, ry);
209+
tf2::Transform trans(q, tf2::Vector3(x, y, z));
210+
graph_.add_edge(command[3], trans, command[4]);
211+
} catch (std::invalid_argument& e)
212+
{
213+
std::cout<<"Please, introduce a correct coordinate between quotation marks in format \"x y z y p r\": "<<e.what()<<std::endl;
214+
std::cout<<"\t\tadd edge [string|double|tf] source target data"<<std::endl;
215+
} catch (bica_graph::exceptions::NodeNotFound& e)
216+
{
217+
std::cout<<"\tNode not found: " << e.what() << std::endl;
218+
}
219+
} // if ((command[5].a ...
220+
} else {
221+
std::cout<<"\tUsage: \n\t\tadd edge [string|double|tf]..."<<std::endl;
222+
} // else if (command[2] == "tf") ...
223+
} else
224+
{
225+
std::cout<<"\tUsage: \n\t\tadd [node|edge]..."<<std::endl;
226+
}
227+
}
228+
}
229+
230+
231+
void process_remove(const std::vector<std::string>& command)
232+
{
233+
if (command.size() > 1)
234+
{
235+
if (command[1] == "node")
236+
{
237+
if (command.size() != 3)
238+
std::cout<<"\tUsage: \n\t\tremove node id"<<std::endl;
239+
else
240+
{
241+
try
242+
{
243+
graph_.remove_node(command[2]);
244+
} catch(bica_graph::exceptions::NodeNotFound& e)
245+
{
246+
std::cout<<"\tNode not found: " << e.what() << std::endl;
247+
}
248+
}
249+
} else if (command[1] == "edge")
250+
{
251+
if ((command.size() == 2) ||
252+
((command.size() > 2) &&
253+
((command[2] != "string") && (command[2] != "double") && (command[2] != "tf"))))
254+
std::cout<<"\t\tremove edge [string|double|tf] source target [data]"<<std::endl;
255+
else if (command[2] == "string")
256+
{
257+
if (command.size() >= 6)
258+
{
259+
std::string data = command[5];
260+
for (int i = 6; i < command.size(); i++) data = data + " " + command[i];
261+
graph_.remove_edge(command[3], data, command[4]);
262+
}else
263+
std::cout<<"\t\tremove edge string source target data"<<std::endl;
264+
} else if (command[2] == "double")
265+
{
266+
if (command.size() == 5)
267+
graph_.remove_double_edge(command[3], command[4]);
268+
else
269+
std::cout<<"\t\tremove edge double source target"<<std::endl;
270+
}
271+
else if (command[2] == "tf")
272+
{
273+
if (command.size() == 5)
274+
graph_.remove_tf_edge(command[3], command[4]);
275+
else
276+
std::cout<<"\t\tremove edge tf source target"<<std::endl;
277+
} else
278+
{
279+
std::cout<<"\t\tremove edge [string|double|tf] source target [data]"<<std::endl;
280+
}
281+
} else
282+
{
283+
std::cout<<"\tUsage: \n\t\tremove [node|edge]..."<<std::endl;
284+
}
285+
}else
286+
{
287+
std::cout<<"\tUsage: \n\t\tremove [node|edge]..."<<std::endl;
288+
}
289+
}
290+
291+
void process_command(const std::string& command)
292+
{
293+
std::vector<std::string> tokens = tokenize(command);
294+
295+
if (tokens.empty())
296+
return;
297+
298+
if (tokens[0] == "list")
299+
process_list(tokens);
300+
else if (tokens[0] == "add")
301+
process_add(tokens);
302+
else if (tokens[0] == "remove")
303+
process_remove(tokens);
304+
else
305+
std::cout << "Command not found" << std::endl;
306+
}
307+
308+
~GraphTerminal()
309+
{
310+
spinner_.stop();
311+
}
312+
private:
313+
ros::AsyncSpinner spinner_;
314+
bica_graph::GraphClient graph_;
315+
};
316+
317+
int main(int argc, char* argv[])
318+
{
319+
ros::init(argc, argv, "graph_terminal");
320+
ros::NodeHandle nh;
321+
322+
GraphTerminal terminal;
323+
terminal.run_console();
324+
325+
ros::waitForShutdown();
326+
327+
return 0;
328+
}

0 commit comments

Comments
 (0)