This document covers how to communicate with the robot base, in both directions.
Connections with the robot base are covered by the Transport
class, Router
class and Session Manager
class. Once the connection is established, commands can be sent to the robot base and corresponding responses received.
To receive unsolicited messages from the robot base, the notification handler must be implemented.
A Transport
class is used to instantiate an object which identifies the robot base being connected to, by specifying a communications protocol, an IP address and a port number.
Kinova provides two pre-defined Transport
object types:
TCPTransport
- using TCP as a transport protocolUDPTransport
- using UDP as a transport protocol
TCPTransport
is used for high-level robot control, configuration, and any other purposes not requiring sending commands at high frequency.
UDPTransport
can only be used for low-level cyclic communication at 1kHz with the robot via the Kinova::Api::BaseCyclic
service.
Only TCP should be used as a transport protocol in Python with a MqttTransport
object.
The RouterClient
class is used to instantiate an object which sends the command to the robot base specified by the Transport
object. A RouterClient
object needs a Transport
object to work. The purpose of the router is to transmit to the robot base all commands sent through the services.
It will also manage all messages sent and received by that service. A router needs to be specified each time a new service is declared.
To handle cases where there is a connection problem with the robot base, a callback method needs to be provided.
errorCallback = lambda kException: print("_________ callback error _________ {}".format(kException))
MQTT_PORT = 1883
transport = MqttTransport()
router = RouterClient(transport, errorCallback)
transport.connect(DEVICE_IP, MQTT_PORT)
The SessionManager
object will manage the connection to the robot base. If no SessionManager
is declared on an active connection, the robot base will not answer commands. A SessionManager
requires a RouterClient
object. The SessionManager
will also manage the connection to ensure that it is still alive if sent commands take too long to execute.
errorCallback = lambda kException: print("_________ callback error _________ {}".format(kException))
MQTT_PORT = 1883
transport = MqttTransport()
router = RouterClient(transport, errorCallback)
transport.connect(DEVICE_IP, MQTT_PORT)
session_info = Session_pb2.CreateSessionInfo()
session_info.username = 'admin'
session_info.password = 'admin'
session_info.session_inactivity_timeout = 60000 # (milliseconds)
session_info.connection_inactivity_timeout = 2000 # (milliseconds)
session_manager = SessionManager(router)
session_manager.CreateSession(session_info)
The robot base provides notifications on different topics as requested by a client application that has a session open with the robot.
The robot base uses a Publish/Subscribe design pattern. Rather than polling periodically for updates, the client application subscribes to a list of topics. Whenever a change happens related to that topic, whether caused by the same client session or not, the publisher sends a notification to all subscribers.
# In this example, when a user is created `notification_callback` will be called because we register it as a
# handler for `ConfigurationChange` topic notifications.
def notification_callback(data):
print("********************************")
print("** Callback function called **")
print(json_format.MessageToJson(data))
print("********************************")
# Subscribe to ConfigurationChange notifications
notif_handle = base.OnNotificationConfigurationChangeTopic(notification_callback, Base_pb2.NotificationOptions())