SW2URDF aka SolidWorks assembly to URFD (…or not)

Designing a virtual representation of a robot is not easy, but it has been greatly facilitated with the introduction of a SolidWorks extension SW2URDF by an amazing Stephen Brawner. This means that you can now design your robot in SolidWorks and directly export the assembly of links and joints into a ROS package with .STL meshes and URDF files and whatnot. Sounds too good to be true? Well it kind of is.

The workflow is very clearly described in the ROS website’s handy tutorial. And it may well be that it will work great for you in which case this post is a waste of your time. Good on you, you lucky bastard.


It seems to often be the case that the automatic workflow of the SW2URDF add-on fails. You have prepared your sweet sweet model, joined all the joints and named all the links, but upon pressing the magical “preview and export” button, the process generates a few joints and then the progress bar stops moving. Nothing new happens even when waiting for a rather long time.

This happened to me and a quick search on the internet revealed that this happened to a bunch of people before as well. And sadly no clear solution was being offered. But all is not lost, there is a workaround!

Digging a bit deeper (well not all that deep after all, it’s an issue raised on the package’s repository website), I have found a post by Ari Kapusta, referring to the same issue. And its solution! In a nutshell, it seems to be the automatic process generating joint origins and axes that is failing without raising an exception or warning. You can work around it if you follow my description (based on Ari’s comment).

  1. This procedure is assuming that you’re working with a Solid Works assembly of robot links and that you have already successfully installed the SW2URDF package. You can activate it with the ‘File > Export to URDF’. This will bring upon a menu where you can prepare names of all your joints and links and select the respective parts of the assembly.
  2. Having organised all the necessary information, you can proceed to activate the automatic process of joint definition and since you’re still reading, presumably fail at some point.
  3. Check which joint origins and axis have been generated and whether some of them seem correct. Presumably the last joint will have failed. Delete that result.
  4. All you have to do now is define all the remaining joints manually. It’s not hard to do. Following is a description that could help you in the process.
  5. Start by preparing guidelines withing the 3D sketch that was automatically generated. You will want to use a clever combination of construction lines akin to what you can see in the picture below. The two perpendicular construction lines that make not sense are remainder from the automatic process and you will need to delete them.URDF
  6. Use the construction lines to define origin and axis of your joints as is your want. Try to keep the naming template generated by the automatic process and defined in the beginning of the process.
  7. When you’re done, go back to the ‘File > Export to URDF’ option. Now you will have a chance to select your predefined joints and axis instead of the automatic options.
  8. Run the ‘preview and export’ option again and  you should through to the next option which is definition of kinetic properties and whatnot. When you’re done with that, you’re pretty much good to go!

Congratulations, you did it! And thanks to Ari for figuring this out!

 

 

Advertisements

REDIS: Iterating through database with SCAN

It has recently come to my attention that iterating though stuff is quite important. Be it a lists, sets or hashes. This can generally be accomplished using the general SCAN method in Redis. However convenient, it is a little confusing at first so lets analyze it a bit closer.

Another option you will notice is the COUNT. I believe this is generally set to 10 give or take. Now you might come up with the same idea as I did. Surely setting the COUNT to 1 will make SCAN act like a normal iterator, returning one value at the time.

This is not the case as I had to learn the hard way.

Strangely enough the COUNT value is only an approximate value of results SCAN will return. Even if set to 1, you will very often receive 2 or more entries at the time so you will always need to iterate through the returned values if you want to deal with entries one by one.

Python code example

So say you have a hash database called ‘hash_database’ because you have no imagination and its late and you want to iterate through its members using redis-py. You would probably want to write something like this


import redis

database = redis.StrictRedis('localhost')
cursor = 0
while true:

    cursor, entries = database.hscan('hash_database', cursor)

    # Just printing entries one by one
    for name, content in entries.items():
    print("Name: {} -- Content: {}".format(name, content))

    if cursor == 0:
        break

This is a pretty simple way to handle this odd iteration method. If you’re concerned about the connection speed, you can set the COUNT to some higher number and receive larger chunks of your data at each call. One again, those chunks will vary in size with each iteration, but generally stay close to the defined number.

As much as this is not extremely complex, redis-py makes your life even simpler offering the convenience wrapper scan-iter. This will simplify the above code thusly:

<pre>import redis

database = redis.StrictRedis('localhost')

for entry in db.hscan_iter('read_sequence'):
    print("Name: {} -- Content: {}".format(entry[0], entry[1]))

How much simpler is this?! Note that in this case the entries will be returned one by one and you don’t have to worry about the cursor value. You can still speficy the COUNT value, which  I assume determines the number of database entries obtained in each ‘call to the database’. However that’s only my assumption and if you know more about it, please leave me a comment.

So why am I even bothering explaining the original SCAN method if redis-py makes it so much simpler? Well mostly because pure Redis doesn’t have any SCAN_ITER method so when accessing it directly or writing lua scripts you’ll still have to rely on the CURSOR. Partially also because I find it quite amusing. It reminds me of The Twelve Tasks of Asterix where they needed to fetch a permit A38 from ‘The Place That Sends You Mad’ sending Asterix and Obelix from one cubicle to another. If you’ve seen the movie and/or ever dealt with bureaucracy,  you would know what I’m refering to.

REDIS: 3 ways to clone a database (in python)

It has recently come to my attention that REDIS is actually a very useful tool for managing your database. It’s very fast it’s supposedly reliable. At least Twitter and Pinterest seem to think so and if Pinterest says it, who am I to oppose.

As much as on a whole REDIS is quite intuitive, one might still run into troubles like I did when I was trying to clone a database and maintain an ‘original’ version alongside a version that had been edited. Apparently there are multiple ways how to go about it, but as it’s often the case, some ways are better the others.

One REDIS instance with multiple databases

This might look like the most straightforward way to deal with multiple databases as suggested here. REDIS is able to operate with multiple databases in one instance. If not specified, REDIS will create database at port 0, however if you so desire, you can change that. In order to achieve that you’ll need to do the following.

Open a single redis-client in your command line or however you decide to do that and proceed to python:

import redis

database1 = redis.StrictRedis('localhost', port = 6379, db=0)
database2 = redis.StrictRedis('localhost', port = 6379, db=1)

database1.set('key1', 'value1')
database2.set('key2', 'value2')
...

Now you have two database object, which each point to the same instance. You can access the two databases using their objects or the following links as described in the redis-py documentation.

This might look convenient, but it’s definitely not recommended. Let’s hear from Salvatore Sanfilippo himself as stated here:

I understand how this can be useful, but unfortunately I consider Redis multiple database errors my worst decision in Redis design at all… without any kind of real gain, it makes the internals a lot more complex.

(Salvatore Sanfilippo, 15.5.2010)

So what is the correct way to do this?

Mark your keys

Instead of separating two databases, you might come up with a system of key names that reflect belonging to two different datasets. There should nothing inherently wrong with that and it might end up being the easiest way. One could imagine a system like this:

database1_key1
database1_key2
database2_key1
...

Use one REDIS instance per database

If you don’t like the idea of mixing up the keys from two databases, having two separate instances of REDIS running should do the work. In this case you’ll probably need to specify port for each one of them as follows:

redis-server --port 6379

This way you can specify the port value for each REDIS instance separately. This is what you will use in your python code.

import redis database = redis.StrictRedis('localhost', port = 6379)

database.set('key1', 'value1')

Copying data between databases

Last but not least, here is a little tip on how to clone a database. Again there are a few ways to do that.

Dump database and reaload it

This is suggested over here. It feels a little bit more like a hack then a proper procedure and I haven’t tested it, but I don’t see a reason why it wouldn’t work. You can dump the whole database into a file asynchronously using:


database.bgsave()

This will create a dump.rdb file, which contains a copy of your database. You’ll need to copy it in a different folder and initiate the second database from there. As the second database starts, it will look for dump.rdb file to initialize from. This will effectively create a new clone.

Enslave and liberate method

This is not exactly an official name, but it’s quite descriptive of what’s going on. You will need to create two instances and make one slave of the other:


database1 = redis.StrictRedis('localhost', port=6379) 

database2 = redis.StrictRedis('localhost', port=6380)

database2.slaveof('localhost', port=6379)

The property of slave database is that it gets a copy of all the entries in a master database. This transfer happens on the background so you don’t have to worry about it.

Now because we want to have a clone of the original database, we need to ‘un-slave’ the second  database, or liberate it if you will. And a free database is a slave to whom? Nobody! And that’s precisely how it’s done.


database2.slaveof()

This breaks the bond between the databases and stops the data from being transfered together with future edits in database1. And there you have it – a clone of database is done. Just a side note though, you probably want to check if the data transfer is finished, so it might be a good idea to compare for instance the database sizes.

import time

if database1.dbsize() == database2,dbsize():
    database2.slaveof()
else:
    print('Waiting for the data transfer to finish')
    time.sleep(1)

There is probably a better way to do this. I reckon there is a way to ask for a confirmation of the transfer. REDIS is very general with its confirmation messages. However I didn’t have time to look into that. If you know any better, please leave me a comment. Thanks!

 

Introduction

When it comes to programming, the abundance of documentation out there is not always directly proportional to the ease of understanding. I for once sometimes find it hard to really figure out just what should I be doing. Too many options confuse me – how can I know which one is the best to pick? And sometimes I feel like I’m downright expected to think in binary to understand some ‘documentation’.

I am personally so glad for the army of ‘noobs’ to cover every possible (bad) idea on the stack overflow. However sometimes one gets to an unexplored territory where only the bravest and skilled programmers dwell. A jungle of undescriptive error messages and unhelpful manuals.

I am bravely trotting, where no (sensible) man has gone before and I’ll be sharing my woes and victories with you.