Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Assembly] Solve the assembly (Card 9). #10764

Merged
merged 22 commits into from
Feb 13, 2024

Conversation

PaddleStroke
Copy link
Contributor

@PaddleStroke PaddleStroke commented Sep 21, 2023

Adds AssemblyObject and viewer in cpp that handle the solving by connecting to ondsel solver.
Fixes #10753
Fixes #10749
Fixes #10754
Fixes #10479
Fixes #11311
Fixes #10751
Fixes #11397
Fixes #10815
Fixes #11606
Fixes #10752

@github-actions github-actions bot added the Mod: Assembly Related to the Integrated Assembly Workbench label Sep 21, 2023
@wwmayer
Copy link
Contributor

wwmayer commented Sep 21, 2023

I can't give a qualified answer about whether these classes are needed or not as I don't know much about assemblies and their requirements.

But for the new code you should use the new copyright header and also listen to the warnings reported by Lint.

@PaddleStroke
Copy link
Contributor Author

Assembly are very similar to sketches actually. You have elements and constraints and you need to solve.

Yes for copyrights and warning, it was just an early draft to open discussion.

@wwmayer
Copy link
Contributor

wwmayer commented Sep 21, 2023

Assembly are very similar to sketches actually. You have elements and constraints and you need to solve.

I know what the assembly is good for but not much beyond that.

@PaddleStroke
Copy link
Contributor Author

So my next step is to be able to create an AssemblyObject in python :
App.ActiveDocument.addObject("Assembly::AssemblyObject", "Assembly")
But it is not working yet. My binding must be missing something but I can't find what. Any idea ?

@PaddleStroke
Copy link
Contributor Author

PaddleStroke commented Sep 22, 2023

AssemblyObjectPy.cpp(20,25): error C2871: 'Assembly': a namespace with this name does not exist

@wwmayer any idea what is wrong with the namespace ? I can't understand what is happening. In visual studio when I follow the error to the generated AssemblyObjectPy.cpp file, the namespace is error-highlighted, then after 2 seconds it becomes ok as if the error is resolved. I tried to follow PartPy example and can't find any difference.

The namespace is declared in AssemblyObject.h.
The cmakefiles follows the same structure as sketcher app cmakefiles.

@FlachyJoe
Copy link
Contributor

Another way could be to delegate the solve to a App::Part child (a solver object) who get the joints by parsing it's parent. The FEM solver is working as this.

@wwmayer
Copy link
Contributor

wwmayer commented Sep 22, 2023

// clang-format off
// inclusion of the generated files (generated out of AssemblyObject.xml)
#include "AssemblyObjectPy.h"
#include "AssemblyObjectPy.cpp"
// clang-format on

@wwmayer
Copy link
Contributor

wwmayer commented Sep 25, 2023

FYI, the workaround with clang-format off/on is not needed any more because the sorting of header file has been disabled: b65ae56

@PaddleStroke
Copy link
Contributor Author

Ah thanks !
I see now clang was reversing the .h and .cpp. Thanks very much. I'll continue on it now.

@PaddleStroke
Copy link
Contributor Author

I am still unable to create the object in python. Any idea what is missing here ?
Is there a template about how to add a DocumentObject class somewhere ?

@wwmayer
Copy link
Contributor

wwmayer commented Sep 25, 2023

What are you trying to do?

@PaddleStroke
Copy link
Contributor Author

PaddleStroke commented Sep 25, 2023

So I want to make a subclass of App::Part called Assembly::AssemblyObject.
This subclass will have a 'solve' function that will solve the assembly based on its joint objects.

So now my goal is to already make a dummy subclass of App::Part and be able to create this object from python :
App.ActiveDocument.addObject("Assembly::AssemblyObject", "Assembly")
And as of now the creation in python does not work.

@wwmayer
Copy link
Contributor

wwmayer commented Sep 25, 2023

You have to register the class AssemblyObject to FreeCAD's type system. Now in your case you have created a Python extension module AssemblyApp and a Python package Assembly. But the prefix name of the types is Assembly instead of AssemblyApp.

To fix this issue you should:

  • Add the file AppAssembly.cpp to Assembly/App. Have a look at AppPartDesign.cpp how to implement the function.
    Important: Replace _PartDesign with AssemblyApp
  • Add the file AppAssemblyPy.cpp. Also have a look at AppPartDesignPy.cpp how to implement it
  • In Assembly/Assembly/__init__.py add the line import AssemblyApp

@PaddleStroke
Copy link
Contributor Author

PaddleStroke commented Sep 25, 2023

Thanks for your feedback! I did those steps, though it still doesn't work. Perhaps I am not using the name AssemblyApp at the correct places ?
I am not sure to understand what you mean by

Now in your case you have created a Python extension module AssemblyApp and a Python package Assembly. But the prefix name of the types is Assembly instead of AssemblyApp.

Does it implies something besides the steps you gave before ?

@wwmayer
Copy link
Contributor

wwmayer commented Sep 26, 2023

The AssemblyObject is created now but what's missing is the creation of its view provider. Currently AssemblyGui is a normal shared library and in order to make it a Python extension module it must define the entry point PyInit_AssemblyGui. And the type ViewProviderAssembly must be registered.
wwmayer@7d7bb90

@PaddleStroke
Copy link
Contributor Author

PaddleStroke commented Sep 27, 2023

Thanks very much, this is working properly now.
One other question: We need to get the list of Joints of the assembly.
Joints are currently App::FeaturePython objects defined in python (JointObject.py).

To get them :

std::vector<App::FeaturePython*> AssemblyObject::getJoints()
{
    std::vector<App::FeaturePython*> joints = {};

    App::Document* doc = getDocument();
    App::DocumentObject* jointsGroup = doc->getObject("Joints");

    if (jointsGroup && jointsGroup->isDerivedFrom(App::DocumentObjectGroup::getClassTypeId())) {
        for (auto* obj : static_cast<App::DocumentObjectGroup*>(jointsGroup)->getObjects()) {

            if (obj /* && obj->isDerivedFrom(App::FeaturePython::getClassTypeId())*/) {
                joints.push_back(static_cast<App::FeaturePython*>(obj));
            }
        }
    }

    return joints;
}

However I am not sure how I can test to make sure its a Joint and not another random object that ended up in the joints group.
obj->isDerivedFrom(App::FeaturePython::getClassTypeId()) does not compile, besides it would not tell if its a Joint or another random FeaturePython.

Any recommandation about the best way to handle things here ? Thanks

@wwmayer
Copy link
Contributor

wwmayer commented Sep 27, 2023

#include <App/PropertyPythonObject.h>
#include <Base/Interpreter.h>

std::vector<App::DocumentObject*> Assembly::getJoints() const
{
    std::vector<App::DocumentObject*> joints = {};

    App::Document* doc = getDocument();
    App::DocumentObject* jointsGroup = doc->getObject("Joints");

    Base::PyGILStateLocker lock;
    if (jointsGroup && jointsGroup->isDerivedFrom(App::DocumentObjectGroup::getClassTypeId())) {
        for (auto* obj : static_cast<App::DocumentObjectGroup*>(jointsGroup)->getObjects()) {
            App::PropertyPythonObject* proxy = obj ? dynamic_cast<App::PropertyPythonObject*>(obj->getPropertyByName("Proxy")) : nullptr;
            if (proxy) {
                Py::Object joint = proxy->getValue();
                if (joint.hasAttr("setJointConnectors")) {
                    joints.push_back(obj);
                }
            }
        }
    }

    return joints;
}

@PaddleStroke
Copy link
Contributor Author

@chennes What is the standard procedure to add a library to freecad ? I am now looking into how to include the OndselSolver and I'm not sure how to proceed.
So now I have a OndselSolver.lib and I created a file SetupLibOndselSolver.cmake. What are the next steps?

@wwmayer
Copy link
Contributor

wwmayer commented Oct 4, 2023

OndselSolver is GPLv2 only [1].
Its usage in FreeCAD is not allowed [2] because it conflicts with the QSint library [3] that is LGPLv3 only.

[1] https://github.com/Ondsel-Development/OndselSolver/blob/main/LICENSE
[2] https://www.gnu.org/licenses/gpl-faq.html#AllCompatibility
[3] https://marketplace.qt.io/products/qsint

@PaddleStroke
Copy link
Contributor Author

I think we will find a solution to this @sliptonic ?
Meanwhile my goal is to get things ready so what I want to do is mostly to add the library locally to test things out.

@sliptonic
Copy link
Member

OndselSolver is GPLv2 only [1].

Should be LGPL. I'll investigate and revise

@wwmayer
Copy link
Contributor

wwmayer commented Oct 4, 2023

Should be LGPL. I'll investigate and revise

Oops, it is LGPL. I missed the word "Library" in the license terms. Sorry for the noise!
The old version (from 1991) of the license text use the word "library" while the newer version (from 1999) use the word "lesser" but both versions have the same meaning.

@wwmayer
Copy link
Contributor

wwmayer commented Oct 4, 2023

So now I have a OndselSolver.lib and I created a file SetupLibOndselSolver.cmake. What are the next steps?

What about adding it as git sub-module?

PaddleStroke and others added 22 commits February 13, 2024 08:25
…ther than to the doc origin.

This enable 'detaching' them, so that they are not recomputed
Remove exportASMT from toolbar.
Fix Fixedjoint name and tooltip
Fix various bugs
Introduce solver drag functions.
@PaddleStroke
Copy link
Contributor Author

@chennes rebased & conflcit fixed

@chennes chennes merged commit 61ec050 into FreeCAD:main Feb 13, 2024
8 of 9 checks passed
@luisDias89
Copy link

luisDias89 commented Feb 19, 2024

Nice Workbench: FreeCAD has been waiting for this feature for a long time.
Please, whoever is developing it, try to make it easy and intuitive, like SolidWorks, for example.
When you select two faces, two disks, edges, or other object items, it will analyze all the possibilities that could be achieved with them and will automatically provide a menu. Initially, the menu will be semi-transparent. If the mouse cursor is moved over the menu, it becomes available; if the mouse moves away, the menu disappears.
Some Features for example for planing is make coincident, make paralel, distance betwen a range, distance only, lock, perpedicular, range of angle betwen boot, or fixed angle.

Look at this image as an example:
image

Other example is two circles:
image
We have concentric, tangent, lock...

And so on, another example: among gears, you can define when one gear rotates in relation to another, making animations super realistic, with the teeth rotating perfectly meshed.

And many other options that can be integrated.

This is the most importante workbench for large assembly, this is what the freecad need to bee a great Software.

A table with relations betwen geometric properties: easy ->
image

All of them
image

@luisDias89
Copy link

luisDias89 commented Feb 20, 2024

Exemple of Gear Assembly
Lock at the mouse, we can able to move object with mouse and see in real time one animation (min 5:39)
https://www.youtube.com/watch?v=JcOO6jcdZ_I

Watch this video from minute 24 - This is a Great Example how easy is one assebmly in other software. Freecad need This.
https://www.youtube.com/watch?v=VIC5ky8Pq8s&list=PLm1W92pCWeKNo5PqIIi7fn51-tWvzpPOv&index=8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment