Loading ...
Sorry, an error occurred while loading the content.

WorldStateSerializer

Expand Messages
  • crews1969
    I am still working on my player driver for the aibo and have gotten the WSS stream coming in. I created a struct to hold all the fields and typecast the
    Message 1 of 29 , Sep 1, 2005
    • 0 Attachment
      I am still working on my player driver for the aibo and have gotten
      the WSS stream coming in. I created a struct to hold all the fields
      and typecast the incoming character array into the struct.
      {typedef struct AIBOWorldSerializer {
      unsigned int timestamp;
      unsigned int NumPIDJoints;
      float JointPositions[24];
      unsigned int NumSensors;
      float SensorData[11];
      unsigned NumButtons;
      float ButtonData[10];
      float DutyCycleData[4];
      }AIBOWorldSerializerData;

      Then I pull out the FarIR data (second index of sensor data array):

      (int)((AIBOWorldSerializerData) *streamdata)->SensorData[1])

      I also print each field in the struct using the same casting method
      inside of a printf.

      The problem is that I seem to only be getting the timestamp and no
      other info. I checked the return of the "recv" at the socket level
      and am only getting 4 bytes of data. I also went back into the
      Controller GUI (after resetting the AIBO) and checked to see if the
      WSS is running at startup, which it is. Is there anything I am
      missing to get the entire data stream?
      BTW, I do sent the "connection request" per our camera server
      converstation a while back.
    • Ethan Tira-Thompson
      ... I m not sure that would compile... I think you mean: ((AIBOWorldSerializerData*) streamdata)- SensorData[1] (no need to cast to int at the end, note
      Message 2 of 29 , Sep 1, 2005
      • 0 Attachment
        > Then I pull out the FarIR data (second index of sensor data array):
        >
        > (int)((AIBOWorldSerializerData) *streamdata)->SensorData[1])
        I'm not sure that would compile... I think you mean:
        ((AIBOWorldSerializerData*) streamdata)->SensorData[1]
        (no need to cast to int at the end, note casting pointer itself
        instead of casting value after dereference of pointer)

        I'd like to see the code for the call to recv I guess... I have a
        feeling you're doing something like:
        recv(socket, streamdata, sizeof(streamdata), 0)
        which will only read 4 bytes at a time because streamdata is a
        pointer...
        This would fix it:
        recv(socket, streamdata, sizeof(AIBOWorldSerializerData), 0)

        But perhaps it's better to avoid this entirely and do something like
        this:
        AIBOWorldSerializerData data;
        int n=recv(socket,&data,sizeof(data),0);
        if(n!=sizeof(data)) { /*err msg */ }
        cout << data.SensorData[1] << endl;
        which avoids the need for casting...

        -ethan
      • Crews Carrie D 1stLt AFIT/ENG
        THX Ethan. Can I load a posture in the Config.h or in a start behavior so it will stand up on boot up? _____ From: tekkotsu_dev@yahoogroups.com
        Message 3 of 29 , Sep 2, 2005
        • 0 Attachment
          THX Ethan.  Can I load a posture in the Config.h or in a start behavior so it will stand up on boot up?


          From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
          Sent: Thursday, September 01, 2005 1:27 PM
          To: tekkotsu_dev@yahoogroups.com
          Subject: Re: [tekkotsu_dev] WorldStateSerializer

          > Then I pull out the FarIR data (second index of sensor data
          array):
          >
          > (int)((AIBOWorldSerializerData)
          *streamdata)->SensorData[1])
          I'm not sure that would compile... I think you mean:
             ((AIBOWorldSerializerData*) streamdata)->SensorData[1]
          (no need to cast to int at the end, note casting pointer itself 
          instead of casting value after dereference of  pointer)

          I'd like to see the code for the call to recv I guess... I have a 
          feeling you're doing something like:
             recv(socket, streamdata, sizeof(streamdata), 0)
          which will only read 4 bytes at a time because streamdata is a 
          pointer...
          This would fix it:
             recv(socket, streamdata, sizeof(AIBOWorldSerializerData), 0)

          But perhaps it's better to avoid this entirely and do something like 
          this:
             AIBOWorldSerializerData data;
             int n=recv(socket,&data,sizeof(data),0);
             if(n!=sizeof(data)) { /*err msg */ }
             cout << data.SensorData[1] << endl;
          which avoids the need for casting...

          -ethan

        • Julien Roux
          Hi I m currently programming a new behavior using statenode on an aibo ers7. My problem is when I m compiling. The only error i receive is: make: ***
          Message 4 of 29 , Sep 6, 2005
          • 0 Attachment
            Hi

            I'm currently programming a new behavior using
            statenode on an aibo ers7.

            My problem is when I'm compiling. The only error i
            receive is:
            make: ***
            [build/PLATFORM_APERIOS/TGT_ERS7/JRGotoNode.o]Error 1

            it doesn't give me the line where the error is and
            sometimes, the error is included in another file
            included. Anybody has an idea?

            thanks


            ____________________________________________________________________________________

            Julien ROUX
            Msc Distributed & Multimedia Information Systems
            Heriot Watt University - Edinburgh
            Mobile: (+44) 0 79 79 21 21 02
            Tel: (+44) 0 131 229 83 64
            MSN: bibus2@...
            Skype: roujul







            ___________________________________________________________________________
            Appel audio GRATUIT partout dans le monde avec le nouveau Yahoo! Messenger
            Téléchargez cette version sur http://fr.messenger.yahoo.com
          • Ethan Tira-Thompson
            ... There s nothing in Config to load a behavior at startup, but you can do this yourself from within your project s StartupBehavior. The easiest way would be
            Message 5 of 29 , Sep 6, 2005
            • 0 Attachment
              THX Ethan.  Can I load a posture in the Config.h or in a start behavior so it will stand up on boot up?
              There's nothing in Config to load a behavior at startup, but you can do this yourself from within your project's StartupBehavior.
              The easiest way would be for StartupBehavior to add a simple MotionSequenceMC moving to your desired posture with some controlled delay so it doesn't just "snap" into position.  You could also use a PostureMC with some reasonably leisurely max speed given.
              There's some other code in project/StartupBehavior.cc that should give you some idea how to proceed.  In particular, look at the code for closing the mouth at boot.

              -ethan
            • Crews Carrie D 1stLt AFIT/ENG
              I used the MotionSequenceMC, and it stands. The problem is that when I give the command to walk (providing the f and an integer value to mirror what happens
              Message 6 of 29 , Sep 6, 2005
              • 0 Attachment
                I used the MotionSequenceMC, and it stands.  The problem is that when I give the command to walk (providing the "f" and an integer value to mirror what happens in your WalkController), nothing happens.  I think there is a conflict....like I am asking the robot to do two things at the same time.


                From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
                Sent: Tuesday, September 06, 2005 2:45 PM
                To: tekkotsu_dev@yahoogroups.com
                Subject: Re: [tekkotsu_dev] WorldStateSerializer

                THX Ethan.  Can I load a posture in the Config.h or in a start behavior so it will stand up on boot up?
                There's nothing in Config to load a behavior at startup, but you can do this yourself from within your project's StartupBehavior.
                The easiest way would be for StartupBehavior to add a simple MotionSequenceMC moving to your desired posture with some controlled delay so it doesn't just "snap" into position.  You could also use a PostureMC with some reasonably leisurely max speed given.
                There's some other code in project/StartupBehavior.cc that should give you some idea how to proceed.  In particular, look at the code for closing the mouth at boot.

                -ethan
              • Ethan Tira-Thompson
                try checking build/PLATFORM_APERIOS/TGT_ERS7/JRGotoNode.log, particularly towards the end of the file -- warnings regarding system files are filtered out of
                Message 7 of 29 , Sep 6, 2005
                • 0 Attachment
                  try checking build/PLATFORM_APERIOS/TGT_ERS7/JRGotoNode.log,
                  particularly towards the end of the file -- warnings regarding system
                  files are filtered out of the console display, but the original
                  output is stored in that log file. Perhaps there's a bug in the
                  system warning filtering (that would be suprising though, we haven't
                  been having trouble with that aside from some occasional confusion
                  regarding which files are including each other.)

                  It's also possible there's an error message buried in other output --
                  linker errors tend to be disguised by the load of garbage gcc spews
                  when its linker has trouble. Feel free to send me a copy of your
                  entire build log if you're not sure.

                  -ethan
                • Ethan Tira-Thompson
                  ... There s a well defined order to resolving joint conflicts. First the MotionManager goes by priority level of the MotionCommands which have supplied a
                  Message 8 of 29 , Sep 6, 2005
                  • 0 Attachment
                    I used the MotionSequenceMC, and it stands.  The problem is that when I give the command to walk (providing the "f" and an integer value to mirror what happens in your WalkController), nothing happens.  I think there is a conflict....like I am asking the robot to do two things at the same time.
                    There's a well defined order to resolving joint conflicts.  First the MotionManager goes by priority level of the MotionCommands which have supplied a value with a non-zero weight for a joint.  A higher priority level (e.g. emergency stop) completely overrides a lower level.
                    If conflicts remain within the topmost priority level, then a weighted average is performed between the joint angle requests.

                    So, if it's a simple matter of a MotionSequence holding a posture, and trying to walk, you would see a "muted" walk, where the joints are averaged between the walk's commands and the posture.  Unless you previously were successfully commanding the walk, I would assume this means that the walking commands aren't being received or processed for some reason.  Try adding some cout's to see what's going on.  (also, can try adding a timer for the time of the motion sequence, and explicitly remove it if you think it isn't autopruning for some reason.)

                    -ethan


                  • Crews Carrie D 1stLt AFIT/ENG
                    The walk command was working before I added the behavior to make the robot stand up. We did use the timer for the motion sequence, but I guess we didn t scale
                    Message 9 of 29 , Sep 6, 2005
                    • 0 Attachment
                      The walk command was working before I added the behavior to make the robot stand up.  We did use the timer for the motion sequence, but I guess we didn't scale it down to a short enough time (ms).  I may work on it some more later in the week.
                       
                      I have another question(networking with image data).  I have successfully read in the data I need from the AIBO.  I have restricted the number of frames I read in (for right now), and close the socket after 17 frames.  I cannot reconnect though, without rebooting the AIBO.  I am sure this is due the fact that the AIBO is still sending me the information. I connect the ControllerGUI/RawCam and get an error because it tries to close the window since the server is already running.  But when I click it the second time, it reestablishes the connection.   How do I tell the server (AIBO) its free to register other listeners on that port so that I may reestablish the connection without rebooting. 


                      From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
                      Sent: Tuesday, September 06, 2005 3:26 PM
                      To: tekkotsu_dev@yahoogroups.com
                      Subject: Re: [tekkotsu_dev] WorldStateSerializer

                      I used the MotionSequenceMC, and it stands.  The problem is that when I give the command to walk (providing the "f" and an integer value to mirror what happens in your WalkController), nothing happens.  I think there is a conflict....like I am asking the robot to do two things at the same time.
                      There's a well defined order to resolving joint conflicts.  First the MotionManager goes by priority level of the MotionCommands which have supplied a value with a non-zero weight for a joint.  A higher priority level (e.g. emergency stop) completely overrides a lower level.
                      If conflicts remain within the topmost priority level, then a weighted average is performed between the joint angle requests.

                      So, if it's a simple matter of a MotionSequence holding a posture, and trying to walk, you would see a "muted" walk, where the joints are averaged between the walk's commands and the posture.  Unless you previously were successfully commanding the walk, I would assume this means that the walking commands aren't being received or processed for some reason.  Try adding some cout's to see what's going on.  (also, can try adding a timer for the time of the motion sequence, and explicitly remove it if you think it isn't autopruning for some reason.)

                      -ethan


                    • Ethan Tira-Thompson
                      ... It should be a matter of calling close() on the desktop side so the AIBO will get notification that the client has shut down, and thus the AIBO should
                      Message 10 of 29 , Sep 6, 2005
                      • 0 Attachment
                        How do I tell the server (AIBO) its free to register other listeners on that port so that I may reestablish the connection without rebooting. 
                        It should be a matter of calling close() on the desktop side so the AIBO will get notification that the client has shut down, and thus the AIBO should start listening for a new client.

                        Or at least, that's what happens with TCP -- since UDP is connectionless, I don't think the AIBO gets any notification when the client closes, but it *should* get a notice when the next packet it sends is refused because the client is gone, which should also mark the Socket to re-listen.  Perhaps I'm mistaken about this?  (This may be a firewall thing that silently drops bad packets to prevent port scans?  In that case the camera stream wouldn't get any feedback the socket had been closed.)

                        If that's not working, we'll have to add a "close" command to the protocol so UDP clients can explicitly declare when they are shutting down.

                        -ethan

                      • Crews Carrie D 1stLt AFIT/ENG
                        I have a UDP connection established, and collect data inside a finite while loop, then close the socket. If I try to run the program again on the two camera
                        Message 11 of 29 , Sep 7, 2005
                        • 0 Attachment
                          I have a UDP connection established, and collect data inside a finite while loop, then close the socket.  If I try to run the program again on the two camera ports, I don't get a connection and have to reboot the AIBO.  I'll look in your code to see how the wireless class handles UDP connections.

                          From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
                          Sent: Tuesday, September 06, 2005 4:29 PM
                          To: tekkotsu_dev@yahoogroups.com
                          Subject: Re: [tekkotsu_dev] WorldStateSerializer

                          How do I tell the server (AIBO) its free to register other listeners on that port so that I may reestablish the connection without rebooting. 
                          It should be a matter of calling close() on the desktop side so the AIBO will get notification that the client has shut down, and thus the AIBO should start listening for a new client.

                          Or at least, that's what happens with TCP -- since UDP is connectionless, I don't think the AIBO gets any notification when the client closes, but it *should* get a notice when the next packet it sends is refused because the client is gone, which should also mark the Socket to re-listen.  Perhaps I'm mistaken about this?  (This may be a firewall thing that silently drops bad packets to prevent port scans?  In that case the camera stream wouldn't get any feedback the socket had been closed.)

                          If that's not working, we'll have to add a "close" command to the protocol so UDP clients can explicitly declare when they are shutting down.

                          -ethan

                        • Crews Carrie D 1stLt AFIT/ENG
                          I m gonna try using a TCP socket instead and see if it makes a difference. Another topic: When I checked the incoming RawCam data stream, I get a JPEGColor
                          Message 12 of 29 , Sep 7, 2005
                          • 0 Attachment
                            I'm gonna try using a TCP socket instead and see if it makes a difference. 
                             
                            Another topic:  When I checked the incoming RawCam data stream, I get a "JPEGColor" string in the FBK Generator-specific header instead of "RawImage".  I still get encode and compression as being ENCODECOLOR and COMPRESS_NONE.  Is there a reason that I am missing?


                            From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
                            Sent: Tuesday, September 06, 2005 4:29 PM
                            To: tekkotsu_dev@yahoogroups.com
                            Subject: Re: [tekkotsu_dev] WorldStateSerializer

                            How do I tell the server (AIBO) its free to register other listeners on that port so that I may reestablish the connection without rebooting. 
                            It should be a matter of calling close() on the desktop side so the AIBO will get notification that the client has shut down, and thus the AIBO should start listening for a new client.

                            Or at least, that's what happens with TCP -- since UDP is connectionless, I don't think the AIBO gets any notification when the client closes, but it *should* get a notice when the next packet it sends is refused because the client is gone, which should also mark the Socket to re-listen.  Perhaps I'm mistaken about this?  (This may be a firewall thing that silently drops bad packets to prevent port scans?  In that case the camera stream wouldn't get any feedback the socket had been closed.)

                            If that's not working, we'll have to add a "close" command to the protocol so UDP clients can explicitly declare when they are shutting down.

                            -ethan

                          • Ethan Tira-Thompson
                            ... I confirmed what you re seeing using the new Echo Client/Server (under TekkotsuMon)... UDP ports stay open even when their packets are being refused
                            Message 13 of 29 , Sep 7, 2005
                            • 0 Attachment
                              Crews Carrie D 1stLt AFIT/ENG wrote:
                              I have a UDP connection established, and collect data inside a finite while loop, then close the socket.  If I try to run the program again on the two camera ports, I don't get a connection and have to reboot the AIBO.  I'll look in your code to see how the wireless class handles UDP connections.
                              I confirmed what you're seeing using the new "Echo Client/Server" (under TekkotsuMon)... UDP ports stay open even when their packets are being refused because the client is closed.  I'm not sure if that's something we can fix (might be a system limitation that it doesn't tell us when packets bounce) but I'll look into it.
                                http://bugs.tekkotsu.org/show_bug.cgi?id=188

                              In the mean time, it looks like you will have to restart the camera servers after each connection (or use TCP).  You could automate the restarts with a script, or by connecting to the ControllerGUI port and sending the appropriate commands, e.g.:
                                !select "#Raw Cam Server" ; !select "#Seg Cam Server"
                                !select "Raw Cam Server" ; !select "Seg Cam Server"
                              (The first line shuts down the servers if they are already running, the second starts them up again)
                              The only trick with scripts is that the ';' token must be its own "word" (surrounded by whitespace), otherwise it is taken as part of an argument and not interpreted to separate commands.  You can also separate commands with a newline.
                              (thanks again to Doug Blank for adding argument support to the !select command, used above)

                              -ethan
                            • Ethan Tira-Thompson
                              ... Hmm, ENCODE_COLOR makes sense for JPEGColor, but I don t see how a JPEG could be sent if Config::vision_config::rawcam_compression==COMPRESS_NONE... there
                              Message 14 of 29 , Sep 7, 2005
                              • 0 Attachment

                                Another topic:  When I checked the incoming RawCam data stream, I get a "JPEGColor" string in the FBK Generator-specific header instead of "RawImage".  I still get encode and compression as being ENCODECOLOR and COMPRESS_NONE.  Is there a reason that I am missing?
                                Hmm, ENCODE_COLOR makes sense for JPEGColor, but I don't see how a JPEG could be sent if Config::vision_config::rawcam_compression==COMPRESS_NONE... there are three places in RawCamBehavior where a JPEG could be sent, and each of them is wrapped by an if() which checks rawcam_compression.

                                So you've stumped me... perhaps there's something funny about the way the vision configuration variables are being set?  Perhaps you're seeing lag between setting a value and getting packets back which were produced after the value was set?  But even then, I don't see how it's possible to get a JPEGColor image in a packet marked COMPRESS_NONE...

                                -ethan

                              • Crews Carrie D 1stLt AFIT/ENG
                                Well, it could be bad info on my part too. Right now, I read those 4 bytes that encode the enum values into a temp[], then do an htonl(atoi(temp)). I do this
                                Message 15 of 29 , Sep 8, 2005
                                • 0 Attachment
                                  Well, it could be bad info on my part too.  Right now, I read those 4 bytes that encode the enum values into a temp[], then do an htonl(atoi(temp)).  I do this with bits 18-21 and 22-25, each resulting in being a zero.  I pull the data from 10011 and 10012, getting "RLE Image" from 10012 and "JPEGImage" from 10011.  The other two strings "TekkotsuImage" and "FBKImage" are accurate.  I run the recv() about 17 times and the values don't change.  Should I run the loop longer to see if I get the "RawImage" or see if the enum data changes? 

                                  From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
                                  Sent: Wednesday, September 07, 2005 3:53 PM
                                  To: tekkotsu_dev@yahoogroups.com
                                  Subject: Re: [tekkotsu_dev] WorldStateSerializer


                                  Another topic:  When I checked the incoming RawCam data stream, I get a "JPEGColor" string in the FBK Generator-specific header instead of "RawImage".  I still get encode and compression as being ENCODECOLOR and COMPRESS_NONE.  Is there a reason that I am missing?
                                  Hmm, ENCODE_COLOR makes sense for JPEGColor, but I don't see how a JPEG could be sent if Config::vision_config::rawcam_compression==COMPRESS_NONE... there are three places in RawCamBehavior where a JPEG could be sent, and each of them is wrapped by an if() which checks rawcam_compression.

                                  So you've stumped me... perhaps there's something funny about the way the vision configuration variables are being set?  Perhaps you're seeing lag between setting a value and getting packets back which were produced after the value was set?  But even then, I don't see how it's possible to get a JPEGColor image in a packet marked COMPRESS_NONE...

                                  -ethan

                                • Ethan Tira-Thompson
                                  ... Whoa! Let s look at the data format for the beginning of the header. I ll list the field s type, and then name the field in paranthesis, separating each
                                  Message 16 of 29 , Sep 8, 2005
                                  • 0 Attachment
                                    Well, it could be bad info on my part too.  Right now, I read those 4 bytes that encode the enum values into a temp[], then do an htonl(atoi(temp)).  I do this with bits 18-21 and 22-25, each resulting in being a zero.
                                    Whoa!  Let's look at the data format for the beginning of the header.
                                    I'll list the field's type, and then name the field in paranthesis, separating each field with a '|'
                                    Literal characters will be single quoted (')
                                    Literal strings will be double quoted (")

                                    * All strings are encoded as such:
                                      int (n) | char[n] (str) | '\0'
                                    (from http://www.tekkotsu.org/dox/classLoadSave.html)

                                    * RawCamBehavior packet header:
                                      "TekkotsuImage" | int (encoding) | int (compression) |
                                        unsigned int (width) | unsigned int (height) |
                                        unsigned int (timestamp) | unsigned int (framenumber)
                                        | generator::SaveBuffer()...
                                    (from http://www.tekkotsu.org/dox/classRawCamBehavior.html)

                                    All of these fields are binary.  The only strings are the creator strings.  But everything else, including the enums for encoding and compression, is a binary value, in the Aibo's byte order (little endian).  This means on a PC, you can read these as is. (big endian platforms just need to byte swap)

                                    The operation you're doing, htonl(atoi(temp)) is going to try to interpret the binary value in temp as an ascii string (bad), parse that to an integer (probably returns 0), and then convert that value to network byte order (which i suspect isn't actually what you want, but depends what you're using it for).
                                    All you need to do for the binary fields (assuming a little-endian platform) is cast temp to an int: (int)(*temp), or better yet, read into the value directly:
                                      int encoding; recv(sock,&encoding,sizeof(encoding),0);

                                    Personally, I'd recommend using our LoadSave class, which was what did the original encoding, and provides matching decoding functions for you (including byte swapping when necessary, which the previous sample is ignoring).
                                    Here's how I would do it (if for some reason I didn't just want to use the Tekkotsu classes' own LoadBuffer()):
                                      //for error reporting/handling:
                                      class bad_format : public std::exception {
                                      public:
                                        explicit bad_format(const std::string& m) throw() : std::exception(), msg(msg) {}
                                       
                                    virtual ~bad_format() throw() {}
                                        virtual const char * what() const throw() { return msg.c_str(); }
                                      protected:
                                       
                                    std::string msg; //!< message regarding the type of error
                                      };

                                      //templated function for easy field decoding (uses LoadSave::decode for actual work)
                                      template<
                                    class T>
                                      void decode(T& data, char*& buf, unsigned int& len, const char* fieldName) {
                                       
                                    int used=LoadSave::decode(data,buf,len);
                                        if(used==0)
                                    throw bad_format(std::string("Failed decoding ")+fieldName);
                                        buf+=used; len-=used;
                                      }

                                      //field list:
                                      std::string typeStr;
                                      int encoding,compression; // etc...

                                      //go to town:
                                      void parse(char* buf, unsigned int len) {
                                        decode(typeStr,buf,len,"creator string");
                                        decode(encoding,buf,len,
                                    "encoding");
                                        decode(compression,buf,len,
                                    "compression");
                                        // etc...
                                      }

                                    Of course, to soup this up even more, you could actually check the typeStr is the correct value (e.g. "TekkotsuImage"), and that len doesn't run out (in which case you need to recv more data -- only a problem for TCP, with UDP you can guarantee each image fits in a single packet, and the maximum packet size is 64KB).

                                    -ethan

                                  • Crews Carrie D 1stLt AFIT/ENG
                                    Yeah, I figured out that I wasn t dealing with the binary data (for integers) correctly. What I have now (directly casting a character into an integer) will
                                    Message 17 of 29 , Sep 8, 2005
                                    • 0 Attachment
                                      Yeah, I figured out that I wasn't dealing with the binary data (for integers)  correctly.  What I have now (directly casting a character into an integer) will work fine for one byte, but if the value is more than one byte long....not so much.  My string conversions work fine.  I'm only having problems with the chunks of the buffer (char[]) being converted to integer values.


                                      From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
                                      Sent: Thursday, September 08, 2005 2:22 PM
                                      To: tekkotsu_dev@yahoogroups.com
                                      Subject: Re: [tekkotsu_dev] WorldStateSerializer

                                      Well, it could be bad info on my part too.  Right now, I read those 4 bytes that encode the enum values into a temp[], then do an htonl(atoi(temp)).  I do this with bits 18-21 and 22-25, each resulting in being a zero.
                                      Whoa!  Let's look at the data format for the beginning of the header.
                                      I'll list the field's type, and then name the field in paranthesis, separating each field with a '|'
                                      Literal characters will be single quoted (')
                                      Literal strings will be double quoted (")

                                      * All strings are encoded as such:
                                        int (n) | char[n] (str) | '\0'
                                      (from http://www.tekkotsu.org/dox/classLoadSave.html)

                                      * RawCamBehavior packet header:
                                        "TekkotsuImage" | int (encoding) | int (compression) |
                                          unsigned int (width) | unsigned int (height) |
                                          unsigned int (timestamp) | unsigned int (framenumber)
                                          | generator::SaveBuffer()...
                                      (from http://www.tekkotsu.org/dox/classRawCamBehavior.html)

                                      All of these fields are binary.  The only strings are the creator strings.  But everything else, including the enums for encoding and compression, is a binary value, in the Aibo's byte order (little endian).  This means on a PC, you can read these as is. (big endian platforms just need to byte swap)

                                      The operation you're doing, htonl(atoi(temp)) is going to try to interpret the binary value in temp as an ascii string (bad), parse that to an integer (probably returns 0), and then convert that value to network byte order (which i suspect isn't actually what you want, but depends what you're using it for).
                                      All you need to do for the binary fields (assuming a little-endian platform) is cast temp to an int: (int)(*temp), or better yet, read into the value directly:
                                        int encoding; recv(sock,&encoding,sizeof(encoding),0);

                                      Personally, I'd recommend using our LoadSave class, which was what did the original encoding, and provides matching decoding functions for you (including byte swapping when necessary, which the previous sample is ignoring).
                                      Here's how I would do it (if for some reason I didn't just want to use the Tekkotsu classes' own LoadBuffer()):
                                        //for error reporting/handling:
                                        class bad_format : public std::exception {
                                        public:
                                          explicit bad_format(const std::string& m) throw() : std::exception(), msg(msg) {}
                                         
                                      virtual ~bad_format() throw() {}
                                          virtual const char * what() const throw() { return msg.c_str(); }
                                        protected:
                                         
                                      std::string msg; //!< message regarding the type of error
                                        };

                                        //templated function for easy field decoding (uses LoadSave::decode for actual work)
                                        template<
                                      class T>
                                        void decode(T& data, char*& buf, unsigned int& len, const char* fieldName) {
                                         
                                      int used=LoadSave::decode(data,buf,len);
                                          if(used==0)
                                      throw bad_format(std::string("Failed decoding ")+fieldName);
                                          buf+=used; len-=used;
                                        }

                                        //field list:
                                        std::string typeStr;
                                        int encoding,compression; // etc...

                                        //go to town:
                                        void parse(char* buf, unsigned int len) {
                                          decode(typeStr,buf,len,"creator string");
                                          decode(encoding,buf,len,
                                      "encoding");
                                          decode(compression,buf,len,
                                      "compression");
                                          // etc...
                                        }

                                      Of course, to soup this up even more, you could actually check the typeStr is the correct value (e.g. "TekkotsuImage"), and that len doesn't run out (in which case you need to recv more data -- only a problem for TCP, with UDP you can guarantee each image fits in a single packet, and the maximum packet size is 64KB).

                                      -ethan

                                    • Crews Carrie D 1stLt AFIT/ENG
                                      What you sent below (LoadBuffer) is in essence what I m doing( but a little less elegant). I have a decodeInt( since all integers are 4 bytes) which will byte
                                      Message 18 of 29 , Sep 8, 2005
                                      • 0 Attachment
                                        What you sent below (LoadBuffer) is in essence what I'm doing( but a little less elegant).  I have a decodeInt( since all integers are 4 bytes) which will byte swap and store in a struct (holding all fields of buffer)  and decodeString method (that parses until the '\0' and stores in the cooresponding struct field) that is called from a parseBuffer(which gets the buffer and flag for the image type).  When I get the integer conversion working, I will have a struct containing the raw image data and another having the segmented image data.  When I begin the image processing, all I will need to do is pull the desired info from the struct. 


                                        From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
                                        Sent: Thursday, September 08, 2005 2:22 PM
                                        To: tekkotsu_dev@yahoogroups.com
                                        Subject: Re: [tekkotsu_dev] WorldStateSerializer

                                        Well, it could be bad info on my part too.  Right now, I read those 4 bytes that encode the enum values into a temp[], then do an htonl(atoi(temp)).  I do this with bits 18-21 and 22-25, each resulting in being a zero.
                                        Whoa!  Let's look at the data format for the beginning of the header.
                                        I'll list the field's type, and then name the field in paranthesis, separating each field with a '|'
                                        Literal characters will be single quoted (')
                                        Literal strings will be double quoted (")

                                        * All strings are encoded as such:
                                          int (n) | char[n] (str) | '\0'
                                        (from http://www.tekkotsu.org/dox/classLoadSave.html)

                                        * RawCamBehavior packet header:
                                          "TekkotsuImage" | int (encoding) | int (compression) |
                                            unsigned int (width) | unsigned int (height) |
                                            unsigned int (timestamp) | unsigned int (framenumber)
                                            | generator::SaveBuffer()...
                                        (from http://www.tekkotsu.org/dox/classRawCamBehavior.html)

                                        All of these fields are binary.  The only strings are the creator strings.  But everything else, including the enums for encoding and compression, is a binary value, in the Aibo's byte order (little endian).  This means on a PC, you can read these as is. (big endian platforms just need to byte swap)

                                        The operation you're doing, htonl(atoi(temp)) is going to try to interpret the binary value in temp as an ascii string (bad), parse that to an integer (probably returns 0), and then convert that value to network byte order (which i suspect isn't actually what you want, but depends what you're using it for).
                                        All you need to do for the binary fields (assuming a little-endian platform) is cast temp to an int: (int)(*temp), or better yet, read into the value directly:
                                          int encoding; recv(sock,&encoding,sizeof(encoding),0);

                                        Personally, I'd recommend using our LoadSave class, which was what did the original encoding, and provides matching decoding functions for you (including byte swapping when necessary, which the previous sample is ignoring).
                                        Here's how I would do it (if for some reason I didn't just want to use the Tekkotsu classes' own LoadBuffer()):
                                          //for error reporting/handling:
                                          class bad_format : public std::exception {
                                          public:
                                            explicit bad_format(const std::string& m) throw() : std::exception(), msg(msg) {}
                                           
                                        virtual ~bad_format() throw() {}
                                            virtual const char * what() const throw() { return msg.c_str(); }
                                          protected:
                                           
                                        std::string msg; //!< message regarding the type of error
                                          };

                                          //templated function for easy field decoding (uses LoadSave::decode for actual work)
                                          template<
                                        class T>
                                          void decode(T& data, char*& buf, unsigned int& len, const char* fieldName) {
                                           
                                        int used=LoadSave::decode(data,buf,len);
                                            if(used==0)
                                        throw bad_format(std::string("Failed decoding ")+fieldName);
                                            buf+=used; len-=used;
                                          }

                                          //field list:
                                          std::string typeStr;
                                          int encoding,compression; // etc...

                                          //go to town:
                                          void parse(char* buf, unsigned int len) {
                                            decode(typeStr,buf,len,"creator string");
                                            decode(encoding,buf,len,
                                        "encoding");
                                            decode(compression,buf,len,
                                        "compression");
                                            // etc...
                                          }

                                        Of course, to soup this up even more, you could actually check the typeStr is the correct value (e.g. "TekkotsuImage"), and that len doesn't run out (in which case you need to recv more data -- only a problem for TCP, with UDP you can guarantee each image fits in a single packet, and the maximum packet size is 64KB).

                                        -ethan

                                      • Ethan Tira-Thompson
                                        ... Oops, I have a mistake in my casting example. int encoding=*(int*)temp; or to be a little fancier: int encoding=*reinterpret_cast (temp); //but not
                                        Message 19 of 29 , Sep 8, 2005
                                        • 0 Attachment
                                          Crews Carrie D 1stLt AFIT/ENG wrote:

                                          > Yeah, I figured out that I wasn't dealing with the binary data (for
                                          > integers) correctly. What I have now (directly casting a character
                                          > into an integer) will work fine for one byte, but if the value is more
                                          > than one byte long....not so much. My string conversions work fine.
                                          > I'm only having problems with the chunks of the buffer (char[]) being
                                          > converted to integer values.

                                          Oops, I have a mistake in my casting example.
                                          int encoding=*(int*)temp;
                                          or to be a little fancier:
                                          int encoding=*reinterpret_cast<int*>(temp);
                                          //but not this: int encoding=(int)(*temp)

                                          -ethan
                                        • Crews Carrie D 1stLt AFIT/ENG
                                          I was wrong, the config::rawcam_compression matches the JPEGColor. I still don t know why I m not getting RawImages . _____ From:
                                          Message 20 of 29 , Sep 12, 2005
                                          • 0 Attachment
                                            I was wrong, the config::rawcam_compression matches the JPEGColor.  I still don't know why I'm not getting "RawImages".


                                            From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
                                            Sent: Wednesday, September 07, 2005 3:53 PM
                                            To: tekkotsu_dev@yahoogroups.com
                                            Subject: Re: [tekkotsu_dev] WorldStateSerializer


                                            Another topic:  When I checked the incoming RawCam data stream, I get a "JPEGColor" string in the FBK Generator-specific header instead of "RawImage".  I still get encode and compression as being ENCODECOLOR and COMPRESS_NONE.  Is there a reason that I am missing?
                                            Hmm, ENCODE_COLOR makes sense for JPEGColor, but I don't see how a JPEG could be sent if Config::vision_config::rawcam_compression==COMPRESS_NONE... there are three places in RawCamBehavior where a JPEG could be sent, and each of them is wrapped by an if() which checks rawcam_compression.

                                            So you've stumped me... perhaps there's something funny about the way the vision configuration variables are being set?  Perhaps you're seeing lag between setting a value and getting packets back which were produced after the value was set?  But even then, I don't see how it's possible to get a JPEGColor image in a packet marked COMPRESS_NONE...

                                            -ethan

                                          • Ethan Tira-Thompson
                                            ... Well, that s good news. You re getting jpeg images because config- ... RawImages, it needs to be set to COMPRESS_NONE. You can do this either at run time
                                            Message 21 of 29 , Sep 12, 2005
                                            • 0 Attachment
                                              On Sep 12, 2005, at 11:43 AM, Crews Carrie D 1stLt AFIT/ENG wrote:
                                              I was wrong, the config::rawcam_compression matches the JPEGColor.  I still don't know why I'm not getting "RawImages".

                                              Well, that's good news.  You're getting jpeg images because config->vision.rawcam_compression is set to COMPRESS_JPEG.  If you want RawImages, it needs to be set to COMPRESS_NONE.  You can do this either at run time (!set vision.rawcam_compression=none at the ControllerGUI input field) or every time from the 'ms/config/tekkotsu.cfg' file.  If you've already set the config file, double check the syntax -- the default setting is 'jpeg', so if the setting used is unrecognized (like a typo in the value), then the system will fall back to jpeg.

                                              -ethan

                                            • Crews Carrie D 1stLt AFIT/ENG
                                              Ok, will do. To use the command port, do I still need to send connection request to the server, then just send the !set vision...... ) in a character
                                              Message 22 of 29 , Sep 12, 2005
                                              • 0 Attachment
                                                Ok, will do.  To use the command port, do I still need to send "connection request" to the server, then just send the !set vision......" ) in a character buffer to the server.


                                                From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
                                                Sent: Monday, September 12, 2005 12:12 PM
                                                To: tekkotsu_dev@yahoogroups.com
                                                Subject: Re: [tekkotsu_dev] WorldStateSerializer

                                                On Sep 12, 2005, at 11:43 AM, Crews Carrie D 1stLt AFIT/ENG wrote:
                                                I was wrong, the config::rawcam_compression matches the JPEGColor.  I still don't know why I'm not getting "RawImages".

                                                Well, that's good news.  You're getting jpeg images because config->vision.rawcam_compression is set to COMPRESS_JPEG.  If you want RawImages, it needs to be set to COMPRESS_NONE.  You can do this either at run time (!set vision.rawcam_compression=none at the ControllerGUI input field) or every time from the 'ms/config/tekkotsu.cfg' file.  If you've already set the config file, double check the syntax -- the default setting is 'jpeg', so if the setting used is unrecognized (like a typo in the value), then the system will fall back to jpeg.

                                                -ethan

                                              • Ethan Tira-Thompson
                                                ... You only need the connection request thing with UDP -- TCP handles connection setup/teardown for you. But otherwise, yeah. -ethan
                                                Message 23 of 29 , Sep 12, 2005
                                                • 0 Attachment
                                                  On Sep 12, 2005, at 12:19 PM, Crews Carrie D 1stLt AFIT/ENG wrote:
                                                  Ok, will do.  To use the command port, do I still need to send "connection request" to the server, then just send the !set vision......" ) in a character buffer to the server.
                                                  You only need the "connection request" thing with UDP -- TCP handles connection setup/teardown for you.  But otherwise, yeah.

                                                  -ethan

                                                • Crews Carrie D 1stLt AFIT/ENG
                                                  I have a question about the image data being sent. I understand that the raw data isn t compressed, but the number representation should still be between 0
                                                  Message 24 of 29 , Sep 13, 2005
                                                  • 0 Attachment
                                                    I have a question about the image data being sent.  I understand that the raw data isn't compressed, but the number representation should still be between 0 and 255 for each pixel, correct?  I've not worked with YUV before, so the numbers I am getting are large(integers), some are even negative(segmented).  Is there a good class on the java side that can tell me how to use the image data to reconstruct the colors?


                                                    From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
                                                    Sent: Monday, September 12, 2005 12:12 PM
                                                    To: tekkotsu_dev@yahoogroups.com
                                                    Subject: Re: [tekkotsu_dev] WorldStateSerializer

                                                    On Sep 12, 2005, at 11:43 AM, Crews Carrie D 1stLt AFIT/ENG wrote:
                                                    I was wrong, the config::rawcam_compression matches the JPEGColor.  I still don't know why I'm not getting "RawImages".

                                                    Well, that's good news.  You're getting jpeg images because config->vision.rawcam_compression is set to COMPRESS_JPEG.  If you want RawImages, it needs to be set to COMPRESS_NONE.  You can do this either at run time (!set vision.rawcam_compression=none at the ControllerGUI input field) or every time from the 'ms/config/tekkotsu.cfg' file.  If you've already set the config file, double check the syntax -- the default setting is 'jpeg', so if the setting used is unrecognized (like a typo in the value), then the system will fall back to jpeg.

                                                    -ethan

                                                  • Ethan Tira-Thompson
                                                    ... Correct. ... YUV is similar to RGB -- it s only an affine transformation away. What that means is that if you take RGB color space and rotate and stretch
                                                    Message 25 of 29 , Sep 13, 2005
                                                    • 0 Attachment
                                                      On Sep 13, 2005, at 10:06 AM, Crews Carrie D 1stLt AFIT/ENG wrote:
                                                      I have a question about the image data being sent.  I understand that the raw data isn't compressed, but the number representation should still be between 0 and 255 for each pixel, correct?
                                                      Correct.

                                                      I've not worked with YUV before, so the numbers I am getting are large(integers), some are even negative(segmented).
                                                      YUV is similar to RGB -- it's only an affine transformation away.  What that means is that if you take RGB color space and rotate and stretch it in a linear way, you can convert it to YUV.  The practical summary is that the Y channel represents the image brightness -- how much light is coming from any given point in the scene.  The U and V channels (also known as Cr and Cb, though I forget which is which) store color information.  It's useful to play with !set vision.rawcam_encoding={y_only,u_only,v_only,uv_only} to get a feel for the contribution of each channel.

                                                      So, interpretation is much the same as an RGB image would be.  Each pixel is three bytes, Y, U, and V respectively.  Y is unsigned, U and V are signed values, but stored as unsigned (not my idea).  So this means their values hover around 128.

                                                      Remember, each value is a single *byte*.  Do not read int's.  Use unsigned chars.  The camera data is "packed", so reading an int at a time would grab an extra sample from the following pixel, which would be bad.

                                                      Is there a good class on the java side that can tell me how to use the image data to reconstruct the colors?
                                                      There's some code in tools/mon/org/tekkotsu/mon/UDPVisionListener.java that might be useful.  Down at the bottom, below all the network parsing code is some code for converting from YUV to RGB.  This code is very fast, but makes a few slight approximations.  Search around on the web for more precise conversions.  Be aware though that there are a couple slight differences in format -- YUV isn't *quite* the same as YCrCb, and although we refer to YUV everywhere, if I remember correctly, the camera is actually returning YCrCb.  I think. ;)

                                                      Note that the Java code is using an int (4 bytes) for each pixel -- 1 byte for an alpha channel (always 255), and then 1 byte for each of the RGB or YUV channels.

                                                      -ethan


                                                    • Crews Carrie D 1stLt AFIT/ENG
                                                      The command port is 10020, correct? _____ From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson Sent:
                                                      Message 26 of 29 , Sep 13, 2005
                                                      • 0 Attachment
                                                        The command port is 10020, correct?


                                                        From: tekkotsu_dev@yahoogroups.com [mailto:tekkotsu_dev@yahoogroups.com] On Behalf Of Ethan Tira-Thompson
                                                        Sent: Wednesday, September 07, 2005 2:46 PM
                                                        To: tekkotsu_dev@yahoogroups.com
                                                        Subject: Re: [tekkotsu_dev] WorldStateSerializer

                                                        Crews Carrie D 1stLt AFIT/ENG wrote:
                                                        I have a UDP connection established, and collect data inside a finite while loop, then close the socket.  If I try to run the program again on the two camera ports, I don't get a connection and have to reboot the AIBO.  I'll look in your code to see how the wireless class handles UDP connections.
                                                        I confirmed what you're seeing using the new "Echo Client/Server" (under TekkotsuMon)... UDP ports stay open even when their packets are being refused because the client is closed.  I'm not sure if that's something we can fix (might be a system limitation that it doesn't tell us when packets bounce) but I'll look into it.
                                                          http://bugs.tekkotsu.org/show_bug.cgi?id=188

                                                        In the mean time, it looks like you will have to restart the camera servers after each connection (or use TCP).  You could automate the restarts with a script, or by connecting to the ControllerGUI port and sending the appropriate commands, e.g.:
                                                          !select "#Raw Cam Server" ; !select "#Seg Cam Server"
                                                          !select "Raw Cam Server" ; !select "Seg Cam Server"
                                                        (The first line shuts down the servers if they are already running, the second starts them up again)
                                                        The only trick with scripts is that the ';' token must be its own "word" (surrounded by whitespace), otherwise it is taken as part of an argument and not interpreted to separate commands.  You can also separate commands with a newline.
                                                        (thanks again to Doug Blank for adding argument support to the !select command, used above)

                                                        -ethan
                                                      • Ethan Tira-Thompson
                                                        ... If I remember correctly, you are connecting to the camera ports using UDP? Currently, the camera is the only one to use UDP -- everything else (notably
                                                        Message 27 of 29 , Oct 25, 2005
                                                        • 0 Attachment
                                                          On Oct 25, 2005, at 2:49 PM, crews1969 wrote:
                                                          > I have turned on the WorldStateSerializer via telnet to port 10020,
                                                          > but
                                                          > my socket won't successfully connect. I use cloned code that works to
                                                          > connect to the camera ports (which works), just replacing variables
                                                          > and
                                                          > assigning the saServer.sin_port to be htons(10031). Any ideas as to
                                                          > why?

                                                          If I remember correctly, you are connecting to the camera ports using
                                                          UDP? Currently, the camera is the only one to use UDP -- everything
                                                          else (notably WorldStateSerializer) uses TCP.
                                                        • crews1969
                                                          If I turn on the WorldStateSerializer server, is there anything else I need to do to trigger output from (wsJoints)10031 and (headControl) 10052? Carrie.
                                                          Message 28 of 29 , Oct 25, 2005
                                                          • 0 Attachment
                                                            If I turn on the WorldStateSerializer server, is there anything else I
                                                            need to do to trigger output from (wsJoints)10031 and (headControl)
                                                            10052?

                                                            Carrie.
                                                          • crews1969
                                                            I ll make the change. THanks ... 10020, ... works to ... variables ... as to ... using ... everything
                                                            Message 29 of 29 , Oct 25, 2005
                                                            • 0 Attachment
                                                              I'll make the change. THanks

                                                              --- In tekkotsu_dev@yahoogroups.com, Ethan Tira-Thompson <ejt@a...>
                                                              wrote:
                                                              >
                                                              > On Oct 25, 2005, at 2:49 PM, crews1969 wrote:
                                                              > > I have turned on the WorldStateSerializer via telnet to port
                                                              10020,
                                                              > > but
                                                              > > my socket won't successfully connect. I use cloned code that
                                                              works to
                                                              > > connect to the camera ports (which works), just replacing
                                                              variables
                                                              > > and
                                                              > > assigning the saServer.sin_port to be htons(10031). Any ideas
                                                              as to
                                                              > > why?
                                                              >
                                                              > If I remember correctly, you are connecting to the camera ports
                                                              using
                                                              > UDP? Currently, the camera is the only one to use UDP --
                                                              everything
                                                              > else (notably WorldStateSerializer) uses TCP.
                                                              >
                                                            Your message has been successfully submitted and would be delivered to recipients shortly.