I didn’t quite get the success I hoped with my last post about Denavit Hartenberg of a PUMA arm But now that I got it solved, I am tackling the much more annoying problem of creating automatically the DH parameters for any robotic arm, using a linked list of joints as the input of the algorithm.
I already did most of the job actually, I compute the Z axis for each of the joints, then I make a crossproduct of the Z axis of the current joint with the previous one to get the X axis (common perpendicular). But in certain cases, my X axis is completely wrong.
I see two main problems with the way I do it : first, the origin of each DH repere is always at the center of the joint while it’s supposed to be computed by intersection of lines and such, in my experience, it’s always in the center of the joint, but … is it really ? Second, my X axis is always computed by the crossproduct unless the result of the crossproduct wield a vector with a norm == 0, in that case, I use the previous X axis. But as far as I know, there are many more cases to deal with, it just seems to me that they all lead to the crossproduct so I simplified it. I guess I shouldn’t have !
Before I get in too much details, has anyone here already dealt with this kind of issues, as in creating an automatic way to build DH tables from scratch ?
I use a table stored in a config file to define dimensions and orientations (using UP & DIR vectors) of each part. That way, based on the servo angle I can calculate the state of the entire skeleton (custom biped) in real time.
For each “part” I specify a known initial DIR and UP vector. Taking the cross product, I get the axis of rotation corresponding to the servo that controls that part. I never get zero vectors since the input to the cross product is always 2 unit vectors that are normal to each other.
Here’s a snippet of a config file:
part = right_upper_arm
parent = right_chest_v
dir = < 0, -1, 0 > # initial orientation - vectors normal to each other
up = < 0, 0, 1 >
size.dir = 16.0 # size in dir direction, cm
size.up = 6.0 # size in up direction, cm
size.dxu = 6.0 # size in dir "cross" up direction, cm
The origin - in my world -is at the base of the part, not the center. The end of the part is “size.dir” centimeters from the base along the DIR vector. The base of the next part is at the end of this part, and so on. It’s recursive.
What you are doing is kinda the end result I was trying to get at 2 months ago. The whole problem was that the robot I was creating the DH parameters from wasn’t in any kind of “easy position”, and it was always about some kind of “epsilon” here and there that made the whole thing collapse.
Also, the axis of rotations aren’t always normal to each other, that was the second part of the problem and the one that took me awake the longest at night ;p They can be normal, but they can also be parallel or skew. In those situations, the DH parameters are harder to get. Even tho my program is currently working and doing well with most 6+ DOF arms, I still encounter situations (positions) where I get problems. It’s the same robot, but in a different position, I can’t get the DH parameters table !
Obviously, doing it your way would have been easier but you are actually using many parameters, namely 3 for dir vector, 3 for up vector, and 3 directions, which is 9 : your parameters are very redundant ! The point of using DH parameters was to have parts defined by only 4 parameters instead of the “minimum” 6 and the easier 9 as you are doing. This can be very helpful in two situations : automatic robot generation (genetic algorithm for instance) where the search space is many order of magnitudes smaller with 4 parameters rather than 6 or 9, and when you are working with real life robots that only have DH parameters table to describe them, as it was the practice (and still is I believe even tho I haven’t been in that field for a while) a few years back.
Thanks anyway and as this is your first post, even tho I am also new here, welcome on Lynxmotion forum !