RAPP Platform Wiki
v0.6.0
RAPP Platform is a collection of ROS nodes and back-end processes that aim to deliver ready-to-use generic services to robots
|
Currently, we support and maintain RAPP-API(s) for the following programming languages:
Under the rapp-api repository you can find more information regarding implemented and tested Rapp-Platform API calls.
As the integration tests are written in Python and uses the Python-Rapp-APi it is a good practice to start on the python-rapp-api.
API users are able to select from 2 API implementations:
The first one allow API users to easily call RAPP PLatform Services through simple function calls. The second one is for advanced usage, delivered for expert developers. This is an object-oriented implementation. As we will later describe, the advanced API usage allow creation of Cloud Messages. Both Platform requests and responses are described by static objects.
Note: The High Level API actually wraps the Advanced API.
RappPlatformService
is the RAPP term for an established connection to the RAPP-Platform Services, over the www (World-Wide-Web). Each Platform Service has it's own unique Response and Request message.
The RappPlatformService
class is used to establish connections to the RAPP-Platform Web-Services, while CloudMsg
objects include:
Request
object. RAPP-Platform Service specific Request messageResponse
object. RAPP-Platform Service specific Response message```python from RappCloud import RappPlatformService
svcClient = RappPlatformService(persistent=True, timeout=30000) ```
By Default it connects to the localhost, assuming that the RAPP Platform has been setup on the local machine. The constructor of the RappPlatformService
class allow to specify the RAPP Platform parameters to connect to.
```python from RappCloud import RappPlatformService
svcClient = RappPlatformService(address='RAPP_PLATFORM_IPv4_ADDRESS', port='RAPP_PLATFORM_PORT_NUMBER', protocol='http') ```
RappPlatformService
object constructor allow to set:
The persistent
and timeout
properties of a RappPlatformService
object are public members and can be set using the dot (.) notation:
```py svcClient = RappPlatformService() svcClient.persistent = True svcClient.timeout = 30000 ```
CloudMsg
objects are feed to the RappPlatformService
object to specific RAPP-Platform Services. CloudMsg
classes can be imported from the CloudMsgs submodule of the RappCloud module:
```py from RappCloud.CloudMsgs import FaceDetection ```
The above line of code is used as an example of importing the FaceDetection
CloudMsg class.
A complete description on available CloudMsg classes as long as their Request and Response message classes is available here
CloudMsg objects hold a Request and a Response object:
```py from RappCloud.CloudMsgs import FaceDetection faceDetectMsg = FaceDetection()
reqObj = faceDetectMsg.req respObj = faceDetectMsg.resp ```
Request and Response objects of a CloudMsg can be serialized to a dictionary:
```py reqDict = faceDetectMsg.req.serialize() print reqDict
{fast: False, imageFilePath: ''}
respDict = faceDetectMsg.resp.serialize() print respDict
{faces: [], error: ''}
```
CloudMsg Request property values can be set through the req
property of the CloudMsg object. or as keyword arguments to the constructor of a CloudMsg:
```py from RappCloud.CloudMsgs import FaceDetection
msg = FaceDetection(imageFilepath='/tmp/face-sample.png') print msg.req.serialize()
{fast: False, imageFilepath: '/tmp/face-sample.png'}
msg.req.fast = True print msg.req.serialize()
{fast: True, imageFilepath: '/tmp/face-sample.png'}
```
RappPlatfomrService
objects have a .call()
method for calling RAPP-Platform Services:
```py class RappPlatformService: ...
def call(self, msg=None): ... return self.resp
... ```
The .call()
method returns the Response object.
```py svcClient= RappPlatformService() msg = FaceDetection() msg.req.fast = True msg.req.imageFilepath = '/tmp/face-sample.png'
response = svcClient.call(msg) print response.faces print response.error
```
CloudMsg objects are passed as argument to the .call()
method of the RappPlatformService
object:
```py svcClient= RappPlatformService() msg = FaceDetection(imageFilepath='/tmp/face-sample.png') response = svcClient.call(msg) ```
CloudMsg
objects can also be passed to the constructor of the RappPlatformService
class:
```py faceMsg = FaceDetection(imageFilepath='/tmp/face-sample.png') svcClient= RappPlatformService(msg=faceMsg, timeout=15000) response = svcClient.call() ```
Note: Calling several different RAPP-Platform Services is done by passing the service specific Cloud Message objects to the .call()
of the RappPlatformService
object.
The following example creates a FaceDetection
and a QrDetection
CloudMsg to call both the Face-Detection and Qr-Detection RAPP-Platform Services.
```py from RappCloud import RappPlatformService from RappCloud.CloudMsgs import ( FaceDetection, QrDetection)
svcClient = RappPlatformService(timeout=1000) faceMsg = FaceDetection(fast=True, imageFilepath='/tmp/face-sample.png') qrMsg = QrDetection() qrMsg.req.imageFilepath = '/tmp/qr-sample.png'
fdResp = svcClient.call(faceMsg) print "Found %s Faces" len(fdResp.faces)
qrResp = svcClient.call(qrMsg) print "Found %s QRs: %s" %(len(qrResp.qr_centers), qrResp.qr_messages)
```
Like previously mentioned, API users can also use the High Level implementation of the RAPP Platform API. Benefits from using this implementation is lack of knowledge of how Cloud Messages and RappPlatformService are used. Calls to the RAPP Platform are done through simple function calls, under the RappPlatformAPI module.
Below is an example of performing a query to the ontologyi, hosted on the RAPP Platform, using the High Level API implementation:
```python from RappCloud import RappPlatformAPI ch = RappPlatformAPI()
response = ch.ontologySubclasses("Oven")
print response
{'results': [u'http://knowrob.org/kb/knowrob.owl#MicrowaveOven', u'http://knowrob.org/kb/knowrob.owl#RegularOven', u'http://knowrob.org/kb/knowrob.owl#ToasterOven'], 'error': u''}
```
The RappPlatformAPI usage and calls are fully documented here, also with examples of usage.
Lets say we want to implement the FaceDetection
Cloud Message.
The face detection RAPP Platform Web Service has a Request and Response object
Web-Service Request
fast
(Boolean): If true, detection will take less time but it will be less accuratefile
(File): Image file.Web-Service Response
faces
(Array): An array of the detected faces coordinates (point2D), on the image frame.error
(String): Error message.Start by creating the python source file for the FaceDeteciton Cloud Message implementation. Head to the RappCloud/CloudMsgs directory of the RappCloud module and create a file named FaceDetection.py
Cloud Messages classes inherit from the CloudMsg
class and Request
and Response
classes inherit from CloudRequest
and CloudResponse
classes respectively. So first import those classes and write the structure of the FaceDetection
Cloud Message:
```python from Cloud import ( CloudMsg, CloudRequest, CloudResponse)
class FaceDetection(CloudMsg):
class Request(CloudRequest): def __init__(self, **kwargs): pass class Response(CloudResponse): def __init__(self, **kwargs): pass def __init__(self, **kwargs): pass
```
Add the appropriate properties to the Request and Response classes. Property names can differ from the Web-Service request and response property names. Mapping from implemented property names to actual request payload will be studied later on:
```python class Request(CloudRequest):
def __init__(self, **kwargs): ## File path to the image file self.imageFilepath = '' ## If true, detection will take less time but it will be less accurate self.fast = False ## Apply keyword arguments to the Request object. super(FaceDetection.Request, self).__init__(**kwargs)
class Response(CloudResponse):
def __init__(self, **kwargs): ## Error message self.error = '' ## Detected faces. Array of face objects. self.faces = [] ## Apply keyword arguments to the Request object. super(FaceDetection.Response, self).__init__(**kwargs)
```
Notice calling CloudResponse
and CloudRequest
construcors.
Remember that a Request
class must implement two member methods, make_payload()
and make_files
. For the payload it's the fast
property and imageFilepath is a file.
```python from RappCloud.Objects import ( Payload, File)
class Request(CloudRequest):
def __init__(self, **kwargs): ## File path to the image file self.imageFilepath = '' ## If true, detection will take less time but it will be less accurate self.fast = False ## Apply keyword arguments to the Request object. super(FaceDetection.Request, self).__init__(**kwargs) def make_payload(self): return Payload(fast=self.fast) def make_files(self): return [File(filepath=self.path, postfield="file")]
```
Next, you have to instantiate a Request
and Response
objects for the FaceDetection
class to hold:
```python class FaceDetection(CloudMsg): ...
def init(self, **kwargs):
self.req = FaceDetection.Request()
self.resp = FaceDetection.Response() ```
Each RAPP Platform Web Service has a unique service name resolving to a url name/path. The service name for the Face Detection RAPP Platform Web Service is:
```shell face_detection ```
CloudMsg
constructor takes as input the service name:
```python class FaceDetection(CloudMsg): ...
def init(self, **kwargs):
self.req = FaceDetection.Request()
self.resp = FaceDetection.Response() super(FaceDetection, self).__init__(svcname='face_detection', **kwargs) ```
Note: Dont forget to document the code using doxygen
Below is the complete FaceDetection.py file
```python from RappCloud.Objects import ( File, Payload)
from Cloud import ( CloudMsg, CloudRequest, CloudResponse)
class FaceDetection(CloudMsg): """ Face Detection CloudMsg object"""
class Request(CloudRequest): """ Face Detection Cloud Request object. FaceDetection.Request """ def init(self, **kwargs): """! Constructor
**kwargs | - Keyword arguments. Apply values to the request attributes.
|
self.imageFilepath = ''
self.fast = False
super(FaceDetection.Request, self).__init__(**kwargs)
def make_payload(self): """ Create and return the Payload of the Request. """ return Payload(fast=self.fast) def make_files(self): """ Create and return Array of File objects of the Request. """ return [File(self.imageFilepath, postfield='file')] class Response(CloudResponse): """ Face Detection Cloud Response object. FaceDetection.Response """ def __init__(self, **kwargs): """! Constructor @param **kwargs - Keyword arguments. Apply values to the request attributes. - @ref error - @ref faces """ ## Error message self.error = '' ## Detected faces. Array of face objects. TODO create face object. self.faces = [] ## Apply passed keyword arguments to the Request object. super(FaceDetection.Response, self).__init__(**kwargs) def __init__(self, **kwargs): """! Constructor @param **kwargs - Keyword arguments. Apply values to the request attributes. - @ref Request.fast - @ref Request.imageFilepath """ # Create and hold the Request object for this CloudMsg self.req = FaceDetection.Request() # Create and hold the Response object for this CloudMsg self.resp = FaceDetection.Response() super(FaceDetection, self).__init__(svcname='face_detection', **kwargs)
```
Finally append the following line of code in the RappCloud/CloudMsgs/__init__.py
file:
```python from FaceDetection import FaceDetection ```
Now everything is in place to call the newly created Face detection RAPP Platform Service, using the python implementation of the rapp-platform-api. An example is presented below:
```python from RappCloud.CloudMsgs import FaceDetection from RappCloud import RappPlatformService
svcClient = RappPlatformService(persistent=True, timeout=30000) msg = FaceDetection(imageFilepath="PATH", fast=True)
response svcClient.call(msg)
if response.error: print "An error has occured: %s" response.error else: print response.faces ```
If you want to also include it in the High Level API implementation, you will have to modify the RappPlatformApi.py file.
First import the FaceDetection
Cloud Message, that was previously implemented:
```py ...
from CloudMsgs import FaceDetection ```
Next, we must implemend the faceDetection
method for the RappPlatformAPI class. Input arguments to the method are:
The output is a python dict
of the response fields:
The faceDetection
method implementation must be as presented below
```py ...
class RappPlatformAPI(): """ RAPP Platform simple API implementation """ def init(self): self.svc_caller = RappPlatformService()
...
def faceDetection(self, imageFilepath, fast = False): """! Face detection API service call. imageFilepath: string
imageFilepath | Path to the image file. fast: bool |
fast | Perform fast detection. If true, detection will take less time but it will be less accurate. : dict |
Note: Make sure to launch both the back-end and the, listening for requests, HOP Web Server, of the RAPP Platform, before executing the above example. Here you can find instructions on how to launch the RAPP Platform.