Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5

Python API Target.Name() Regresses between API 5.6.3 and 5.6.4

#1
I have a fairly large codebase/environment and the relevant call happens deep inside, so I am not able to provide an exact reproducible example of what I am seeing. However, I can reproduce it on my own and I would be happy to demonstrate it on a call if desired.

Here's a mock-up of what my function looks like:
Code:
def example_fn(t_0: robolink.Item, t_1: robolink.Item):
    v = robomath.subs3(t_1.Pose()[0:3,3].tolist(), t_0.Pose()[0:3,3].tolist())
    z = robomath.subs3(t_0.Pose()[0:3,3].tolist(), t_0.Pose().Offset(x=0, y=0, z=-1)[0:3,3].tolist())
    t_0.setPose(robomath.point_Xaxis_2_pose(point=t_0.Pose()[0:3,3], xaxis=v, zaxis_hint1=z))

With RoboDK API 5.6.4 (`pip install robodk=5.6.4`), I get the following exception on the last line of the function above.
Quote:Exception has occurred: error
required argument is not a float

In the debug console, I repeatedly called t_0.Name() and, bizarrely, got a different result each time.
Code:
>>t_0.Name()
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "my_path\robolink.py", line 4491, in Name
    name = self.link._rec_line()
           ^^^^^^^^^^^^^^^^^^^^^
  File " my_path\robolink.py", line 862, in _rec_line
    return str(b''.join(bytes_list).decode('utf-8'))  # python 2 and python 3 compatible
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
>>t_0.Name()
'\x00\x00\x00\x00t_0'
>>t_0 .Name()
't_0'
>>t_0 .Name()
't_0'

After `pip install robodk=5.6.3`, this issue completely disappears and my code runs fine, throwing no exceptions.
#2
Checking-in on this -- there's some features from newer versions of the API that I'd very much like to use. (Right now I've got local changes to the 5.6.3 .py files sitting on my machine, which is not a sustainable solution.)

Let me know if the GitHub is a better place to open an issue like this.
#3
I'm not sure what the issue is but it may be related to how this function is used:
point_Xaxis_2_pose

And it provokes other issues with the Name function.

Where exactly do you see this error?
Code:
Exception has occurred: error
required argument is not a float
Can you print the value of the Pose?
Example:
Code:
def example_fn(t_0: robolink.Item, t_1: robolink.Item):
    v = robomath.subs3(t_1.Pose()[0:3,3].tolist(), t_0.Pose()[0:3,3].tolist())
    z = robomath.subs3(t_0.Pose()[0:3,3].tolist(), t_0.Pose().Offset(x=0, y=0, z=-1)[0:3,3].tolist())
    pose =  robomath.point_Xaxis_2_pose(point=t_0.Pose()[0:3,3], xaxis=v, zaxis_hint1=z)
    print(pose)
    t_0.setPose(pose)
Or if you can provide us with a fully working example we can better reproduce and fix this issue.
#4
The exception occurred somewhere in the line below. I expect I most likely got the error in `point=t_0.Pose()`, but it could have been anywhere in that line.
Code:
t_0.setPose(robomath.point_Xaxis_2_pose(point=t_0.Pose()[0:3,3], xaxis=v, zaxis_hint1=z))

I went to try to get the information you requested, and unfortunately, I am no longer able to reproduce the problem (previously it was reliable and predictable). I was able to checkout the specific commit of my code as well as the right version of the RoboDK API. The only thing that I wasn't able to revert was the actual workstation that I was testing on, so I have to assume there was something about the workstation itself causing this problem.

Pretty disappointed that I lost it, but I will post again if I ever see and reproduce this issue in the future.
#5
@Albert

This issue started occurring again and I found the cause this time (explanation below). Looks like the change that provoked this is in the Mat.setPos() method. `self[0, 3] = newpos[0]` became `self.rows[0][3] = newpos[0]`.

I traced the issue back to this specific line, unusually returning a robomath.Mat object that isn't displayed the normal way.

Code:
robomath.point_Xaxis_2_pose(point=t_0.Pose()[0:3,3], xaxis=v, zaxis_hint1=z)
> <robodk.robomath.Mat object at 0x000002012D21CC10>

To investigate further, I printed it as a list.
Code:
robomath.point_Xaxis_2_pose(point=t_0.Pose()[0:3,3], xaxis=v, zaxis_hint1=z).tolist()
> [-0.9972576834640152, -0.012691713711623781, -0.07291113203790231, 0]

Interestingly, robomath.size() is no help.

Code:
robomath.size(robomath.point_Xaxis_2_pose(point=t_0.Pose()[0:3,3], xaxis=v, zaxis_hint1=z))
> (4, 4)

This presented three issues.
1. Why was robomath.point_Xaxis_2_pose returning a Mat whose .tolist() method returns a list of length four?
2. Why does robomath.size(Mat_with_4_elements) return (4, 4)? It's not clear what shape the four elements I saw from the .tolist() call were in, but there were only four elements, so it definitely couldn't be a 4x4 matrix.
3. Why does t_0.setPose(Mat_with_4_elements) make it such that subsequent calls to t_0.Name() return the bizarre results I previously described?

I figured out issue 1:
`t_0.Pose()[0:3,3]` returns a 3x1 Mat. This is passed to `point_Xaxis_2_pose` through the `point` argument, which subsequently passes that variable to `setPos`. The `setPos` method of the Mat then attempts to set its three translation elements to be 1x1 Mat's. The success of this operation varies between v5.6.3 and v5.6.4.
I did not put time into debugging the other two issues.

Here are two worked examples to compare.

1: 5.6.3 just works. I also confirmed that this works when `point != [[0,0,0]]`
Code:
pip install robodk==5.6.3
python
>>> from robodk import robolink, robomath
>>> rdk = robolink.Robolink(args=['-NEWINSTANCE'])
>>> t_0 = rdk.AddTarget('t_0')
>>> pose = robomath.eye()
>>> point = t_0.Pose()[0:3,3]
>>> pose = pose.setPos(point)
>>> t_0.setPose(pose)
>>> t_0.Name()
't_0'

2: 5.6.4 Prints error message after setting the target to the invalid pose, but does not stop execution. (In my specific application, this error message gets suppressed by some menu interfaces managing what what is displayed in the console.) After setting the target to the invalid pose, the bizarre errors with `t_0.Name()` occur as I previously described.
Code:
pip install robodk==5.6.4
python
>>> from robodk import robolink, robomath
>>> rdk = robolink.Robolink(args=['-NEWINSTANCE'])
>>> t_0 = rdk.AddTarget('t_0')
>>> pose = robomath.eye()
>>> point = t_0.Pose()[0:3,3]
>>> pose = pose.setPos(point)
>>> t_0.setPose(pose)
struct.error: required argument is not a float
# ( error above occurs in robolink.py, line 921: data = [struct.pack('>4d', *(lst2[i])) for i in range(4)] )
>>> t_0.Name()
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
>>> t_0.Name()
'\x00\x00\x00\x00t_0'
>>> t_0.Name()
't_0'

Note that if you call `pose.setPos(point)` without anything to catch the return value, it will attempt to print to the console, which throws an exception when the `__str__` method gets called.

It is easy for me to resolve this issue by using `point=pose[0:3,3].tolist()`. Indeed, I should have been doing it the whole time and it's just a coincidence that it worked at all in v5.6.3. However, some of the other behavior is pretty weird and should probably have more graceful handling when the user (me) tries to do dumb things (pass an iterable of the wrong shape).
#6
Thanks for letting us know with such detail. I understand the issue now. I was able to reproduce it and we just fixed it on GitHub:
https://github.com/RoboDK/RoboDK-API/com...abb1c0e4cb

In short, you could replace the setPos by this function:
Code:
    def setPos(self, newpos):
        """Sets the XYZ position of a pose (assumes that a 4x4 homogeneous matrix is being used)"""
        if type(newpos) == Mat:
            newpos = list(newpos)[0]
           
        self.rows[0][3] = newpos[0]
        self.rows[1][3] = newpos[1]
        self.rows[2][3] = newpos[2]
        return self
#7
Thanks, Albert! Just pulled.
  




Users browsing this thread:
1 Guest(s)