Unit mismatch error in FreeCAD 0.20

Need help, or want to share a macro? Post here!
Post Reply
Zoltan
Posts: 62
Joined: Wed Jul 07, 2021 10:08 am

Unit mismatch error in FreeCAD 0.20

Post by Zoltan »

Hello,

I encountered a strange error in FreeCAD 0.20.
Assume that you have four points (Draft.Point objects), labelled as P1, P2, P3 and P4, with units in mm. I have an expression in the form of a Python string to evaluate, let us call it expression. To evaluate this expression, we can use

Code: Select all

P1.evalExpression(expression)
This provides the correct value in FreeCAD 0.19, but not in FreeCAD 0.20 (git hash 68e3376), the latter throwing an exception:

Code: Select all

ArithmeticError: Quantity::operator +(): Unit mismatch in plus operation
What makes the situation stranger is that when I run my script containing this expression using the PyCharm IDE (the Python interpreter coming from the extracted AppImage), I do not get this error.

Do you have any ideas why this happens and how I could further narrow down the cause of the error?

The error can be reproduced with the code below.

Code: Select all

import FreeCAD as App
import Draft

P1 = Draft.make_point(App.Vector(-74.924, 2.875, 160.36))
P1.Label = 'P1'
P2 = Draft.make_point(App.Vector(-10.965, 11.594, 160.36))
P2.Label = 'P2'
P3 = Draft.make_point(App.Vector(-7.391, -50.421, 160.36))
P3.Label = 'P3'
P4 = Draft.make_point(App.Vector(54.302, 5.066, 160.36))
P4.Label = 'P4'
App.ActiveDocument.recompute()

expression = 'P3.X + (-10)*-(((P3.Y + 1.5*(sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2))*((P1.Y) - (P3.Y)) / sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2)) - (P3.Y)) / sqrt(((P3.X + 1.5*(sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2))*((P1.X) - (P3.X)) / sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2)) - (P3.X))^2 + ((P3.Y + 1.5*(sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2))*((P1.Y) - (P3.Y)) / sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2)) - (P3.Y))^2 + ((P3.Z + 1.5*(sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2))*((P1.Z) - (P3.Z)) / sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2)) - (P3.Z))^2))'

P1.evalExpression(expression)
openBrain
Veteran
Posts: 7993
Joined: Fri Nov 09, 2018 5:38 pm

Re: Unit mismatch error in FreeCAD 0.20

Post by openBrain »

Maybe you could evaluate each parenthesis content by descending hierarchical order...
User avatar
onekk
Veteran
Posts: 2816
Joined: Sat Jan 17, 2015 7:48 am
Contact:

Re: Unit mismatch error in FreeCAD 0.20

Post by onekk »

Zoltan wrote: Wed Jun 29, 2022 3:56 pm

Probably it is happening has you has no units in the multipliers:

try:

Code: Select all

print(P1.X)

expr1 = 'P3.X + -10 mm'
expr2 = ""
# expr2 = ' * -(((P3.Y + 1.5 * (sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2))*((P1.Y) - (P3.Y)) / sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2)) - (P3.Y)) / sqrt(((P3.X + 1.5*(sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2))*((P1.X) - (P3.X)) / sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2)) - (P3.X))^2 + ((P3.Y + 1.5*(sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2))*((P1.Y) - (P3.Y)) / sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2)) - (P3.Y))^2 + ((P3.Z + 1.5*(sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2))*((P1.Z) - (P3.Z)) / sqrt(((P1.X) - (P3.X))^2 + ((P1.Y) - (P3.Y))^2 + ((P1.Z) - (P3.Z))^2)) - (P3.Z))^2))'

expression = expr1 + expr2

P1.evalExpression(expression)

You will easily see that P1.X will return units, and 10 has no units in your code, in my test code it will print correctly

So the error has some sense!

But probably expression should allow "unitless" operators?

Regards

Carlo D.

Edit: some conceptual error it was not a multiplier but addend.
Last edited by onekk on Fri Jul 01, 2022 7:53 am, edited 2 times in total.
My English and Italian Scripting Guide https://github.com/onekk/freecad-doc.
My Blog: https://onekk-maker.blogspot.com/

To help development see on GitHub Page

For enquiry about customized FC Scripting job PM me.
TheMarkster
Veteran
Posts: 4515
Joined: Thu Apr 05, 2018 1:53 am

Re: Unit mismatch error in FreeCAD 0.20

Post by TheMarkster »

import math
>>> P1.Y
2.875 mm
>>> math.sqrt(P1.Y)
1.695582495781317
>>> math.sqrt(P1.Y)+P1.Y
Traceback (most recent call last):
File "<input>", line 1, in <module>
ArithmeticError: Quantity::operator +(): Unit mismatch in plus operation
>>>
Zoltan
Posts: 62
Joined: Wed Jul 07, 2021 10:08 am

Re: Unit mismatch error in FreeCAD 0.20

Post by Zoltan »

TheMarkster wrote: Wed Jun 29, 2022 5:24 pm import math
>>> P1.Y
2.875 mm
>>> math.sqrt(P1.Y)
1.695582495781317
>>> math.sqrt(P1.Y)+P1.Y
Traceback (most recent call last):
File "<input>", line 1, in <module>
ArithmeticError: Quantity::operator +(): Unit mismatch in plus operation
>>>
This is indeed the problem. Your code worked in FreeCAD 0.19, so I guess there was implicit conversion for the units. On the other hand, the sqrt function in the Expression Engine may propagate the units as opposed to math.sqrt, which removes the unit as you demonstrated. So I am still puzzled.
Zoltan
Posts: 62
Joined: Wed Jul 07, 2021 10:08 am

Re: Unit mismatch error in FreeCAD 0.20

Post by Zoltan »

onekk wrote: Wed Jun 29, 2022 5:19 pm You will easily see that P1.X will return units, and 10 has no units in your code, in my test code it will print correctly
But probably expression should allow "unitless" operators?
Thank you, Carlo! You found the error.

Here is the summary:
  • Additive operators (+ and -) require consistency in the units
  • Multiplicative operators (* and /) perform implicit conversion, so consistency in the units is not necessary
  • The expression engine must have changed since version 0.19, in which additive operators were agnostic to units
Zoltan
Posts: 62
Joined: Wed Jul 07, 2021 10:08 am

Re: Unit mismatch error in FreeCAD 0.20

Post by Zoltan »

I made some detective work and I think I found the source of the problem. Here are the steps I went through, hopefully it will be useful for others when encountering issues with FreeCAD.

  1. Simplify the problem
    Thanks to onekk, I know exactly which part of the expression causes the error. So I came up with a minimum working example (MWE):

    Code: Select all

    >>> from FreeCAD import Units
    >>> Units.Quantity(1.0, Units.Unit(1)) + 2
    3.0 mm
    
  2. Browsing GitHub for existing issues, PRs and commits
    The search term unit mismatch did not give answer to my problem. Same on the old issue tracker.
  3. Checking the documentation
    The corresponding wiki page gives an example for the addition of units, right at the beginning:
    Operators and functions are unit-aware, and require valid combinations of units, if supplied. For example, 2mm + 4mm is a valid expression, while 2mm + 4 is not (the reason for this is that an expression like 1in + 4 will most likely be interpreted as 1in + 4in by humans, but all units are converted to the SI system internally, and the system is not able to guess this).
    Therefore, according to the wiki, my example should not work! Maybe it was introduced in a later version?
  4. Finding when the feature was introduced
    I clicked on View history at the top right corner to find out when the referenced sentence was written. Looking at the complete history, it turned out that even the very first wiki entry mentioned it. And that entry was written in September 2015, well before FreeCAD 0.19!
    Then I realized that I was using the RealThunder fork of FreeCAD 0.19. So I downloaded the official version 0.19.3, the latest bugfix release available for Linux. My MWE fails there. This means that adding a unitless quantity to a length is supported only in the RealThunder fork, not in base FreeCAD. Although I could not find it.
Conclusion: since I do not need the Assembly 3 workbench, I will use the official FreeCAD releases.
Post Reply