Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <dot_bt.h>
00022 #include <control_node.h>
00023 #include <std_msgs/String.h>
00024 #include <cctype>
00025 #include <algorithm>
00026
00027 namespace BT
00028 {
00029 DotBt::DotBt(TreeNode* root, const std::string& topic, double ros_rate, bool left_right, bool multiple_parents) :
00030 root_(root),
00031 topic_(topic),
00032 loop_rate_(ros_rate),
00033 left_right_(left_right),
00034 multiple_parents_(multiple_parents)
00035 {
00036 dotbt_publisher_ = n_.advertise<std_msgs::String>(topic_, 1);
00037
00038 ROS_INFO_STREAM("Visualization: Start publishing the tree in topic: "
00039 << topic_ << " with rate: " << ros_rate << " Hz.");
00040 }
00041
00042 DotBt::~DotBt() {}
00043
00044 std::string DotBt::defineNodeDot(TreeNode* node, const std::string& alias)
00045 {
00046 std::string output = alias + " ";
00047
00048
00049 switch (node->DrawType())
00050 {
00051 case SELECTORSTAR:
00052 output += "[label=\"*\n?\" penwidth=\"2\" shape=\"box\"";
00053 break;
00054 case BT::SEQUENCESTAR:
00055 output += "[label=\"*\n-->\" penwidth=\"2\" shape=\"box\"";
00056 break;
00057 case BT::SELECTOR:
00058 output += "[label=\"?\" penwidth=\"2\" shape=\"box\"";
00059 break;
00060 case BT::SEQUENCE:
00061 output += "[label=\"-->\" penwidth=\"2\" shape=\"box\"";
00062 break;
00063 case BT::PARALLEL:
00064 output += "[label=\"-->\n-->\" penwidth=\"2\" shape=\"box\"";
00065 break;
00066 case BT::DECORATOR:
00067 output += "[label=\"D\" penwidth=\"2\" shape=\"diamond\"";
00068 break;
00069 case BT::ACTION:
00070 output += "[label=\"" + node->get_name() + "\" penwidth=\"2\" shape=\"box\" fillcolor=\"palegreen\" style=\"filled\"";
00071 break;
00072 case BT::CONDITION:
00073 output += "[label=\"" + node->get_name() + "\" penwidth=\"2\" shape=\"ellipse\" fillcolor=\"khaki1\" style=\"filled\"";
00074 break;
00075 default:
00076 break;
00077 }
00078
00079
00080 switch (node->get_color_status())
00081 {
00082 case BT::RUNNING:
00083 output += " color=\"black\" ];";
00084 break;
00085 case BT::SUCCESS:
00086 output += " color=\"green\" ];";
00087 break;
00088 case BT::FAILURE:
00089 output += " color=\"red\" ];";
00090 break;
00091 case BT::IDLE:
00092 output += " color=\"gray88\" ];";
00093 break;
00094 case BT::HALTED:
00095 output += " color=\"orange\" ];";
00096 break;
00097 default:
00098 output += " color=\"gray88\" ];";
00099 break;
00100 }
00101
00102 return output;
00103 }
00104
00105 void DotBt::produceDot(TreeNode* node, TreeNode* parent, const std::string& parent_alias)
00106 {
00107
00108 if (parent == NULL)
00109 {
00110 dot_file_ = "graph behavior_tree {\n";
00111 if (left_right_)
00112 {
00113 dot_file_ += "rankdir=LR;\n";
00114 }
00115
00116 if (!multiple_parents_)
00117 {
00118 aliases_.clear();
00119 }
00120 }
00121
00122
00123 std::string alias = getAlias(node->get_name());
00124
00125
00126
00127
00128
00129 if (std::find(aliases_.begin(), aliases_.end(), alias) != aliases_.end())
00130 {
00131 alias += std::to_string(multiple_alias_solver_++);
00132 }
00133 aliases_.push_back(alias);
00134
00135
00136
00137 dot_file_ += defineNodeDot(node, alias) + "\n";
00138
00139
00140 if (parent != NULL)
00141 {
00142 dot_file_ += parent_alias + " -- " + alias + ";\n";
00143 }
00144
00145
00146 BT::ControlNode* n = dynamic_cast<BT::ControlNode*> (node);
00147 if (n != NULL)
00148 {
00149 std::vector<TreeNode *> children = n->GetChildren();
00150 for (unsigned int i = 0; i < children.size(); i++)
00151 {
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 produceDot(children.at(i), node, alias);
00172 }
00173 }
00174
00175
00176 if (parent == NULL)
00177 {
00178 dot_file_ += "\n}";
00179 }
00180 }
00181
00182 std::string DotBt::getAlias(const std::string &name)
00183 {
00184
00185 std::string out = boost::to_lower_copy<std::string>(name);
00186
00187
00188
00189 if (std::isdigit(out.at(0)))
00190 {
00191 out.insert(0, "a");
00192 }
00193
00194
00195
00196 for (std::string::iterator it = out.begin(); it != out.end(); ++it)
00197 {
00198 if (*it == ' ' || *it == '-')
00199 {
00200 *it = '_';
00201 }
00202 }
00203 return out;
00204 }
00205
00206 std::string DotBt::getDotFile()
00207 {
00208 return dot_file_;
00209 }
00210
00211 void DotBt::publish()
00212 {
00213 std_msgs::String msg;
00214
00215
00216 while (ros::ok())
00217 {
00218 produceDot(root_);
00219 msg.data = dot_file_;
00220 dotbt_publisher_.publish(msg);
00221 ros::spinOnce();
00222 loop_rate_.sleep();
00223 }
00224 }
00225 }