![]() |
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.