Skip to content

Instantly share code, notes, and snippets.

@wjwwood
Last active November 3, 2016 03:25
Show Gist options
  • Save wjwwood/ded26c4213f5046fef6b3e92e0af5d7c to your computer and use it in GitHub Desktop.
Save wjwwood/ded26c4213f5046fef6b3e92e0af5d7c to your computer and use it in GitHub Desktop.
#include <string>
#include <vector>
struct NodeBaseIface {
virtual std::string get_name() = 0;
};
struct NodeBase : public NodeBaseIface {
explicit NodeBase(std::string name) : name_(name) {}
virtual std::string get_name() {return name_;}
private:
std::string name_;
};
struct NodePubSubIface {
virtual void create_publisher(std::string topic) = 0;
virtual void create_subscription(std::string topic) = 0;
};
struct NodePubSub : public NodePubSubIface {
explicit NodePubSub(NodeBase * node_base) : node_base_(node_base) {}
virtual void create_publisher(std::string topic) {
printf("in NodePubSub::create_publisher(%s) for node '%s'\n", topic.c_str(), node_base_->get_name().c_str());
}
virtual void create_subscription(std::string topic) {
printf("in NodePubSub::create_subscription(%s) for node '%s'\n", topic.c_str(), node_base_->get_name().c_str());
}
private:
NodeBase * node_base_;
};
struct NodeServiceIface {
virtual void create_client(std::string service) = 0;
virtual void create_service(std::string service) = 0;
};
struct NodeService : public NodeServiceIface {
explicit NodeService(NodeBase * node_base) : node_base_(node_base) {}
virtual void create_client(std::string service) {
printf("in NodeService::create_client(%s) for node '%s'\n", service.c_str(), node_base_->get_name().c_str());
}
virtual void create_service(std::string service) {
printf("in NodeService::create_service(%s) for node '%s'\n", service.c_str(), node_base_->get_name().c_str());
}
private:
NodeBase * node_base_;
};
//////////////////////////////////////////////////////////////////////////////////////
// Graph part of the Node interface.
//////////////////////////////////////////////////////////////////////////////////////
struct NodeGraphIface {
virtual void wait_for_graph_change() = 0;
};
struct NodeGraph : public NodeGraphIface {
explicit NodeGraph(NodeBase * node_base) : node_base_(node_base) {}
virtual void wait_for_graph_change() {
printf("in NodeGraph::wait_for_graph_change() for node '%s'\n", node_base_->get_name().c_str());
}
private:
NodeBase * node_base_;
};
//////////////////////////////////////////////////////////////////////////////////////
// Parameter part of the Node interface.
//////////////////////////////////////////////////////////////////////////////////////
struct NodeParamsIface {
virtual void get_parameter() = 0;
virtual void set_parameter() = 0;
};
struct NodeParams : public NodeParamsIface {
explicit NodeParams(
NodeBaseIface * node_base,
NodePubSubIface * node_pub_sub,
NodeServiceIface * node_service)
: node_base_(node_base), node_pub_sub_(node_pub_sub), node_service_(node_service)
{
printf("in NodeGraph::NodeGraph() for node '%s'\n", node_base_->get_name().c_str());
printf(" ");
node_service_->create_service(node_base_->get_name() + "/set_parameter");
printf(" ");
node_pub_sub_->create_publisher(node_base_->get_name() + "/parameter_events");
}
virtual void get_parameter() {
printf("in NodeGraph::get_parameter() for node '%s'\n", node_base_->get_name().c_str());
}
virtual void set_parameter() {
printf("in NodeGraph::set_parameter() for node '%s'\n", node_base_->get_name().c_str());
}
private:
NodeBaseIface * node_base_;
NodePubSubIface * node_pub_sub_;
NodeServiceIface * node_service_;
};
//////////////////////////////////////////////////////////////////////////////////////
// Action part of the Node interface.
//////////////////////////////////////////////////////////////////////////////////////
struct NodeActionIface {
virtual void create_action_server(std::string action) = 0;
virtual void create_action_client(std::string action) = 0;
};
struct NodeActions : public NodeActionIface {
explicit NodeActions(
NodeBaseIface * node_base,
NodePubSubIface * node_pub_sub,
NodeServiceIface * node_service)
: node_base_(node_base), node_pub_sub_(node_pub_sub), node_service_(node_service)
{
}
virtual void create_action_server(std::string action) {
printf("in NodeGraph::create_action_server(%s) for node '%s'\n", action.c_str(), node_base_->get_name().c_str());
};
virtual void create_action_client(std::string action) {
printf("in NodeGraph::create_action_client(%s) for node '%s'\n", action.c_str(), node_base_->get_name().c_str());
};
private:
NodeBaseIface * node_base_;
NodePubSubIface * node_pub_sub_;
NodeServiceIface * node_service_;
};
//////////////////////////////////////////////////////////////////////////////////////
// Experimental "composite" or "subset" interface.
//////////////////////////////////////////////////////////////////////////////////////
// struct NodeCommsIface : public NodeBaseIface, public NodePubSubIface, public NodeServiceIface {};
// struct NodeComms : public NodeCommsIface
struct NodeComms : public NodeBase, public NodePubSub, public NodeService
{
explicit NodeComms(std::string name) : NodeBase(name), NodePubSub(this), NodeService(this) {}
};
//////////////////////////////////////////////////////////////////////////////////////
// Basic Node class.
//////////////////////////////////////////////////////////////////////////////////////
struct Node
:
public NodeComms,
// public NodeBase,
// public NodePubSub,
// public NodeService,
public NodeGraph,
public NodeParams,
public NodeActions
{
explicit Node(std::string name)
:
NodeComms(name),
// NodeBase(name),
// NodePubSub(this),
// NodeService(this),
NodeGraph(this),
NodeParams(this, this, this),
NodeActions(this, this, this)
{}
};
//////////////////////////////////////////////////////////////////////////////////////
// Custom Node class which does not expose the normal PubSub interface.
//////////////////////////////////////////////////////////////////////////////////////
struct CustomNodeWithoutPubSub_NodePubSub_Wrapper
{
explicit CustomNodeWithoutPubSub_NodePubSub_Wrapper(NodeBase * node_base)
: custom_helper_node_pub_sub_(new NodePubSub(node_base))
{}
virtual ~CustomNodeWithoutPubSub_NodePubSub_Wrapper() {delete custom_helper_node_pub_sub_;}
protected:
CustomNodeWithoutPubSub_NodePubSub_Wrapper(const CustomNodeWithoutPubSub_NodePubSub_Wrapper &) = delete;
NodePubSub * custom_helper_node_pub_sub_;
};
struct CustomNodeWithoutPubSub
:
public NodeBase,
public CustomNodeWithoutPubSub_NodePubSub_Wrapper,
// public NodePubSub, // explicitly left out to remove functions from API
public NodeService,
public NodeGraph,
public NodeParams,
public NodeActions
{
explicit CustomNodeWithoutPubSub(std::string name)
:
NodeBase(name),
CustomNodeWithoutPubSub_NodePubSub_Wrapper(this),
NodeService(this),
NodeGraph(this),
NodeParams(this, custom_helper_node_pub_sub_, this),
NodeActions(this, custom_helper_node_pub_sub_, this)
{}
};
//////////////////////////////////////////////////////////////////////////////////////
// Test functions that take different forms of the interface.
//////////////////////////////////////////////////////////////////////////////////////
void func_takes_pubsub(NodePubSubIface * i) {
printf("in func_takes_pubsub()\n");
i->create_publisher("chatter");
i->create_subscription("chatter");
printf("\n");
}
void func_takes_services(NodeServiceIface * i) {
printf("in func_takes_services()\n");
i->create_service("add_two_ints");
i->create_client("add_two_ints");
printf("\n");
}
void func_takes_comms(NodeComms * i) {
printf("in func_takes_comms(NodeCommsIface *)\n");
i->create_publisher("chatter");
i->create_subscription("chatter");
i->create_service("add_two_ints");
i->create_client("add_two_ints");
printf("\n");
}
void func_takes_comms(NodePubSubIface * pub_sub, NodeServiceIface * service) {
printf("in func_takes_comms(NodePubSubIface *, NodeServiceIface *)\n");
pub_sub->create_publisher("chatter");
pub_sub->create_subscription("chatter");
service->create_service("add_two_ints");
service->create_client("add_two_ints");
printf("\n");
}
void func_takes_params(NodeParamsIface * i) {
printf("in func_takes_params()\n");
i->get_parameter();
i->set_parameter();
printf("\n");
}
void func_takes_actions(NodeActionIface * i) {
printf("in func_takes_actions()\n");
i->create_action_server("move_base/goal");
i->create_action_client("move_base/goal");
printf("\n");
}
//////////////////////////////////////////////////////////////////////////////////////
// Toy Executor that only needs part of the API.
//////////////////////////////////////////////////////////////////////////////////////
struct Executor
{
void add_node(NodeBaseIface * node) {nodes_.push_back(node);}
private:
std::vector<NodeBaseIface *> nodes_;
};
//////////////////////////////////////////////////////////////////////////////////////
// Demo main function.
//////////////////////////////////////////////////////////////////////////////////////
int main(int argc, char const *argv[])
{
Node * node = new Node("my_node");
func_takes_pubsub(node);
func_takes_services(node);
func_takes_comms(node);
func_takes_comms(node, node);
func_takes_params(node);
func_takes_actions(node);
CustomNodeWithoutPubSub * custom_node = new CustomNodeWithoutPubSub("my_custom_node");
// func_takes_pubsub(custom_node); // class has no pub sub in API
func_takes_services(custom_node); // class does have service API
// func_takes_comms(custom_node); // class does not inherit from NodeComms
// func_takes_comms(custom_node, custom_node); // class has no pub sub in API (first argument)
func_takes_params(custom_node); // still works for param API
func_takes_actions(custom_node); // also for actions
// Both can be added to the executor because it only needs the NodeBase API.
Executor exec;
exec.add_node(node);
exec.add_node(custom_node);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment