Closed lrapetti closed 1 year ago
Maybe @traversaro or @GiulioRomualdi that have more experience on bindings generation and usage might help?
Indeed, this is quite counterintuitive, but I guess it is how pybind11 works, see https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html :
In this case, properties can be read and written in their entirety. However, an append operation involving such a list type has no effect:
So, we cannot append to the poseSensors
attribute, but only substitute it. Accounting for this, and for the element type of the poseSensors
map is the PoseSensors
, not PoseSensorsData
(see https://github.com/robotology/wearables/blob/v1.7.1/msgs/thrift/WearableData.thrift#L183), a working variant of your script is:
import yarp
import wearables.bindings as wearables
import time
# create the yarp network
network = yarp.Network()
network.init()
port = wearables.msg.BufferedPortWearableData()
port.open("/foo2")
time.sleep(1)
data = port.prepare()
data.producerName = "myWearableDevice"
time.sleep(1)
# here we create a PoseSensorData message, and try to update the value of the position x
myPoseSensorData = wearables.msg.PoseSensorData()
myPoseSensorData.position.x = 1.0
print(myPoseSensorData.position.x) #this returns the expected value
myPoseSensor = wearables.msg.PoseSensor()
myPoseSensor.data = myPoseSensorData
# here we want to add myPoseSensor to the data.poseSensors dictionary
originalPoseSensors = data.poseSensors
originalPoseSensors.update({"firstTracker": myPoseSensor})
data.poseSensors = originalPoseSensors
print(data)
# If we try to print the value from the dictionary here it returns an error (see below)
print(data.poseSensors["firstTracker"].data.position.x)
while True:
print(data)
port.write()
time.sleep(1)
To make the code more user-friendly I do not know if it is helpful to use PYBIND11_MAKE_OPAQUE
, as I never tried it.
Tested with:
(wearables190) traversaro@IITICUBLAP257:~/wearables190$ mamba list
List of packages in environment: "/home/traversaro/mambaforge/envs/wearables190"
Name Version Build Channel
─────────────────────────────────────────────────────────────────────────────
_libgcc_mutex 0.1 conda_forge conda-forge
_openmp_mutex 4.5 2_gnu conda-forge
ace 7.1.0 hcb278e6_0 conda-forge
alsa-lib 1.2.8 h166bdaf_0 conda-forge
ampl-mp 3.1.0 h2cc385e_1006 conda-forge
aom 3.5.0 h27087fc_0 conda-forge
assimp 5.2.5 hf40c2ba_0 conda-forge
attr 2.5.1 h166bdaf_1 conda-forge
boost-cpp 1.78.0 h6582d0a_3 conda-forge
bzip2 1.0.8 h7f98852_4 conda-forge
c-ares 1.19.1 hd590300_0 conda-forge
ca-certificates 2023.5.7 hbcca054_0 conda-forge
cairo 1.16.0 hbbf8b49_1016 conda-forge
dav1d 1.2.1 hd590300_0 conda-forge
dbus 1.13.6 h5008d03_3 conda-forge
eigen 3.4.0 h4bd325d_0 conda-forge
expat 2.5.0 hcb278e6_1 conda-forge
ffmpeg 6.0.0 gpl_hdbbbd96_103 conda-forge
font-ttf-dejavu-sans-mono 2.37 hab24e00_0 conda-forge
font-ttf-inconsolata 3.000 h77eed37_0 conda-forge
font-ttf-source-code-pro 2.038 h77eed37_0 conda-forge
font-ttf-ubuntu 0.83 hab24e00_0 conda-forge
fontconfig 2.14.2 h14ed4e7_0 conda-forge
fonts-conda-ecosystem 1 0 conda-forge
fonts-conda-forge 1 0 conda-forge
freeglut 3.2.2 hac7e632_2 conda-forge
freetype 2.12.1 hca18f0e_1 conda-forge
fribidi 1.0.10 h36c2ea0_0 conda-forge
gettext 0.21.1 h27087fc_0 conda-forge
glfw 3.3.8 hd590300_1 conda-forge
glib 2.76.3 hfc55251_0 conda-forge
glib-tools 2.76.3 hfc55251_0 conda-forge
gmp 6.2.1 h58526e2_0 conda-forge
gnutls 3.7.8 hf3e180e_0 conda-forge
graphite2 1.3.13 h58526e2_1001 conda-forge
gst-plugins-base 1.22.3 h938bd60_1 conda-forge
gstreamer 1.22.3 h977cf35_1 conda-forge
harfbuzz 7.3.0 hdb3a94d_0 conda-forge
hdf5 1.14.1 nompi_h4f84152_100 conda-forge
icu 72.1 hcb278e6_0 conda-forge
idyntree 9.1.0 py310hcc9ab6b_1 conda-forge
ipopt 3.14.12 hf9e1ecf_0 conda-forge
irrlicht 1.8.5 h3749e40_3 conda-forge
jasper 4.0.0 h32699f2_1 conda-forge
keyutils 1.6.1 h166bdaf_0 conda-forge
krb5 1.20.1 h81ceb04_0 conda-forge
lame 3.100 h166bdaf_1003 conda-forge
ld_impl_linux-64 2.40 h41732ed_0 conda-forge
lerc 4.0.0 h27087fc_0 conda-forge
libabseil 20230125.2 cxx17_h59595ed_2 conda-forge
libaec 1.0.6 hcb278e6_1 conda-forge
libass 0.17.1 hc9aadba_0 conda-forge
libblas 3.9.0 17_linux64_openblas conda-forge
libcap 2.67 he9d0100_0 conda-forge
libcblas 3.9.0 17_linux64_openblas conda-forge
libclang 15.0.7 default_h7634d5b_2 conda-forge
libclang13 15.0.7 default_h9986a30_2 conda-forge
libcups 2.3.3 h36d4200_3 conda-forge
libcurl 8.1.2 h409715c_0 conda-forge
libdeflate 1.18 h0b41bf4_0 conda-forge
libdrm 2.4.114 h166bdaf_0 conda-forge
libedit 3.1.20191231 he28a2e2_2 conda-forge
libev 4.33 h516909a_1 conda-forge
libevent 2.1.12 hf998b51_1 conda-forge
libexpat 2.5.0 hcb278e6_1 conda-forge
libffi 3.4.2 h7f98852_5 conda-forge
libflac 1.4.3 h59595ed_0 conda-forge
libgcc-ng 13.1.0 he5830b7_0 conda-forge
libgcrypt 1.10.1 h166bdaf_0 conda-forge
libgfortran-ng 13.1.0 h69a702a_0 conda-forge
libgfortran5 13.1.0 h15d22d2_0 conda-forge
libglib 2.76.3 hebfc3b9_0 conda-forge
libglu 9.0.0 hac7e632_1002 conda-forge
libgomp 13.1.0 he5830b7_0 conda-forge
libgpg-error 1.47 h71f35ed_0 conda-forge
libi2c 4.3 hcb278e6_2 conda-forge
libiconv 1.17 h166bdaf_0 conda-forge
libidn2 2.3.4 h166bdaf_0 conda-forge
libjpeg-turbo 2.1.5.1 h0b41bf4_0 conda-forge
liblapack 3.9.0 17_linux64_openblas conda-forge
liblapacke 3.9.0 17_linux64_openblas conda-forge
libllvm15 15.0.7 h5cf9203_2 conda-forge
libmatio 1.5.23 hde58830_3 conda-forge
libmatio-cpp 0.2.2 h002c22a_0 conda-forge
libnghttp2 1.52.0 h61bc06f_0 conda-forge
libnsl 2.0.0 h7f98852_0 conda-forge
libogg 1.3.4 h7f98852_1 conda-forge
libopenblas 0.3.23 pthreads_h80387f5_0 conda-forge
libopencv 4.7.0 py38h16dcf2c_5 conda-forge
libopus 1.3.1 h7f98852_1 conda-forge
libosqp 0.6.3 h59595ed_0 conda-forge
libpciaccess 0.17 h166bdaf_0 conda-forge
libpng 1.6.39 h753d276_0 conda-forge
libpq 15.3 hbcd7760_1 conda-forge
libprotobuf 4.23.2 hd1fb520_5 conda-forge
libqdldl 0.1.5 h27087fc_1 conda-forge
librobometry 1.2.1 hc5a7426_1 conda-forge
libsndfile 1.2.0 hb75c966_0 conda-forge
libsqlite 3.42.0 h2797004_0 conda-forge
libssh2 1.11.0 h0841786_0 conda-forge
libstdcxx-ng 13.1.0 hfd8a6a1_0 conda-forge
libsystemd0 253 h8c4010b_1 conda-forge
libtasn1 4.19.0 h166bdaf_0 conda-forge
libtiff 4.5.1 h8b53f26_0 conda-forge
libunistring 0.9.10 h7f98852_0 conda-forge
libuuid 2.38.1 h0b41bf4_0 conda-forge
libva 2.18.0 h0b41bf4_0 conda-forge
libvorbis 1.3.7 h9c3ff4c_0 conda-forge
libvpx 1.13.0 hcb278e6_0 conda-forge
libwebp-base 1.3.0 h0b41bf4_0 conda-forge
libxcb 1.15 h0b41bf4_0 conda-forge
libxkbcommon 1.5.0 h5d7e998_3 conda-forge
libxml2 2.11.4 h0d562d8_0 conda-forge
libzlib 1.2.13 hd590300_5 conda-forge
lz4-c 1.9.4 hcb278e6_0 conda-forge
metis 5.1.0 h58526e2_1006 conda-forge
mpg123 1.31.3 hcb278e6_0 conda-forge
mumps-include 5.2.1 ha770c72_11 conda-forge
mumps-seq 5.2.1 h2104b81_11 conda-forge
mysql-common 8.0.33 hf1915f5_0 conda-forge
mysql-libs 8.0.33 hca2cd23_0 conda-forge
ncurses 6.4 hcb278e6_0 conda-forge
nettle 3.8.1 hc379101_1 conda-forge
nspr 4.35 h27087fc_0 conda-forge
nss 3.89 he45b914_0 conda-forge
numpy 1.25.0 py310ha4c1d20_0 conda-forge
openh264 2.3.1 hcb278e6_2 conda-forge
openssl 3.1.1 hd590300_1 conda-forge
osqp-eigen 0.8.0 hdd734ac_1 conda-forge
p11-kit 0.24.1 hc5aa10d_0 conda-forge
pcre2 10.40 hc3806b6_0 conda-forge
pip 23.1.2 pyhd8ed1ab_0 conda-forge
pixman 0.40.0 h36c2ea0_0 conda-forge
portaudio 19.6.0 h583fa2b_7 conda-forge
pthread-stubs 0.4 h36c2ea0_1001 conda-forge
pulseaudio-client 16.1 hb77b528_4 conda-forge
pybind11-abi 4 hd8ed1ab_3 conda-forge
python 3.10.12 hd12c33a_0_cpython conda-forge
python_abi 3.10 3_cp310 conda-forge
qt-main 5.15.8 h01ceb2d_13 conda-forge
readline 8.2 h8228510_1 conda-forge
robot-testing-framework 2.0.1 hcb278e6_1 conda-forge
scotch 6.0.9 hb2e6521_2 conda-forge
sdl 1.2.64 h293081c_0 conda-forge
sdl2 2.26.5 h949db6a_0 conda-forge
setuptools 68.0.0 pyhd8ed1ab_0 conda-forge
soxr 0.1.3 h0b41bf4_3 conda-forge
svt-av1 1.6.0 h59595ed_0 conda-forge
tinyxml 2.6.2 h4bd325d_2 conda-forge
tk 8.6.12 h27826a3_0 conda-forge
tzdata 2023c h71feb2d_0 conda-forge
unixodbc 2.3.10 h583eb01_0 conda-forge
visit_struct 1.0.0.1 hcb278e6_2 conda-forge
wearables 1.7.1 py310h64a2142_88 robotology
wheel 0.40.0 pyhd8ed1ab_0 conda-forge
x264 1!164.3095 h166bdaf_2 conda-forge
x265 3.5 h924138e_3 conda-forge
xcb-util 0.4.0 hd590300_1 conda-forge
xcb-util-image 0.4.0 h8ee46fc_1 conda-forge
xcb-util-keysyms 0.4.0 h8ee46fc_1 conda-forge
xcb-util-renderutil 0.3.9 hd590300_1 conda-forge
xcb-util-wm 0.4.1 h8ee46fc_1 conda-forge
xkeyboard-config 2.39 hd590300_0 conda-forge
xorg-fixesproto 5.0 h7f98852_1002 conda-forge
xorg-inputproto 2.3.2 h7f98852_1002 conda-forge
xorg-kbproto 1.0.7 h7f98852_1002 conda-forge
xorg-libice 1.1.1 hd590300_0 conda-forge
xorg-libsm 1.2.4 h7391055_0 conda-forge
xorg-libx11 1.8.6 h8ee46fc_0 conda-forge
xorg-libxau 1.0.11 hd590300_0 conda-forge
xorg-libxcursor 1.2.0 h0b41bf4_1 conda-forge
xorg-libxdmcp 1.1.3 h7f98852_0 conda-forge
xorg-libxext 1.3.4 h0b41bf4_2 conda-forge
xorg-libxfixes 5.0.3 h7f98852_1004 conda-forge
xorg-libxi 1.7.10 h7f98852_0 conda-forge
xorg-libxinerama 1.1.5 h27087fc_0 conda-forge
xorg-libxrandr 1.5.2 h7f98852_1 conda-forge
xorg-libxrender 0.9.10 h7f98852_1003 conda-forge
xorg-randrproto 1.5.0 h7f98852_1001 conda-forge
xorg-renderproto 0.11.1 h7f98852_1002 conda-forge
xorg-xextproto 7.3.0 h0b41bf4_1003 conda-forge
xorg-xf86vidmodeproto 2.3.1 h7f98852_1002 conda-forge
xorg-xproto 7.0.31 h7f98852_1007 conda-forge
xz 5.2.6 h166bdaf_0 conda-forge
yarp 3.8.1 ha770c72_0 conda-forge
yarp-cxx 3.8.1 h245b40a_0 conda-forge
yarp-python 3.8.1 py310h6c2f4e2_0 conda-forge
ycm-cmake-modules 0.15.3 h59595ed_0 conda-forge
zlib 1.2.13 hd590300_5 conda-forge
zstd 1.5.2 h3eb15da_6 conda-forge
Thanks a lot @traversaro! The example you provided is working for me and I see the following print of data
:
myWearableDevice () () () () () () () () ((firstTracker ("" 0 0.0 0.0 0.0 0.0 1.0 0.0 0.0))) () () () () () () ()
Still I am not able to read the port from yarp
$ yarp read ... /foo2
\[INFO] |yarp.os.Port|/tmp/port/1| Port /tmp/port/1 active at tcp://10.0.2.116:10003/
[INFO] |yarp.os.impl.PortCoreInputUnit|/tmp/port/1| Receiving input from /foo2 to /tmp/port/1 using tcp
this was happening also with my previous script, it was not publishing even the empty message.
Working version:
import yarp
import wearables.bindings as wearables
import time
# create the yarp network
network = yarp.Network()
network.init()
port = wearables.msg.BufferedPortWearableData()
port.open("/foo2")
time.sleep(1)
data = port.prepare()
data.producerName = "myWearableDevice"
time.sleep(1)
# here we create a PoseSensorData message, and try to update the value of the position x
myPoseSensorData = wearables.msg.PoseSensorData()
myPoseSensorData.position.x = 1.0
print(myPoseSensorData.position.x) #this returns the expected value
myPoseSensor = wearables.msg.PoseSensor()
myPoseSensor.data = myPoseSensorData
# here we want to add myPoseSensor to the data.poseSensors dictionary
originalPoseSensors = data.poseSensors
originalPoseSensors.update({"firstTracker": myPoseSensor})
data.poseSensors = originalPoseSensors
print(data)
# If we try to print the value from the dictionary here it returns an error (see below)
print(data.poseSensors["firstTracker"].data.position.x)
dataToSend = data
while True:
newData = port.prepare()
newData = dataToSend
print(dataToSend)
print(newData)
port.write()
time.sleep(1)
Output:
(wearables190) traversaro@IITICUBLAP257:~/wearables190$ yarp read ... /foo2
[INFO] |yarp.os.Port|/tmp/port/1| Port /tmp/port/1 active at tcp://172.23.21.248:10003/
[INFO] |yarp.os.impl.PortCoreInputUnit|/tmp/port/1| Receiving input from /foo2 to /tmp/port/1 using tcp
myWearableDevice () () () () () () () () ((firstTracker ("" 0 0.0 0.0 0.0 0.0 1.0 0.0 0.0))) () () () () () () ()
myWearableDevice () () () () () () () () ((firstTracker ("" 0 0.0 0.0 0.0 0.0 1.0 0.0 0.0))) () () () () () () ()
myWearableDevice () () () () () () () () ((firstTracker ("" 0 0.0 0.0 0.0 0.0 1.0 0.0 0.0))) () () () () () () ()
myWearableDevice () () () () () () () () ((firstTracker ("" 0 0.0 0.0 0.0 0.0 1.0 0.0 0.0))) () () () () () () ()
^CInterrupting...
[INFO] |yarp.os.impl.PortCoreInputUnit|/tmp/port/1| Removing input from /foo2 to /tmp/port/1
Thanks @traversaro, I am now able to read data from the port, what was missingwas to capp port.prepare()
in the loop.
Here, for reference, is the final test script I was using for testing:
import yarp
import wearables.bindings as wearables
import time
# create the yarp network
network = yarp.Network()
network.init()
# create a buffered wearable data port
port = wearables.msg.BufferedPortWearableData()
port.open("/foo")
time.sleep(0.2)
# prepare data
dataToSend = port.prepare()
dataToSend.producerName = "myWearableDevice"
time.sleep(0.2)
# prepare a pose sensor data
myPoseSensor = wearables.msg.PoseSensor()
myPoseSensor.data = wearables.msg.PoseSensorData()
myPoseSensor.info.name = "myWearableDevice::Pose::FirstTracker"
myPoseSensor.info.status = wearables.msg.OK
# add the pose sensor data to the data.poseSensors dictionary
originalPoseSensors = dataToSend.poseSensors
dataToSend.poseSensors.update({"FristTracker": myPoseSensor})
dataToSend.poseSensors = originalPoseSensors
count = 0
while True:
# update data
count = count + 1
dataToSend.poseSensors["FristTracker"].data.position.x = count
data = port.prepare()
data = dataToSend
print(data)
port.write()
time.sleep(0.05)
cc @Zweisteine96 I think this will be useful for your use case.
With @Zweisteine96 we tried to use the python bindings (that were added with https://github.com/robotology/wearables/pull/162) in order to open a wearable data port and publish some data.
This is the script we are using
But what happen is that:
if we try to access the data from the dictionary (the line that is commented above) we get the following error:
If instead we leave that line commented, when printing
data
it seems that the data is not added (this is what it is printed in the while loop byprint(data)
):(We can observe that the
data.producerName
is updated, but the rest is empty)