python / bluezero

Typically: "How do I... ", "How can I... " questions
Post Reply
Justus
Posts: 37
Joined: 24 Jan 2017, 07:37

python / bluezero

Post by Justus » 04 Jul 2018, 08:43

Hi,

I'm trying my hands on the BlueZero interface, using Python 3.7 x64 on Win10 and V-REP PRO 3.5.0 (rev4).

Starting with a very basic test: I can load remoteapi.dll just fine (using the remoteapi.dll in path: programming\remoteApiBindings\lib\lib\Windows\64Bit)

Code: Select all

from ctypes import *
libc=CDLL('remoteApi')
But b0.dll doesn't import (using b0.dll in the V-REP root folder):

Code: Select all

from ctypes import *
libc=CDLL('b0')
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "(my python path)\lib\ctypes\__init__.py", line 356, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] The specified module could not be found
Any suggestions on how to load b0.dll?

Regards,
Justus

coppelia
Site Admin
Posts: 6867
Joined: 14 Dec 2012, 00:25

Re: python / bluezero

Post by coppelia » 04 Jul 2018, 10:32

Hello Justus, this is still work-in-progress, but following works on Python 2.x with the latest B0 library (tested on Windows):

File b0.py:

Code: Select all

import platform
import struct
import sys
import os
import ctypes as ct

libb0 = None
prefix, suffix = 'lib', '.so'
if platform.system() in ('cli', 'Windows'):
    prefix, suffix = '', '.dll'
if platform.system() in ('Darwin', ):
    suffix = '.dylib'
for path in ('.', 'build', '../../build'):
    fullpath = os.path.join(os.path.dirname(__file__), path)
    if not os.path.isdir(fullpath): continue
    libb0_fullpath = os.path.join(fullpath, '%sb0%s' % (prefix, suffix))
    if os.path.exists(libb0_fullpath):
        libb0 = ct.CDLL(libb0_fullpath)
        break
if libb0 is None:
    raise RuntimeError('%sb0%s not found' % (prefix, suffix))

def _(n, ret, *args):
    # perform encoding/decoding for char* argument (use str to enable conversion)
    def _enc(v, t): return v.encode('ascii') if t == str else v
    def _dec(v, t): return v.decode('ascii') if t == str else v
    def _wrap(t): return ct.c_char_p if t == str else t
    # unwrapped CFUNCTYPE: (prefixed with _)
    globals()['_' + n] = ct.CFUNCTYPE(_wrap(ret), *[_wrap(arg) for arg in args])((n, libb0))
    # wrapped CFUNCTYPE: (performs string encoding/decoding)
    globals()[n] = lambda *args2: _dec(globals()['_' + n](*[_enc(arg, t) for t, arg in zip(args, args2)]), ret)

_("b0_buffer_new", ct.c_void_p, ct.c_size_t)
_("b0_buffer_delete", None, ct.c_void_p)
_("b0_node_new", ct.c_void_p, str)
_("b0_node_delete", None, ct.c_void_p)
_("b0_node_init", None, ct.c_void_p)
_("b0_node_shutdown", None, ct.c_void_p)
_("b0_node_shutdown_requested", ct.c_int, ct.c_void_p)
_("b0_node_spin_once", None, ct.c_void_p)
_("b0_node_spin", None, ct.c_void_p)
_("b0_node_cleanup", None, ct.c_void_p)
_("b0_node_get_name", str, ct.c_void_p)
_("b0_node_get_state", ct.c_int, ct.c_void_p)
_("b0_node_get_context", ct.c_void_p, ct.c_void_p)
_("b0_node_hardware_time_usec", ct.c_longlong, ct.c_void_p)
_("b0_node_time_usec", ct.c_longlong, ct.c_void_p)
_("b0_node_log", None, ct.c_void_p, ct.c_int, str)
_("b0_publisher_new_ex", ct.c_void_p, ct.c_void_p, str, ct.c_int, ct.c_int)
_("b0_publisher_new", ct.c_void_p, ct.c_void_p, str)
_("b0_publisher_delete", None, ct.c_void_p)
_("b0_publisher_init", None, ct.c_void_p)
_("b0_publisher_cleanup", None, ct.c_void_p)
_("b0_publisher_spin_once", None, ct.c_void_p)
_("b0_publisher_get_topic_name", str, ct.c_void_p)
_("b0_publisher_publish", None, ct.c_void_p, ct.c_void_p, ct.c_size_t)
_("b0_publisher_log", None, ct.c_void_p, ct.c_int, str)
_("b0_subscriber_new_ex", ct.c_void_p, ct.c_void_p, str, ct.c_void_p, ct.c_int, ct.c_int)
_("b0_subscriber_new", ct.c_void_p, ct.c_void_p, str, ct.c_void_p)
_("b0_subscriber_delete", None, ct.c_void_p)
_("b0_subscriber_init", None, ct.c_void_p)
_("b0_subscriber_cleanup", None, ct.c_void_p)
_("b0_subscriber_spin_once", None, ct.c_void_p)
_("b0_subscriber_get_topic_name", str, ct.c_void_p)
_("b0_subscriber_log", None, ct.c_void_p, ct.c_int, str)
_("b0_subscriber_poll", ct.c_int, ct.c_void_p, ct.c_long)
_("b0_subscriber_read", ct.c_void_p, ct.c_void_p, ct.POINTER(ct.c_size_t))
_("b0_service_client_new_ex", ct.c_void_p, ct.c_void_p, str, ct.c_int, ct.c_int)
_("b0_service_client_new", ct.c_void_p, ct.c_void_p, str)
_("b0_service_client_delete", None, ct.c_void_p)
_("b0_service_client_init", None, ct.c_void_p)
_("b0_service_client_cleanup", None, ct.c_void_p)
_("b0_service_client_spin_once", None, ct.c_void_p)
_("b0_service_client_get_service_name", str, ct.c_void_p)
_("b0_service_client_call", ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_size_t, ct.POINTER(ct.c_size_t))
_("b0_service_client_log", None, ct.c_void_p, ct.c_int, str)
_("b0_service_server_new_ex", ct.c_void_p, ct.c_void_p, str, ct.c_void_p, ct.c_int, ct.c_int)
_("b0_service_server_new", ct.c_void_p, ct.c_void_p, str, ct.c_void_p)
_("b0_service_server_delete", None, ct.c_void_p)
_("b0_service_server_init", None, ct.c_void_p)
_("b0_service_server_cleanup", None, ct.c_void_p)
_("b0_service_server_spin_once", None, ct.c_void_p)
_("b0_service_server_get_service_name", str, ct.c_void_p)
_("b0_service_server_log", None, ct.c_void_p, ct.c_int, str)

class Node:
    def __init__(self, name='node'):
        self._node = b0_node_new(name)

    def __del__(self):
        b0_node_delete(self._node)

    def init(self):
        b0_node_init(self._node)

    def shutdown(self):
        b0_node_shutdown(self._node)

    def shutdown_requested(self):
        return b0_node_shutdown_requested(self._node)

    def spin_once(self):
        b0_node_spin_once(self._node)

    def spin(self):
        b0_node_spin(self._node)

    def cleanup(self):
        b0_node_cleanup(self._node)

    def get_name(self):
        return b0_node_get_name(self._node)

    def get_state(self):
        return b0_node_get_state(self._node)

    def get_context(self):
        return b0_node_get_context(self._node)

    def hardware_time_usec(self):
        return b0_node_hardware_time_usec(self._node)

    def time_usec(self):
        return b0_node_time_usec(self._node)

    def log(self, level, message):
        b0_node_log(self._node, level, message)

class Publisher:
    def __init__(self, node, topic_name, managed=1, notify_graph=1):
        self._pub = b0_publisher_new_ex(node._node, topic_name, managed, notify_graph)

    def __del__(self):
        b0_publisher_delete(self._pub)

    def init(self):
        b0_publisher_init(self._pub)

    def cleanup(self):
        b0_publisher_cleanup(self._pub)

    def spin_once(self):
        b0_publisher_spin_once(self._pub)

    def get_topic_name(self):
        return b0_publisher_get_topic_name(self._pub)

    def publish(self, data):
        buf = ct.c_char_p(data)
        b0_publisher_publish(self._pub, buf, len(data))

    def log(self, level, message):
        b0_publisher_log(self._pub, level, message)

class Subscriber:
    def __init__(self, node, topic_name, callback, managed=1, notify_graph=1):
        def w(data, size):
            data_bytes = bytearray(ct.cast(data, ct.POINTER(ct.c_ubyte * size)).contents)
            return callback(data_bytes)
        self._cb = ct.CFUNCTYPE(None, ct.c_void_p, ct.c_size_t)(w)
        self._sub = b0_subscriber_new_ex(node._node, topic_name, self._cb, managed, notify_graph)

    def __del__(self):
        b0_subscriber_delete(self._sub)

    def init(self):
        b0_subscriber_init(self._sub)

    def cleanup(self):
        b0_subscriber_cleanup(self._sub)

    def spin_once(self):
        b0_subscriber_spin_once(self._sub)

    def get_topic_name(self):
        return b0_subscriber_get_topic_name(self._sub)

    def log(self, level, message):
        b0_subscriber_log(self._sub, level, message)

    def poll(self,timeout):
        return b0_subscriber_poll(self._sub,timeout)
        
    def read(self):
        outsz = ct.c_size_t()
        outbuf = b0_subscriber_read(self._sub, ct.byref(outsz))
        outarr = ct.cast(outbuf, ct.POINTER(ct.c_ubyte * outsz.value))
        rep_bytes = bytearray(outarr.contents)
        return rep_bytes
        
class ServiceClient:
    def __init__(self, node, topic_name, managed=1, notify_graph=1):
        self._cli = b0_service_client_new_ex(node._node, topic_name, managed, notify_graph)

    def __del__(self):
        b0_service_client_delete(self._cli)

    def init(self):
        b0_service_client_init(self._cli)

    def cleanup(self):
        b0_service_client_cleanup(self._cli)

    def spin_once(self):
        b0_service_client_spin_once(self._cli)

    def get_service_name(self):
        return b0_service_client_get_service_name(self._cli)

    def call(self, data):
        buf = ct.c_char_p(data)
        sz = len(data)
        outsz = ct.c_size_t()
        outbuf = b0_service_client_call(self._cli, buf, sz, ct.byref(outsz))
        outarr = ct.cast(outbuf, ct.POINTER(ct.c_ubyte * outsz.value))
        rep_bytes = bytearray(outarr.contents)
        return rep_bytes

    def log(self, level, message):
        b0_service_client_log(self._cli, level, message)

class ServiceServer:
    def __init__(self, node, topic_name, callback, managed=1, notify_graph=1):
        def w(data, size, outsize):
            req_bytes = bytearray(ct.cast(data, ct.POINTER(ct.c_ubyte * size)).contents)
            resp_bytes = callback(req_bytes)
            outsize[0] = len(resp_bytes)
            outdata = b0_buffer_new(outsize[0])
            outarr = ct.cast(outdata, ct.POINTER(ct.c_ubyte * outsize[0]))
            #for i, c in enumerate(resp_str): outarr.contents[i] = ord(c)
            ct.memmove(outarr, ct.c_char_p(resp_bytes), len(resp_bytes))
            return outdata
        self._cb = ct.CFUNCTYPE(ct.c_void_p, ct.c_void_p, ct.c_size_t, ct.POINTER(ct.c_size_t))(w)
        self._srv = b0_service_server_new_ex(node._node, topic_name, self._cb, managed, notify_graph)

    def __del__(self):
        b0_service_server_delete(self._srv)

    def init(self):
        b0_service_server_init(self._srv)

    def cleanup(self):
        b0_service_server_cleanup(self._srv)

    def spin_once(self):
        b0_service_server_spin_once(self._srv)

    def get_service_name(self):
        return b0_service_server_get_service_name(self._srv)

    def log(self, level, message):
        b0_service_server_log(self._srv, level, message)
In next release there will be a b0-based remote API, that uses above and following:

File b0RemoteApi.py:

Code: Select all

import b0
import msgpack
import random
import string
import time

class RemoteApiClient:
    def __init__(self,nodeName='b0RemoteApi_pythonClient',channelName='b0RemoteApi',inactivityToleranceInSec=60,setupSubscribersAsynchronously=False):
        self._channelName=channelName
        self._serviceCallTopic=channelName+'SerX'
        self._defaultPublisherTopic=channelName+'SubX'
        self._defaultSubscriberTopic=channelName+'PubX'
        self._nextDefaultSubscriberHandle=2
        self._nextDedicatedPublisherHandle=500
        self._nextDedicatedSubscriberHandle=1000
        self._node=b0.Node(nodeName)
        self._clientId=''.join(random.choice(string.ascii_uppercase+string.ascii_lowercase+string.digits) for _ in range(10))
        self._serviceClient=b0.ServiceClient(self._node,self._serviceCallTopic)
        self._defaultPublisher=b0.Publisher(self._node,self._defaultPublisherTopic)
        self._defaultSubscriber=b0.Subscriber(self._node,self._defaultSubscriberTopic,None) # we will poll the socket
        print('\n  Running B0 Remote API client with channel name ['+channelName+']')
        print('  make sure that: 1) the B0 resolver is running')
        print('                  2) V-REP is running the B0 Remote API server with the same channel name')
        print('  Initializing...\n')
        self._node.init()
        self._handleFunction('inactivityTolerance',[inactivityToleranceInSec],self._serviceCallTopic)
        print('\n  Connected!\n')
        self._allSubscribers={}
        self._allDedicatedPublishers={}
        self._setupSubscribersAsynchronously=setupSubscribersAsynchronously
  
    def __enter__(self):
        return self
    
    def __exit__(self,*err):
        self._pongReceived=False
        self._handleFunction('Ping',[0],self.simxDefaultSubscriber(self._pingCallback))
        while not self._pongReceived:
            self.simxSpinOnce();
        self._handleFunction('DisconnectClient',[self._clientId],self._serviceCallTopic)
        for key, value in self._allSubscribers.items():
            if value['handle']!=self._defaultSubscriber:
                value['handle'].cleanup()
        for key, value in self._allDedicatedPublishers.items():
            value.cleanup()
        self._node.cleanup()
        
    def _pingCallback(self,msg):
        self._pongReceived=True
        
    def _handleReceivedMessage(self,msg):
        msg=msgpack.unpackb(msg)
        msg[0]=msg[0].decode('ascii')
        if msg[0] in self._allSubscribers:
            cbMsg=msg[1]
            if len(cbMsg)==1:
                cbMsg.append(None)
            self._allSubscribers[msg[0]]['cb'](cbMsg)
            
    def _handleFunction(self,funcName,reqArgs,topic):
        if topic==self._serviceCallTopic:
            packedData=msgpack.packb([[funcName,self._clientId,topic,0],reqArgs])
            rep = msgpack.unpackb(self._serviceClient.call(packedData))
            if len(rep)==1:
                rep.append(None)
            return rep
        elif topic==self._defaultPublisherTopic:
            packedData=msgpack.packb([[funcName,self._clientId,topic,1],reqArgs])
            self._defaultPublisher.publish(packedData)
        elif topic in self._allSubscribers:
            if self._allSubscribers[topic]['handle']==self._defaultSubscriber:
                packedData=msgpack.packb([[funcName,self._clientId,topic,2],reqArgs])
                if self._setupSubscribersAsynchronously:
                    self._defaultPublisher.publish(packedData)
                else:
                    self._serviceClient.call(packedData)
            else:
                packedData=msgpack.packb([[funcName,self._clientId,topic,4],reqArgs])
                if self._setupSubscribersAsynchronously:
                    self._defaultPublisher.publish(packedData)
                else:
                    self._serviceClient.call(packedData)
        elif topic in self._allDedicatedPublishers:
            packedData=msgpack.packb([[funcName,self._clientId,topic,3],reqArgs])
            self._allDedicatedPublishers[topic].publish(packedData)
        else:
            print('B0 Remote API error: invalid topic')
        
    def simxDefaultPublisher(self):
        return self._defaultPublisherTopic

    def simxCreatePublisher(self,dropMessages=False):
        topic=self._channelName+'Sub'+str(self._nextDedicatedPublisherHandle)+self._clientId
        self._nextDedicatedPublisherHandle=self._nextDedicatedPublisherHandle+1
        pub=b0.Publisher(self._node,topic,0,1)
        pub.init()
        self._allDedicatedPublishers[topic]=pub
        self._handleFunction('createSubscriber',[topic,dropMessages],self._serviceCallTopic)
        return topic

    def simxDefaultSubscriber(self,cb,publishInterval=1):
        topic=self._channelName+'Pub'+str(self._nextDefaultSubscriberHandle)+self._clientId
        self._nextDefaultSubscriberHandle=self._nextDefaultSubscriberHandle+1
        self._allSubscribers[topic]={}
        self._allSubscribers[topic]['handle']=self._defaultSubscriber
        self._allSubscribers[topic]['cb']=cb
        self._allSubscribers[topic]['dropMessages']=False
        channel=self._serviceCallTopic
        if self._setupSubscribersAsynchronously:
            channel=self._defaultPublisherTopic
        self._handleFunction('setDefaultPublisherPubInterval',[topic,publishInterval],channel)
        return topic
        
    def simxCreateSubscriber(self,cb,publishInterval=1,dropMessages=False):
        topic=self._channelName+'Pub'+str(self._nextDedicatedSubscriberHandle)+self._clientId
        self._nextDedicatedSubscriberHandle=self._nextDedicatedSubscriberHandle+1
        sub=b0.Subscriber(self._node,topic,None,0,1)
        sub.init()
        self._allSubscribers[topic]={}
        self._allSubscribers[topic]['handle']=sub
        self._allSubscribers[topic]['cb']=cb
        self._allSubscribers[topic]['dropMessages']=dropMessages
        channel=self._serviceCallTopic
        if self._setupSubscribersAsynchronously:
            channel=self._defaultPublisherTopic
        self._handleFunction('createPublisher',[topic,publishInterval],channel)
        return topic
  
    def simxServiceCall(self):
        return self._serviceCallTopic
        
    def simxSpin(self):
        while True:
            self.simxSpinOnce()
        
    def simxSpinOnce(self):
        defaultSubscriberAlreadyProcessed=False
        for key, value in self._allSubscribers.items():
            readData=None
            if (value['handle']!=self._defaultSubscriber) or (not defaultSubscriberAlreadyProcessed):
                defaultSubscriberAlreadyProcessed=defaultSubscriberAlreadyProcessed or (value['handle']==self._defaultSubscriber)
                while value['handle'].poll(0):
                    readData=value['handle'].read()
                    if not value['dropMessages']:
                        self._handleReceivedMessage(readData)
                if value['dropMessages'] and (readData is not None):
                    self._handleReceivedMessage(readData)
                    
    def simxGetTimeInMs(self):
        return self._node.hardware_time_usec()/1000;    

    def simxSleep(self,durationInMs):
        time.sleep(durationInMs)
        
    def simxSynchronous(self,enable):
        reqArgs = [enable]
        funcName = 'Synchronous'
        self._handleFunction(funcName,reqArgs,self._serviceCallTopic)
        
    def simxSynchronousTrigger(self):
        reqArgs = [0]
        funcName = 'SynchronousTrigger'
        self._handleFunction(funcName,reqArgs,self._defaultPublisherTopic)
        
    def simxGetSimulationStepDone(self,topic):
        if topic in self._allSubscribers:
            reqArgs = [0]
            funcName = 'GetSimulationStepDone'
            self._handleFunction(funcName,reqArgs,topic)
        else:
            print('B0 Remote API error: invalid topic')
        
    def simxGetSimulationStepStarted(self,topic):
        if topic in self._allSubscribers:
            reqArgs = [0]
            funcName = 'GetSimulationStepStarted'
            self._handleFunction(funcName,reqArgs,topic)
        else:
            print('B0 Remote API error: invalid topic')
    
    # ------------------------------
    # Add your custom function here:
    # ------------------------------
        
    def simxAuxiliaryConsoleClose(self,consoleHandle,topic):
        reqArgs = [consoleHandle]
        funcName = 'AuxiliaryConsoleClose'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxAuxiliaryConsolePrint(self,consoleHandle,text,topic):
        reqArgs = [consoleHandle,text]
        funcName = 'AuxiliaryConsolePrint'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxAuxiliaryConsoleOpen(self,title,maxLines,mode,position,size,textColor,backgroundColor,topic):
        reqArgs = [title,maxLines,mode,position,size,textColor,backgroundColor]
        funcName = 'AuxiliaryConsoleOpen'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxAuxiliaryConsoleShow(self,consoleHandle,showState,topic):
        reqArgs = [consoleHandle,showState]
        funcName = 'AuxiliaryConsoleShow'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxGetObjectHandle(self,objectName,topic):
        reqArgs = [objectName]
        funcName = 'GetObjectHandle'
        return self._handleFunction(funcName,reqArgs,topic)

    def simxAddStatusbarMessage(self,txt,topic):
        reqArgs = [txt]
        funcName = 'AddStatusbarMessage'
        return self._handleFunction(funcName,reqArgs,topic)

    def simxGetObjectPosition(self,objectHandle,refObjectHandle,topic):
        reqArgs = [objectHandle,refObjectHandle]
        funcName = 'GetObjectPosition'
        return self._handleFunction(funcName,reqArgs,topic)

    def simxStartSimulation(self,topic):
        reqArgs = []
        funcName = 'StartSimulation'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxStopSimulation(self,topic):
        reqArgs = []
        funcName = 'StopSimulation'
        return self._handleFunction(funcName,reqArgs,topic)

    def simxGetVisionSensorImage(self,objectHandle,greyscale,topic):
        reqArgs = [objectHandle,greyscale]
        funcName = 'GetVisionSensorImage'
        return self._handleFunction(funcName,reqArgs,topic)

    def simxSetVisionSensorImage(self,objectHandle,greyscale,img,topic):
        reqArgs = [objectHandle,greyscale,img]
        funcName = 'SetVisionSensorImage'
        return self._handleFunction(funcName,reqArgs,topic)

    def simxAddDrawingObject_points(self,size,color,coords,topic):
        reqArgs = [size,color,coords]
        funcName = 'AddDrawingObject_points'
        return self._handleFunction(funcName,reqArgs,topic)

    def simxAddDrawingObject_spheres(self,size,color,coords,topic):
        reqArgs = [size,color,coords]
        funcName = 'AddDrawingObject_spheres'
        return self._handleFunction(funcName,reqArgs,topic)

    def simxAddDrawingObject_cubes(self,size,color,coords,topic):
        reqArgs = [size,color,coords]
        funcName = 'AddDrawingObject_cubes'
        return self._handleFunction(funcName,reqArgs,topic)

    def simxAddDrawingObject_lines(self,lineSize,color,segments,topic):
        reqArgs = [lineSize,color,segments]
        funcName = 'AddDrawingObject_lines'
        return self._handleFunction(funcName,reqArgs,topic)

    def simxAddDrawingObject_triangles(self,color,triangles,topic):
        reqArgs = [color,triangles]
        funcName = 'AddDrawingObject_triangles'
        return self._handleFunction(funcName,reqArgs,topic)

    def simxRemoveDrawingObject(self,handle,topic):
        reqArgs = [handle]
        funcName = 'RemoveDrawingObject'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxCallScriptFunction(self,funcAtObjName,scriptType,arg1,arg2,arg3,arg4,topic):
        reqArgs = [funcAtObjName,scriptType,arg1,arg2,arg3,arg4]
        funcName = 'CallScriptFunction'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxCheckCollision(self,entity1,entity2,topic):
        reqArgs = [entity1,entity2]
        funcName = 'CheckCollision'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxGetCollisionHandle(self,name,topic):
        reqArgs = [name]
        funcName = 'GetCollisionHandle'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxReadCollision(self,handle,topic):
        reqArgs = [handle]
        funcName = 'ReadCollision'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxCheckDistance(self,entity1,entity2,threshold,topic):
        reqArgs = [entity1,entity2,threshold]
        funcName = 'CheckDistance'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxGetDistanceHandle(self,name,topic):
        reqArgs = [name]
        funcName = 'GetDistanceHandle'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxReadDistance(self,handle,topic):
        reqArgs = [handle]
        funcName = 'ReadDistance'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxCheckProximitySensor(self,sensor,entity,topic):
        reqArgs = [sensor,entity]
        funcName = 'CheckProximitySensor'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxReadProximitySensor(self,handle,topic):
        reqArgs = [handle]
        funcName = 'ReadProximitySensor'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxCheckVisionSensor(self,sensor,entity,topic):
        reqArgs = [sensor,entity]
        funcName = 'CheckVisionSensor'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxReadVisionSensor(self,handle,topic):
        reqArgs = [handle]
        funcName = 'ReadVisionSensor'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxReadForceSensor(self,handle,topic):
        reqArgs = [handle]
        funcName = 'ReadForceSensor'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxBreakForceSensor(self,handle,topic):
        reqArgs = [handle]
        funcName = 'BreakForceSensor'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxClearFloatSignal(self,sig,topic):
        reqArgs = [sig]
        funcName = 'ClearFloatSignal'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxClearIntegerSignal(self,sig,topic):
        reqArgs = [sig]
        funcName = 'ClearIntegerSignal'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxClearStringSignal(self,sig,topic):
        reqArgs = [sig]
        funcName = 'ClearStringSignal'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxSetFloatSignal(self,sig,val,topic):
        reqArgs = [sig,val]
        funcName = 'SetFloatSignal'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxSetIntegerSignal(self,sig,val,topic):
        reqArgs = [sig,val]
        funcName = 'SetIntegerSignal'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxSetStringSignal(self,sig,val,topic):
        reqArgs = [sig,val]
        funcName = 'SetStringSignal'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxGetFloatSignal(self,sig,topic):
        reqArgs = [sig]
        funcName = 'GetFloatSignal'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxGetIntegerSignal(self,sig,topic):
        reqArgs = [sig]
        funcName = 'GetIntegerSignal'
        return self._handleFunction(funcName,reqArgs,topic)
        
    def simxGetStringSignal(self,sig,topic):
        reqArgs = [sig]
        funcName = 'GetStringSignal'
        return self._handleFunction(funcName,reqArgs,topic)
        
    #constants to be added here
There will also be a customization script on the V-REP side to handle messages (publishers, subscribers and service calls)

Cheers

Justus
Posts: 37
Joined: 24 Jan 2017, 07:37

Re: python / bluezero

Post by Justus » 04 Jul 2018, 19:14

Hi,

Thanks for the info; so I suppose it is better to wait for a next release/revision before working with the BlueZero interface?
Will it also support the shared memory feature (like the current remoteApi)?

I tried the above with Python 2.7.13 (x86-64), but I still get the same error. Workflow: install python 2.7, put the .dll in the same dir, open python.exe (console) and run

Code: Select all

from ctypes import *
libc=CDLL('b0')
Above works like a charm with remoteapi.dll

Probably something simple, do you have any clue what might go wrong? Are there any dependencies in the DLL that could be an issue, or a 32/64bit thing?

Regards,
Justus

<edit> Also checked both remoteApi.dll and b0.dll with Dependency Walker, both dll's report many missing dependencies.

coppelia
Site Admin
Posts: 6867
Joined: 14 Dec 2012, 00:25

Re: python / bluezero

Post by coppelia » 05 Jul 2018, 14:42

Yes, there are several dependencies. On Windows typically, you need following items too, next to b0.dll:
  • boost_chrono_vc140-mt-1_62.dll
  • boost_system_vc140-mt-1_62.dll
  • boost_thread_vc140-mt-1_62.dll
  • libzmq.dll
The b0.py and b0RemoteApi.py code in my previous post was updated. Now it should also work With Python 3.X

Cheers

Justus
Posts: 37
Joined: 24 Jan 2017, 07:37

Re: python / bluezero

Post by Justus » 08 Jul 2018, 18:06

When running b0.py in the V-REP folder there is no missing DLL issue anymore (import b0 is succesful). However, a new error comes up (using Python 2.7, vanilla installation).

Code: Select all

Traceback (most recent call last):
  File "b0remoteapi.py", line 1, in <module>
    import b0
  File "C:\Program Files\V-REP3\V-REP_PRO\b0.py", line 71, in <module>
    _("b0_subscriber_poll", ct.c_int, ct.c_void_p, ct.c_long)
  File "C:\Program Files\V-REP3\V-REP_PRO\b0.py", line 33, in _
    globals()['_' + n] = ct.CFUNCTYPE(_wrap(ret), *[_wrap(arg) for arg in args])((n, libb0))
AttributeError: function 'b0_subscriber_poll' not found
Just to let you know. (I'll continue using the standard remoteApi.dll for now.)

fferri
Posts: 246
Joined: 09 Sep 2013, 19:28

Re: python / bluezero

Post by fferri » 09 Jul 2018, 10:56

It seems b0_subscriber_poll has been recently added to the python bindings (see commit 77bfd9f9).

So you'll need to get the latest source code from the bluezero git repository.

Post Reply