Sarafun Behavior Trees package  1
Behavior trees for the SARAFun project
 All Data Structures Namespaces Functions Variables Enumerations Enumerator
TreeFromKF.cpp
1 #include <tree_generator/TreeFromKF.hpp>
2 
3 using json = nlohmann::json;
4 namespace tree_generator {
5 
7  {
8  nh_ = ros::NodeHandle("~");
9  has_label_ = false;
10  }
11 
12  /*
13  Replace all hifens in a string with an underscore
14  */
15  void replaceWithUnderscore(std::string &label)
16  {
17  for (int i = 0; i < label.size(); i++)
18  {
19  if (label[i] == '-')
20  {
21  label[i] = '_';
22  }
23  }
24  }
25 
26  bool SubTreeFromKF::loadLabel(std::string label)
27  {
28  std::string filename;
29  has_label_ = false;
30 
31  replaceWithUnderscore(label);
32 
33  if (!nh_.getParam(ros::this_node::getName() + "/" + label + "/file", filename))
34  {
35  ROS_ERROR("Got label %s, which is not defined in the tree generator", label.c_str());
36  return false;
37  }
38 
39  std::string path = ros::package::getPath("tree_generator") + "/data/subtrees/" + filename;
40  file_.open(path);
41 
42  if (file_.good())
43  {
44  ROS_INFO("Successfully loaded the tree for label %s", label.c_str());
45  has_label_ = true;
46  return true;
47  }
48 
49  ROS_ERROR("The filename for the label %s defined in the parameter server does not exist in /data/subtrees!", label.c_str());
50  return false;
51  }
52 
53  json SubTreeFromKF::createSubTree(std::vector<int> &indices)
54  {
55  if (!has_label_)
56  {
57  throw std::logic_error("Called the createSubTree method without a loaded label");
58  }
59 
60  file_ >> subtree_;
61 
62  file_.close();
63 
64  if (!subtree_.count("nodes") || !subtree_.count("root")) {
65  throw std::logic_error(
66  std::string("The subtree file must declare the 'nodes' and root members "
67  "at the base level!"));
68  }
69 
70  for (auto i = subtree_["nodes"].begin(); i != subtree_["nodes"].end(); i++) {
71  subtree_["nodes"][i.key()] = modifyId((json) subtree_["nodes"][i.key()], indices);
72  }
73 
74  return subtree_;
75  }
76 
77  json SubTreeFromKF::modifyId(json node, std::vector<int> &indices)
78  {
79  if (!node.count("id") || !node.count("type"))
80  {
81  throw std::logic_error(std::string("modifyId called on a json object without the 'id' and 'type' members!"));
82  }
83 
84  std::string type = node["type"];
85  std::string id = node["id"];
86 
87  if(type == "Selector") {
88  indices[SEL]++;
89  node["id"] = id + std::to_string(indices[SEL]);
90  } else if (type == "SelectorStar") {
91  indices[SELSTAR]++;
92  node["id"] = id + std::to_string(indices[SELSTAR]);
93  } else if (type == "Sequence") {
94  indices[SEQ]++;
95  node["id"] = id + std::to_string(indices[SEQ]);
96  } else if (type == "SequenceStar") {
97  indices[SEQSTAR]++;
98  node["id"] = id + std::to_string(indices[SEQSTAR]);
99  } else if (type == "Action") {
100  indices[ACTION]++;
101  node["id"] = id + std::to_string(indices[ACTION]);
102  } else if (type == "Condition") {
103  indices[CONDITION]++;
104  node["id"] = id + std::to_string(indices[CONDITION]);
105  } else {
106  std::string error_message("Tried to modify id of an unknown node type: ");
107  error_message = error_message + type;
108  throw std::logic_error(error_message);
109  }
110 
111  return node;
112  }
113 
115  {
116  indices_.resize(6);
117  }
118 
119  json TreeFromKF::createTree(const std::vector<sarafun_msgs::KeyframeMsg> &keyframes_list)
120  {
121  json tree, root_sequence;
122  std::vector<std::string> children_id_list;
123  std::map<std::string, json> children;
124  std::vector<json> children_list;
125  std::string id;
126 
127  tree["root"] = "root_sequence"; // Assuming that the top-most node is always a sequence
128 
129  root_sequence["id"] = "root_sequence";
130  root_sequence["type"] = "SequenceStar";
131  root_sequence["name"] = "SequenceStar";
132 
133  for (int i = 0; i < keyframes_list.size(); i++) // cycle through the keyframes and initialize the pre-defined subtrees
134  {
135  subtree_parser_.loadLabel(keyframes_list[i].label); // TODO: I am assuming an ordered list. Will this always be the case?
136  json subtree = subtree_parser_.createSubTree(indices_);
137  id = subtree["root"];
138  children_id_list.push_back(id);
139  addChildren(subtree, children);
140  }
141 
142  root_sequence["children"] = children_id_list;
143  children["root_sequence"] = root_sequence;
144  tree["nodes"] = children;
145 
146  std::cout << tree << std::endl;
147 
148  return tree;
149  }
150 
151  void TreeFromKF::addChildren(const json &tree, std::map<std::string, json> &children_map)
152  {
153  for(auto i = tree["nodes"].begin(); i != tree["nodes"].end(); i++)
154  {
155  children_map[i.key()] = i.value();
156  }
157  return;
158  }
159 }
void replaceWithUnderscore(std::string &label)
Definition: TreeFromKF.cpp:15
SubTreeFromKF subtree_parser_
Definition: TreeFromKF.hpp:87
bool loadLabel(std::string label)
Definition: TreeFromKF.cpp:26
json createSubTree(std::vector< int > &indices)
Definition: TreeFromKF.cpp:53
json createTree(const std::vector< sarafun_msgs::KeyframeMsg > &keyframes_list)
Definition: TreeFromKF.cpp:119
json modifyId(json node, std::vector< int > &indices)
Definition: TreeFromKF.cpp:77
std::vector< int > indices_
Definition: TreeFromKF.hpp:84
void addChildren(const json &tree, std::map< std::string, json > &children_map)
Definition: TreeFromKF.cpp:151