Design
The driver node is written modular and extendable as shown in the following simplified UML class diagram:
The Node
manager class implements the rclcpp::Node
interface and contains a list of Converter
instances and an instance of the Driver
class. The Driver
class is responsible to set up a
thread via an IoContext
instance to receive data asynchronously. It also provides a Sender
interface to send sensor PDUs. The Driver
class will check received PDUs, deserialize them and
dispatch the resulting PDU structures to a list of Receiver
instances.
For receiving and sending UDP data the Driver
class uses an instance of the UdpSocket
class
which handles sending and receiving bytes over the wire. The UdpSocket
class is based on the
ASIO library and uses an udp::socket
instance.
On the sending side, the Driver
class implements a Sender
interface, which allows any user of
that interface to send PDUs to the sensor. The Driver
will serialize PDU input structures and send
the byte stream via the UdpSocket
instance. The Node
class forwards the Sender
interface and
a weak reference to its rclcpp::Node
interface to all of its Converter
instances.
Each Converter
implements the
Receiver
interface, such that the
Node
class can register each Converter
as Receiver
in the Driver
instance.
In conclusion, the list of Converter
instances passed to the Node
can receive PDUs through the
Receiver
interface, called by the receiving thread in the IoContext
and can send PDUs through
the Sender
interface to the Driver
in the main thread.
Thus, the list of Converter
instances is a plugin list, which can be extended by subsequent
packages.
The implemented DefaultConstructor
maps the received PDU structures into ROS messages through
publishers and on the other hand fills PDU structures from a ROS message subscription / service and
sends them via the Sender
to the sensor. Furthermore, it implements diagnosis for all subscribed
and published topics if they are expected to transmit data cyclically.