Python Usage of External API

From ANVEL Wiki
Jump to: navigation, search


The ANVEL EXTERNAL API has been used and tested with Python 2.7. Compatibility with Python 3 is not guaranteed; review known issues before proceeding.

  1. Install a Python development and run-time environment on the host running the remote application.
    • Ubuntu 16.04 includes Python 2.7 by default. An IDE may be useful in addition.
    • Anaconda, Python(x,y), or similar distributions are suitable for Windows.
  2. Install the Thrift Python module according to the Python distribution's instructions. For most distributions, this can be accomplished using the pip package management system.
    • For Ubuntu 16.04, install pip first (sudo apt-get install python-pip) followed by the Thrift module (pip install thrift).
    • For Windows with pip, Thrift is installed in the command prompt with python -m pip install thrift.

    The version of Thrift supported by ANVEL is 0.10.0. Verify the installed version using the command pip show thrift.

  3. If the remote application will run on a different host than ANVEL, copy the client side code from the ANVEL installation to the remote host. The python/src folder under the standard External API directory contains the AnvelApi Python module that is needed to use the API.
    If the remote application and ANVEL will run on the same host using a loopback connection, no copying is necessary as the Python path can point to the ANVEL installation directly.
  4. Adjust the Python path so that the remote application code can locate the AnvelApi module. The module's location is either the standard python/src folder referenced above or the copy destination of the same on the remote host. There are several ways to adjust the path:
    • If using an IDE, add the folder to the IDE's module search path.
    • The PYTHONPATH environment variable can be set under Windows and Linux.
    • The remote application code can specify the path to the AnvelApi module directly through the sys module's sys.path variable. For example, under a typical Windows installation:
      import sys
      # for ANVEL 2.0, use the following line:
      sys.path.append('C:\Program Files\Quantum Signal, LLC\ANVEL 2\API\python\src') 
      #for ANVEL 2.5, choose the line for the ANVEL edition that applies:
      sys.path.append('C:\Program Files\Quantum Signal, LLC\ANVEL 2.5 Academic\API\python\src')
      sys.path.append('C:\Program Files\Quantum Signal, LLC\ANVEL 2.5 Commercial\API\python\src')
      sys.path.append('C:\Program Files\Quantum Signal, LLC\ANVEL 2.5 Government\API\python\src')

General Information

  • The mappings between Thrift and native Python data types are generally straightforward and intuitive. Thrift string objects are returned as unicode objects under Python 2. Standard Python str objects can be provided as input arguments.
  • The following code helps to import the IDL-defined structures and enumerations in to the current Python namespace.
    from AnvelApi.ttypes import *
Cone.png Known Issue

The provided client side Python code for the API does not perform strict type checking for structure objects in the current ANVEL release. Providing the incorrect structure type for input arguments appears to succeed (no exceptions are generated) but may produce undefined or incorrect results.
For example, using a Quaternion structure as the input to SetVehicleInput call (instead of a proper VehicleInputRecord) does not produce an exception.
It is the user's responsibility to ensure correct typing of input argument structures.

Connecting to ANVEL

Establishing a connection to the ANVEL server from a remote Python application requires creating Thrift transport and protocol objects for the AnvelControlService.Client constructor.

The following code is sufficient for creating an AnvelControlService client object and connecting to an ANVEL server at the specified IP address and port.

ANVEL must be running before attempting to connect. If ANVEL cannot be reached, ConnectToANVEL transmits TTransportException.

from thrift.transport import TSocket
from thrift.protocol import TBinaryProtocol
from AnvelApi import AnvelControlService
from socket import IPPROTO_TCP, TCP_NODELAY

def ConnectToANVEL(address='', port=9094):
    '''Return a connected ANVEL client object.'''
    trans = TSocket.TSocket(address, port)
    proto = TBinaryProtocol.TBinaryProtocol(trans)
    anv = AnvelControlService.Client(proto)
    trans.handle.setsockopt(IPPROTO_TCP, TCP_NODELAY, 1)
        # disable buffering for congestion control
    return anv

Setting TCP_NODELAY for the socket is necessary to disable congestion control buffering (Nagle's algorithm) for small packets. By default, Thrift sockets in Python include additional buffering which can dramatically increase latency between ANVEL and the Python application (including on loopback connections). Disabling congestion control forces the small API command packets to be transmitted to ANVEL immediately.

Example Scripts

  • Simulation Timer Control: Illustrates basic use of the functions for inspecting and advancing the simulation timer
  • Attached Lidar: Illustrates attaching a lidar to a vehicle and retrieving scan data
  • Vehicle Control: Illustrates driving control and pose retrieval for multiple vehicles
  • Attach View to Vehicle: Illustrates attaching the view to a vehicle using internal commands
  • Link View to Object: Illustrates creating an object and setting the world view camera to focus on
  • Weather: Illustrates adjusting precipitation options
  • Add DataSource To Chart: Illustrates how to programmatically add a DataSource to the ANVEL chart

Known Issues

By default, Python 3 will not implement a __hash__ method for custom types. This prevents custom structs like ObjectDescriptor from being added to sets and any service which attempts to do so will fail with "TypeError: unhashable type: ObjectDescriptor". Python 2 will assign the default object.__hash__ method to custom structs. To recreate this behavior, include the following line at the top of the file in scripts : setattr(ObjectDescriptor, "__hash__", object.__hash__)

See Also

API Type Mapping

Built-in Python

External API Reference

External API Directory

Introduction to the External API

Python Example Vehicle Control using External API