Build a Node

1. PolySync Node

PolySync nodes publish and subscribe to message types on the PolySync bus.

When a node subscribes to a message type, it receives a copy of every instance of that message type published to the PolySync bus. The node can access the message buffer and queue, process, convert, or visualize the data contained in the message.

PolySync provides a scaffolding generator that makes it easy to roll out a functioning C++ software node that subscribes to the data the node needs.

2. Scaffolding a node

To generate a new node, open a new terminal and type:

$ polysync-generate node

This will create a project called MyNode, which can be built with:

$ mkdir ./MyNode/build 
$ cd MyNode/build
$ cmake .. && make
$ ./MyNode

By default MyNode subscribes to and prints PolySync diagnostic messages - DiagnosticTraceMessage.

2.1 Subscribing to specific messages

The PolySync Core data model ships with pre-defined message types to store common data types seen on an autonomous vehicle. For example the ps_objects_msg, or ps_lidar_points_msg.

These are high-level, hardware agnostic message types. Any PolySync node can populate and publish messages defined in the data model.

You can view all messages currently being published to the PolySync Core bus using the Echo C++ example.

2.1.1 Sensor data

Sensor data is published to the bus as messages by dynamic driver nodes, which communicate with supported sensors.

Each supported sensor page indicates the message types the dynamic driver publishes to the bus. For example the FLIR Blackfly GigE article indicates that the ps_image_data_msg is published by the driver.

2.2 Building the node

Use the -s <message-type> flag to subscribe to the list of messages.

$ polysync-generate node -s ps_objects_msg ps_lidar_points_msg ps_image_data_msg
$ mkdir ./MyNode/build 
$ cd MyNode/build
$ cmake .. && make
$ ./MyNode

The generated C++ node will have access to all objects, LiDAR points, and image data in the messageEvent function.

2.3 Command line options

Print the command line options with the help flag. You can specify the node name, output directory, and which messages to subscribe to with a few flags.

$ polysync-generate node -h
usage: polysync-generate node [-h] [-n NAME] [-o DIR]
                              [-s MESSAGE [MESSAGE ...]] [-l]

optional arguments:
  -h, --help            show this help message and exit
  -n NAME, --name NAME  name of the generated PolySync node
  -o DIR, --output DIR  path in which to place generated files
  -s MESSAGE [MESSAGE ...], --subscribe MESSAGE [MESSAGE ...]
                        messages to which to subscribe
  -l, --list            list valid PolySync messages

3. About the code

MyNode contains all of the necessary methods every PolySync C++ node should have. This is the working directory:

MyNode
├── include
│   └── MyNode.hpp
├── CMakeLists.txt
└── src
    ├── MyNode.cpp
    └── main.cpp

In main.cpp, you can see how PolySync nodes are initialized.

The connectPolySync( ) is a blocking operation, and places the node in the node state machine. If there is a valid license, the node leaves the AUTH state and enters the INIT state, calling the initStateEvent( ) in MyNode.cpp.

3.1 main.cpp

#include < iostream >

#include < GetOpt.hpp >
#include < PolySyncCore.hpp >
#include < PolySyncNode.hpp >
#include < PolySyncDataModel.hpp >

#include "MyNode.hpp"


using namespace std;


int main( int argc, char * argv[] )
{
    MyNode node;

    node.setNodeName( MyNode::NODE_NAME );

    node.setCommandLineOptions( { argc, argv } );

    node.connectPolySync();

    return 0;
}

3.2 MyNode.hpp

#ifndef MYNODE_HPP
#define MYNODE_HPP


class MyNode : public polysync::Node
{

public:
    virtual void messageEvent( std::shared_ptr< polysync::Message > message );


    virtual void initStateEvent();


    virtual void setConfigurationEvent( const GetOpt & commandLineArgs );


    void okStateEvent();


    virtual void fatalStateEvent();


    virtual void errorStateEvent();


    virtual void warnStateEvent();


    virtual void releaseStateEvent();


public:

    static constexpr auto NODE_NAME = "MyNode";


private:

    ps_msg_type _messageTypeDiagnosticTraceMsg;

};

#endif // MYNODE_HPP

3.3 MyNode.cpp

#include <iostream>

#include < GetOpt.hpp >
#include < PolySyncCore.hpp >
#include < PolySyncNode.hpp >
#include < PolySyncDataModel.hpp >

#include "MyNode.hpp"


using namespace std;


void MyNode::messageEvent( std::shared_ptr< polysync::Message > message )
{
    using namespace polysync::datamodel;

    if( auto diagnosticTraceMsg = getSubclass< DiagnosticTraceMessage >( message ) )
    {
        diagnosticTraceMsg->print();
    }
}


void MyNode::initStateEvent()
{
     try
     {
         _messageTypeDiagnosticTraceMsg = getMessageTypeByName( "ps_diagnostic_trace_msg" );
         registerListener( _messageTypeDiagnosticTraceMsg );
     }
     catch (polysync::DTCException e)
     {
         polySyncLogDebug( "ps_diagnostic_trace_msg - " + e.getDtcDescription() );
         activateFault( e.getDtc(), NODE_STATE_FATAL );
     }
}


void MyNode::setConfigurationEvent( const GetOpt & commandLineArgs )
{
    commandLineArgs.printAll();
}


void MyNode::okStateEvent()
{
    // called continuously while in OK state
}


void MyNode::fatalStateEvent()
{
    // called once upon entering FATAL state
}


void MyNode::errorStateEvent()
{
    // called continuously while in ERROR state
}


void MyNode::warnStateEvent()
{
    // called continuously while in WARN state
}


void MyNode::releaseStateEvent()
{
    // called at end of node life
}

4. Additional References

The node generator is a great tool to get you developing custom nodes in PolySync quickly. All nodes implement the C Node API or the C++ Node API where you can find the functions a node implements. Most examples implement the Node API as nodes are at the core of PolySync however a few examples provide additional references for Node use and construction.

node_template shows the basic “node template” that all PolySync nodes use. This is a reference for understanding PolySync nodes and the different node states.

publish_subscribe provides an overview of the publish and subscribe communication in PolySync which is the most common form of node to node communication in PolySync. This is a good example to reference for node to node communication. PublishSubscribe provides the same overview except in C++.

Finally, ParameterGetSet provides an overview of filtering for a specific node on the PolySync bus and setting a specific parameter ID. This is good reference for setting parameter IDs at runtime and publishing and subscribing to ps_parameters_msg.