Hi, I am trying to write a Pure Data external for getting real time motion capture values from an Xsens system. According to the manual ( https://xsens.com/download/usermanual/3DBM/MVN_real-time_network_streaming_p...), the x, y and z coordinates of the skeleton segment positions are transferred over network (udp) as sequential 4 bytes (32 bit floating point
I am reading the udp data with [netreceive] succesfully and able to reach any value I need. Now trying to find a way to combine these (big endian) sequential 4 bytes in order to get the resulting 32 bit floating point number. A little advice would speed me up.
By the way, I studied the [oscparse] source. It was very helpful in most ways but also a little complicated too.
Thanks already.
I found a method using "memcpy". Seems like it is working for now.
Arda Eden ardaeden@gmail.com, 5 Nis 2019 Cum, 16:00 tarihinde şunu yazdı:
Hi, I am trying to write a Pure Data external for getting real time motion capture values from an Xsens system. According to the manual ( https://xsens.com/download/usermanual/3DBM/MVN_real-time_network_streaming_p...), the x, y and z coordinates of the skeleton segment positions are transferred over network (udp) as sequential 4 bytes (32 bit floating point
- big endian).
I am reading the udp data with [netreceive] succesfully and able to reach any value I need. Now trying to find a way to combine these (big endian) sequential 4 bytes in order to get the resulting 32 bit floating point number. A little advice would speed me up.
By the way, I studied the [oscparse] source. It was very helpful in most ways but also a little complicated too.
Thanks already.
-- Arda EDEN Yıldız Teknik Üniversitesi Sanat ve Tasarım Fakültesi Müzik ve Sahne Sanatları Bölümü Duysal (Ses) Sanatları Tasarımı Programı İstanbul/Türkiye
Yildiz Technical University Faculty of Art and Design Department of Music and Performing Arts Audio Design Program Istanbul/Turkey
hello, I think a better way (that did not need to copy the data) is to use a union : i.e. 2 different type can be declared in the same memory space. something like :
// union type definition union int_and_float { int8_t my_int[4]; float my_float; };
int_and_float my_int_and_float; // declaration of a variable of this type
my_int_and_float.my_int[0] = 0; // value assignation my_int_and_float.my_int[1] = 0; my_int_and_float.my_int[2] = 0; my_int_and_float.my_int[3] = 0;
the float data should be in : my_int_and_float.my_float;
I did not test this code, It will certainly contain syntaxes errors, but you'll find the way to correct it on internet...
An other solution is to use bitwise operator :
my_float = (byte1 << 24) & (byte2 << 16) & (byte3 << 8) & byte4;
cheers Cyrille
Le 05/04/2019 à 19:04, Arda Eden a écrit :
I found a method using "memcpy". Seems like it is working for now.
Arda Eden <ardaeden@gmail.com mailto:ardaeden@gmail.com>, 5 Nis 2019 Cum, 16:00 tarihinde şunu yazdı:
Hi, I am trying to write a Pure Data external for getting real time motion capture values from an Xsens system. According to the manual (https://xsens.com/download/usermanual/3DBM/MVN_real-time_network_streaming_protocol_specification.pdf), the x, y and z coordinates of the skeleton segment positions are transferred over network (udp) as sequential 4 bytes (32 bit floating point - big endian). I am reading the udp data with [netreceive] succesfully and able to reach any value I need. Now trying to find a way to combine these (big endian) sequential 4 bytes in order to get the resulting 32 bit floating point number. A little advice would speed me up. By the way, I studied the [oscparse] source. It was very helpful in most ways but also a little complicated too. Thanks already. -- Arda EDEN Yıldız Teknik Üniversitesi Sanat ve Tasarım Fakültesi Müzik ve Sahne Sanatları Bölümü Duysal (Ses) Sanatları Tasarımı Programı İstanbul/Türkiye Yildiz Technical University Faculty of Art and Design Department of Music and Performing Arts Audio Design Program Istanbul/Turkey
-- Arda EDEN Yıldız Teknik Üniversitesi Sanat ve Tasarım Fakültesi Müzik ve Sahne Sanatları Bölümü Duysal (Ses) Sanatları Tasarımı Programı İstanbul/Türkiye
Yildiz Technical University Faculty of Art and Design Department of Music and Performing Arts Audio Design Program Istanbul/Turkey
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
On Sat, 2019-04-06 at 11:28 +0200, cyrille henry wrote:
An other solution is to use bitwise operator :
my_float = (byte1 << 24) & (byte2 << 16) & (byte3 << 8) & byte4;
From what I understand, the result is not a 32 bit floating point number, but a 32 bit unsigned int (assuming that each byte is an unsigned 8 bit int).
Roman
While type punning through unions is allowed in C, the only way which works in both C and C++ (without breaking the strict aliasing rule) is using memcpy. In such case, the call to memcpy will completely optimized away by every decent compiler.
Gesendet: Samstag, 06. April 2019 um 11:28 Uhr Von: "cyrille henry" ch@chnry.net An: "pd-list@lists.iem.at" pd-list@lists.iem.at Betreff: Re: [PD] Getting 32 bit floating point number from 4 sequential bytes
hello, I think a better way (that did not need to copy the data) is to use a union : i.e. 2 different type can be declared in the same memory space. something like :
// union type definition union int_and_float { int8_t my_int[4]; float my_float; };
int_and_float my_int_and_float; // declaration of a variable of this type
my_int_and_float.my_int[0] = 0; // value assignation my_int_and_float.my_int[1] = 0; my_int_and_float.my_int[2] = 0; my_int_and_float.my_int[3] = 0;
the float data should be in : my_int_and_float.my_float;
I did not test this code, It will certainly contain syntaxes errors, but you'll find the way to correct it on internet...
An other solution is to use bitwise operator :
my_float = (byte1 << 24) & (byte2 << 16) & (byte3 << 8) & byte4;
cheers Cyrille
Le 05/04/2019 à 19:04, Arda Eden a écrit :
I found a method using "memcpy". Seems like it is working for now.
Arda Eden <ardaeden@gmail.com mailto:ardaeden@gmail.com>, 5 Nis 2019 Cum, 16:00 tarihinde şunu yazdı:
Hi, I am trying to write a Pure Data external for getting real time motion capture values from an Xsens system. According to the manual (https://xsens.com/download/usermanual/3DBM/MVN_real-time_network_streaming_protocol_specification.pdf), the x, y and z coordinates of the skeleton segment positions are transferred over network (udp) as sequential 4 bytes (32 bit floating point - big endian). I am reading the udp data with [netreceive] succesfully and able to reach any value I need. Now trying to find a way to combine these (big endian) sequential 4 bytes in order to get the resulting 32 bit floating point number. A little advice would speed me up. By the way, I studied the [oscparse] source. It was very helpful in most ways but also a little complicated too. Thanks already. -- Arda EDEN Yıldız Teknik Üniversitesi Sanat ve Tasarım Fakültesi Müzik ve Sahne Sanatları Bölümü Duysal (Ses) Sanatları Tasarımı Programı İstanbul/Türkiye Yildiz Technical University Faculty of Art and Design Department of Music and Performing Arts Audio Design Program Istanbul/Turkey
-- Arda EDEN Yıldız Teknik Üniversitesi Sanat ve Tasarım Fakültesi Müzik ve Sahne Sanatları Bölümü Duysal (Ses) Sanatları Tasarımı Programı İstanbul/Türkiye
Yildiz Technical University Faculty of Art and Design Department of Music and Performing Arts Audio Design Program Istanbul/Turkey
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
On Sat, Apr 6, 2019 at 10:06 AM Christof Ressi christof.ressi@gmx.at wrote:
While type punning through unions is allowed in C, the only way which works in both C and C++ (without breaking the strict aliasing rule) is using memcpy. In such case, the call to memcpy will completely optimized away by every decent compiler.
But Pd is written in c, so no problem. How does the memcpy thing work? It is also ANSI c. To m it looks just as 'dangerous' as the union method, which I wouldn't call type-punning. 'Raw' type punning would be like: uint8_t bytes[4] = {12, 34, 56, 78}; float f = *(float*)bytes; But isn't that basically the same as what memcpy does?
Martin
With this method, I got the compiler warning about breaking the strict aliasing rule: uint8_t bytes[4] = {12, 34, 56, 78}; float f = *(float*)bytes;
This is my code, and for now, it is working properly. But I am not sure if this is an efficient way or not.
typedef struct _xsensparse { t_object x_obj; uint8_t wrd[4]; t_float o; t_outlet *f1_out, *f2_out; } t_xsensparse;
static void xsensparse_list(t_xsensparse *x, t_symbol *s, int argc, t_atom *argv) { for(int i=0; i<argc; i++) { x->wrd[i]=(uint8_t)atom_getfloat(argv+3-i); memcpy(&x->o, &x->wrd, 4); } post("%f", x->o); outlet_float(x->f1_out, x->o); }
Martin Peach chakekatzil@gmail.com, 6 Nis 2019 Cmt, 17:36 tarihinde şunu yazdı:
On Sat, Apr 6, 2019 at 10:06 AM Christof Ressi christof.ressi@gmx.at wrote:
While type punning through unions is allowed in C, the only way which works in both C and C++ (without breaking the strict aliasing rule) is using memcpy. In such case, the call to memcpy will completely optimized away by every decent compiler.
But Pd is written in c, so no problem. How does the memcpy thing work? It is also ANSI c. To m it looks just as 'dangerous' as the union method, which I wouldn't call type-punning. 'Raw' type punning would be like: uint8_t bytes[4] = {12, 34, 56, 78}; float f = *(float*)bytes; But isn't that basically the same as what memcpy does?
Martin
Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list
On Sat, Apr 6, 2019 at 10:54 AM Arda Eden ardaeden@gmail.com wrote:
With this method, I got the compiler warning about breaking the strict aliasing rule: uint8_t bytes[4] = {12, 34, 56, 78}; float f = *(float*)bytes;
Yes, modern c doesn't like type punning.
This is my code, and for now, it is working properly. But I am not sure if this is an efficient way or not.
typedef struct _xsensparse { t_object x_obj; uint8_t wrd[4]; t_float o; t_outlet *f1_out, *f2_out; } t_xsensparse;
static void xsensparse_list(t_xsensparse *x, t_symbol *s, int argc, t_atom *argv) { for(int i=0; i<argc; i++) { x->wrd[i]=(uint8_t)atom_getfloat(argv+3-i); memcpy(&x->o, &x->wrd, 4); } post("%f", x->o); outlet_float(x->f1_out, x->o); }
I think the memcpy statement should be outside the for loop. As it is, it operates the first three times uselessly. Using a union would be a bit more efficient as it doesn't copy any memory.
Martin
Absolutely !!! Copying memory 3 times is not efficient already. :) Thanks Martin.
I just need to get 2 or a few skeleton segments for a contemporary dance performance, and this way, I will solve my problem temporarily. Xsens may not be a widely used system, but it works great. I think it deserves an Xsens to OSC converter PD object some day, But this exceeds my programming skills (as you will get it from my code above :) ).
Just remembered now: Xsens has a fps rate of 60-240 and a very big amount of data is transferred very fast over the network. When I listened the packages with [netreceive] and printed them on the console, PD Vanilla 0.49.1 crashed. But it worked with Purr-data. Indeed, I didn't have time to test it in detail. Maybe the problem was with my computer. Just for info. Thank you my friends.
Using a union would be a bit more efficient as it doesn't copy any memory.
an optimizing compiler will very likely generate identical assembly. look here, how the call to memcpy is reduced to a single 'movss' instruction: https://godbolt.org/z/n5ueWD
@Arda: shouldn't 'wrd' and 'o' be local variables instead of struct members? or do you need somehow to cache the value for later?
Christof
Gesendet: Samstag, 06. April 2019 um 17:27 Uhr Von: "Martin Peach" chakekatzil@gmail.com An: Pd-List pd-list@lists.iem.at Betreff: Re: [PD] Getting 32 bit floating point number from 4 sequential bytes
On Sat, Apr 6, 2019 at 10:54 AM Arda Eden <ardaeden@gmail.com[mailto:ardaeden@gmail.com]> wrote:
With this method, I got the compiler warning about breaking the strict aliasing rule: uint8_t bytes[4] = {12, 34, 56, 78}; float f = *(float*)bytes; Yes, modern c doesn't like type punning.
This is my code, and for now, it is working properly. But I am not sure if this is an efficient way or not. typedef struct _xsensparse { t_object x_obj; uint8_t wrd[4]; t_float o; t_outlet *f1_out, *f2_out; } t_xsensparse; static void xsensparse_list(t_xsensparse *x, t_symbol *s, int argc, t_atom *argv) { for(int i=0; i<argc; i++) { x->wrd[i]=(uint8_t)atom_getfloat(argv+3-i); memcpy(&x->o, &x->wrd, 4); } post("%f", x->o); outlet_float(x->f1_out, x->o); } I think the memcpy statement should be outside the for loop. As it is, it operates the first three times uselessly. Using a union would be a bit more efficient as it doesn't copy any memory. Martin _______________________________________________ Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list%5Bhttps://lists.puredata.info/l...]
Christof, Yes, you are right. For this example keeping them as local variables will be better. This code is just a scratch and I actually didn't think about the life cycle of those variables. My first plan was to write an xsenstoOSC converter. But when my skills are considered, I will need to read a lot of documentation for this and I don't have time. I just have to save the day. Thanks.
Christof Ressi christof.ressi@gmx.at, 6 Nis 2019 Cmt, 19:16 tarihinde şunu yazdı:
Using a union would be a bit more efficient as it doesn't copy any
memory.
an optimizing compiler will very likely generate identical assembly. look here, how the call to memcpy is reduced to a single 'movss' instruction: https://godbolt.org/z/n5ueWD
@Arda: shouldn't 'wrd' and 'o' be local variables instead of struct members? or do you need somehow to cache the value for later?
Christof
Gesendet: Samstag, 06. April 2019 um 17:27 Uhr Von: "Martin Peach" chakekatzil@gmail.com An: Pd-List pd-list@lists.iem.at Betreff: Re: [PD] Getting 32 bit floating point number from 4 sequential bytes
On Sat, Apr 6, 2019 at 10:54 AM Arda Eden <ardaeden@gmail.com[mailto: ardaeden@gmail.com]> wrote:
With this method, I got the compiler warning about breaking the strict aliasing rule: uint8_t bytes[4] = {12, 34, 56, 78}; float f = *(float*)bytes;
Yes, modern c doesn't like type punning.
This is my code, and for now, it is working properly. But I am not sure if this is an efficient way or not.
typedef struct _xsensparse { t_object x_obj; uint8_t wrd[4]; t_float o; t_outlet *f1_out, *f2_out; } t_xsensparse;
static void xsensparse_list(t_xsensparse *x, t_symbol *s, int argc, t_atom *argv) { for(int i=0; i<argc; i++) { x->wrd[i]=(uint8_t)atom_getfloat(argv+3-i); memcpy(&x->o, &x->wrd, 4); } post("%f", x->o); outlet_float(x->f1_out, x->o); }
I think the memcpy statement should be outside the for loop. As it is, it operates the first three times uselessly. Using a union would be a bit more efficient as it doesn't copy any memory.
Martin _______________________________________________ Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list%5Bhttps://lists.puredata.info/l...]
Hi Arda
On Fri, 2019-04-05 at 16:00 +0300, Arda Eden wrote:
I am reading the udp data with [netreceive] succesfully and able to reach any value I need. Now trying to find a way to combine these (big endian) sequential 4 bytes in order to get the resulting 32 bit floating point number. A little advice would speed me up.
Don't know if you need to do it in your own external. If you do the message parsing in Pd (as opposed to a dedicated external), check attached patch. It converts between floats and 4-byte-lists. Probably not efficient, when converting tons of numbers, but easy if you're looking for a quick'n'dirty solution.
Roman
Thanks Roman, I didn't know that this was possible with [oscformat] and [oscparse]. Thanks all the friends here, I finally succeed writing my own external. Not a perfect one, but solved my problem for now.
Roman Haefeli reduzent@gmail.com, 7 Nis 2019 Paz, 18:54 tarihinde şunu yazdı:
Hi Arda
On Fri, 2019-04-05 at 16:00 +0300, Arda Eden wrote:
I am reading the udp data with [netreceive] succesfully and able to reach any value I need. Now trying to find a way to combine these (big endian) sequential 4 bytes in order to get the resulting 32 bit floating point number. A little advice would speed me up.
Don't know if you need to do it in your own external. If you do the message parsing in Pd (as opposed to a dedicated external), check attached patch. It converts between floats and 4-byte-lists. Probably not efficient, when converting tons of numbers, but easy if you're looking for a quick'n'dirty solution.
Roman _______________________________________________ Pd-list@lists.iem.at mailing list UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list