Giter VIP home page Giter VIP logo

Comments (6)

routiful avatar routiful commented on August 17, 2024

Hello @RobotisBrandon :)

Because of storage size, I was supposed to restict address of Dynamixel.
But user can use itemwrite function to access what they want

https://github.com/ROBOTIS-GIT/OpenCR/blob/9da4ae9fd4506df6e068c2a6d381f268a0ba371a/arduino/opencr_arduino/opencr/libraries/DynamixelWorkbench/src/dynamixel_workbench_toolbox/dynamixel_workbench.cpp#L349

For example, set data true on Drive Mode

dxl_wb.itemwrite(ID, 10, 1, 1);

However, I expect that user want to frequently access to this address. So I will include this available in OpenCR and OpenCM9.04.

Thanks

from opencm9.04.

KurtE avatar KurtE commented on August 17, 2024

@routiful @OpusK and @RobotisBrandon

For the fun of it I made a version of the Workbench (currently on OpenCR as my OpenCM Fork/Branch has a reasonable sized PR pending in it for SerialX.write...

I put in a PR against OpenCR project (#139), where I changed how the register name tables were handled. I created const static arrays for each Servo type, so all memory associated with them stays in ROM and does not use RAM. The tools object was updated to use the returned ptr instead of making local copy. So again removed the RAM usage.

With this I used the full table for all of the servos.... And again RAM usage went down... Program size went up a little.

This is in the same branch where I added the "info" command
ROBOTIS-GIT/OpenCR#136

With this change there could be a slight slowdown of programs, as you are searching for address names by brute force so if your item was the 10th item down and now is the 15th, you will have done some extra compares...

That part can be improved a few different ways, including:

a) order the list, by expected frequency of usage. i.e. goal position should be pretty close to top

b) Put in alphabetical order, and do an alpha/beta or like tree prune search... if you have 50 items, look first at 25th if your value is less look at 12th if value greater look at 37th...

c) convert strings to some hashtag value example 32 bits which should be unique. Then you can do quick WORD compares...
...
But that is beyond the scope of the changes I did...

from opencm9.04.

OpusK avatar OpusK commented on August 17, 2024

@KurtE ,

With this I used the full table for all of the servos.... And again RAM usage went down... Program size went up a little.

Your working is cool!

As you mentioned, I think we should choose between reduced RAM usage and speed.
This will depend on the policies of OpenCM or OpenCR.

What do you think about this? @routiful @chcbaram ?

from opencm9.04.

KurtE avatar KurtE commented on August 17, 2024

Hi @OpusK, @routiful and @chcbaram,

Your working is cool!

As you mentioned, I think we should choose between reduced RAM usage and speed.
This will depend on the policies of OpenCM or OpenCR.

As I mentioned in the current Pull Request, I personally believe you should be able to give the user the full table of Items on all platforms and speed it up on all platforms. As I mentioned in another message,
If you take my current tables which should reside in program space not ROM, example AX:

static const ControlTableItem items_AX[] {
    {0  , "Model_Number"                  , 2},
    {2  , "Firmware_Version"              , 1},
    {3  , "ID"                            , 1},
    {4  , "Baud_Rate"                     , 1},
    {5  , "Return_Delay_Time"             , 1},
    {6  , "CW_Angle_Limit"                , 2},
    {8  , "CCW_Angle_Limit"               , 2},
    {11 , "Temperature_Limit"             , 1},
    {12 , "Min_Voltage_Limit"             , 1},
    {13 , "Max_Voltage_Limit"             , 1},
    {14 , "Max_Torque"                    , 2},
    {16 , "Status_Return_Level"           , 1},
    {17 , "Alarm_LED"                     , 1},
    {18 , "Shutdown"                      , 1},

    {24 , "Torque_Enable"                 , 1},
    {25 , "LED"                           , 1},
    {26 , "CW_Compliance_Margin"          , 1},
    {27 , "CCW_Compliance_Margin"         , 1},
    {28 , "CW_Compliance_Slope"           , 1},
    {29 , "CCW_Compliance_Slope"          , 1},
    {30 , "Goal_Position"                 , 2},
    {32 , "Moving_Speed"                  , 2},
    {34 , "Torque_Limit"                  , 2},
    {36 , "Present_Position"              , 2},
    {38 , "Present_Speed"                 , 2},
    {40 , "Present_Load"                  , 2},
    {42 , "Present_Voltage"               , 1},
    {43 , "Present_Temperature"           , 1},
    {44 , "Registered"                    , 1},
    {46 , "Moving"                        , 1},
    {47 , "Lock"                          , 1},
    {48 , "Punch"                         , 2} };
#define COUNT_AX_ITEMS (sizeof(items_AX)/sizeof(items_AX[0]))

And ask yourself, how often am I likely to use each of these items. Especially in any frequent usage. What happens to the speed if you simply change it closer to:

static const ControlTableItem items_AX[] {
    {36 , "Present_Position"              , 2},
    {38 , "Present_Speed"                 , 2},
    {40 , "Present_Load"                  , 2},
    {42 , "Present_Voltage"               , 1},

    {30 , "Goal_Position"                 , 2},
    {32 , "Moving_Speed"                  , 2},
   
    {24 , "Torque_Enable"                 , 1},
    {25 , "LED"                           , 1},
    {43 , "Present_Temperature"           , 1},
    {46 , "Moving"                        , 1},

    {26 , "CW_Compliance_Margin"          , 1},
    {27 , "CCW_Compliance_Margin"         , 1},
    {28 , "CW_Compliance_Slope"           , 1},
    {29 , "CCW_Compliance_Slope"          , 1},
    {34 , "Torque_Limit"                  , 2},
    {44 , "Registered"                    , 1},
    {47 , "Lock"                          , 1},
    {48 , "Punch"                         , 2} };
   {0  , "Model_Number"                  , 2},
    {2  , "Firmware_Version"              , 1},
    {3  , "ID"                            , 1},
    {4  , "Baud_Rate"                     , 1},
    {5  , "Return_Delay_Time"             , 1},
    {6  , "CW_Angle_Limit"                , 2},
    {8  , "CCW_Angle_Limit"               , 2},
    {11 , "Temperature_Limit"             , 1},
    {12 , "Min_Voltage_Limit"             , 1},
    {13 , "Max_Voltage_Limit"             , 1},
    {14 , "Max_Torque"                    , 2},
    {16 , "Status_Return_Level"           , 1},
    {17 , "Alarm_LED"                     , 1},
    {18 , "Shutdown"                      , 1},

#define COUNT_AX_ITEMS (sizeof(items_AX)/sizeof(items_AX[0]))

Note: the order above is somewhat random, but I bet in the majority of cases this will be faster.

I have not checked the compiler/linker output to see if it combines duplicate const strings or not... If not and maybe even if so, we would benefit if we create the table more like:

static const uint8_t s_model_number[] =  "Model_Number";
static const uint8_t s_firmware_version[] = "Firmware_Version";
...

static const ControlTableItem items_AX[] {
    {0  , s_model_number, sizeof(s_model_number)-1 , 2},
    {2  , s_firmware_version, sizeof(s_firmware_version)-1            , 1},
    ...

And update the item to contain a length field... Then for example we could change

const ControlTableItem* DynamixelTool::getControlItem(const char* item_name)
{
  const ControlTableItem* cti = item_ptr_;  
  for (int num = 0; num < the_number_of_item_; num++)
  {
    if (!strncmp(item_name, cti->item_name, strlen(cti->item_name)))
    {
      return cti;
    }
    cti++;
  }
...

To not have to run the strlen on all of these items every time. Also not of your usage of strncmp here as not sure if you want the string: "IDLE" passed in to match the item "ID"

The above could probably be changed to something like:

const ControlTableItem* DynamixelTool::getControlItem(const char* item_name)
{
  const ControlTableItem* cti = item_ptr_;  
  item_name_length = strlen(item_name);  // get the length of requested string. 
  for (int num = 0; num < the_number_of_item_; num++)
  {
    if ((item_name_length == cti->item_name_length) && (memcmp(item_name, cti->item_name, item_name_length == 0))
    {
      return cti;
    }
    cti++;
  }

Would speed things up, as you are not calling strlen on every item every time, and you only compare strings of same size...

These together would probably be faster than current code even with full lists. If still not fast enough, there are obviously faster searching methods... Been a long time since I looked at the book Sorting and Searching by Donald Knuth.... (oops shows my age ;) ) So I forget the names and exacts...

But one is: sort all of the items alphabetically: and keep a Head/tail pointer (first/last). Obviously at any time if you get a match stop... Compare the item half way between head and tail. If your string is < mid point set last to your mid, else set first till your mid... repeat... Usually at some point where there is less than N items between first and last you then just go sequential...

Another is to create a KEY value for each string. Do some quick calculation Example if key is uint32_t, try adding every DWORD value of the string together and add in remainder.. Or simply add all of the bytes of the string together. Or maybe add but do a shift between, or... But hopefully some very simple calculation. Run this over all of the Item_Name strings, and hopefully make it such that all items are unique and again store these as part of the item name table. And then hopefully you can simply take in the string from call, convert to key and then simply look through table matching keys... You might still do strcmp at end to verify it truly is your item.

So again I think this is very doable...

from opencm9.04.

routiful avatar routiful commented on August 17, 2024

If anyone want to keep subscribing this issue, please follow below PR.

#45

from opencm9.04.

routiful avatar routiful commented on August 17, 2024

This issue is closed after merge @KurtE branch to develop branch.

from opencm9.04.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.