feat(solver): refactor AssemblyObject to use IKCSolver interface (#295)
Rewire AssemblyObject to call through KCSolve::IKCSolver instead of directly manipulating OndselSolver ASMT types. Key changes: - Remove all 30+ #include <OndselSolver/*> from AssemblyObject.cpp - Remove MbDPartData, objectPartMap, mbdAssembly members - Add solver_ (IKCSolver), lastResult_ (SolveResult), partIdToObjs_ maps - New buildSolveContext() builds SolveContext from FreeCAD document objects with JointType/DistanceType -> BaseJointKind decomposition - New computeMarkerTransform() replaces handleOneSideOfJoint() - New computeRackPinionMarkers() replaces getRackPinionMarkers() - Rewrite solve/preDrag/doDragStep/postDrag/generateSimulation to call through IKCSolver interface - Rewrite setNewPlacements/validateNewPlacements to use SolveResult - Rewrite updateSolveStatus to use ConstraintDiagnostic - Add export_native() to IKCSolver for ASMT export support - Register OndselAdapter at Assembly module init in AppAssembly.cpp - Remove OndselSolver from Assembly_LIBS (linked transitively via KCSolve) Assembly module now has zero OndselSolver includes. All solver coupling is confined to KCSolve/OndselAdapter.cpp.
This commit is contained in:
@@ -26,6 +26,8 @@
|
||||
#include <Base/Interpreter.h>
|
||||
#include <Base/PyObjectBase.h>
|
||||
|
||||
#include <Mod/Assembly/Solver/OndselAdapter.h>
|
||||
|
||||
#include "AssemblyObject.h"
|
||||
#include "AssemblyLink.h"
|
||||
#include "BomObject.h"
|
||||
@@ -54,6 +56,10 @@ PyMOD_INIT_FUNC(AssemblyApp)
|
||||
}
|
||||
|
||||
PyObject* mod = Assembly::initModule();
|
||||
|
||||
// Register the built-in OndselSolver adapter with the solver registry.
|
||||
KCSolve::OndselAdapter::register_solver();
|
||||
|
||||
Base::Console().log("Loading Assembly module... done\n");
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,24 +25,21 @@
|
||||
#ifndef ASSEMBLY_AssemblyObject_H
|
||||
#define ASSEMBLY_AssemblyObject_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
#include <Mod/Assembly/AssemblyGlobal.h>
|
||||
#include <Mod/Assembly/Solver/Types.h>
|
||||
|
||||
#include <App/FeaturePython.h>
|
||||
#include <App/Part.h>
|
||||
#include <App/PropertyLinks.h>
|
||||
|
||||
#include <OndselSolver/enum.h>
|
||||
|
||||
namespace MbD
|
||||
namespace KCSolve
|
||||
{
|
||||
class ASMTPart;
|
||||
class ASMTAssembly;
|
||||
class ASMTJoint;
|
||||
class ASMTMarker;
|
||||
class ASMTPart;
|
||||
} // namespace MbD
|
||||
class IKCSolver;
|
||||
} // namespace KCSolve
|
||||
|
||||
namespace App
|
||||
{
|
||||
@@ -105,7 +102,6 @@ public:
|
||||
|
||||
void exportAsASMT(std::string fileName);
|
||||
|
||||
Base::Placement getMbdPlacement(std::shared_ptr<MbD::ASMTPart> mbdPart);
|
||||
bool validateNewPlacements();
|
||||
void setNewPlacements();
|
||||
static void redrawJointPlacements(std::vector<App::DocumentObject*> joints);
|
||||
@@ -114,42 +110,8 @@ public:
|
||||
// This makes sure that LinkGroups or sub-assemblies have identity placements.
|
||||
void ensureIdentityPlacements();
|
||||
|
||||
// Ondsel Solver interface
|
||||
std::shared_ptr<MbD::ASMTAssembly> makeMbdAssembly();
|
||||
void create_mbdSimulationParameters(App::DocumentObject* sim);
|
||||
std::shared_ptr<MbD::ASMTPart> makeMbdPart(
|
||||
std::string& name,
|
||||
Base::Placement plc = Base::Placement(),
|
||||
double mass = 1.0
|
||||
);
|
||||
std::shared_ptr<MbD::ASMTPart> getMbDPart(App::DocumentObject* obj);
|
||||
// To help the solver, during dragging, we are bundling parts connected by a fixed joint.
|
||||
// So several assembly components are bundled in a single ASMTPart.
|
||||
// So we need to store the plc of each bundled object relative to the bundle origin (first obj
|
||||
// of objectPartMap).
|
||||
struct MbDPartData
|
||||
{
|
||||
std::shared_ptr<MbD::ASMTPart> part;
|
||||
Base::Placement offsetPlc; // This is the offset within the bundled parts
|
||||
};
|
||||
MbDPartData getMbDData(App::DocumentObject* part);
|
||||
std::shared_ptr<MbD::ASMTMarker> makeMbdMarker(std::string& name, Base::Placement& plc);
|
||||
std::vector<std::shared_ptr<MbD::ASMTJoint>> makeMbdJoint(App::DocumentObject* joint);
|
||||
std::shared_ptr<MbD::ASMTJoint> makeMbdJointOfType(App::DocumentObject* joint, JointType jointType);
|
||||
std::shared_ptr<MbD::ASMTJoint> makeMbdJointDistance(App::DocumentObject* joint);
|
||||
std::string handleOneSideOfJoint(
|
||||
App::DocumentObject* joint,
|
||||
const char* propRefName,
|
||||
const char* propPlcName
|
||||
);
|
||||
void getRackPinionMarkers(
|
||||
App::DocumentObject* joint,
|
||||
std::string& markerNameI,
|
||||
std::string& markerNameJ
|
||||
);
|
||||
int slidingPartIndex(App::DocumentObject* joint);
|
||||
|
||||
void jointParts(std::vector<App::DocumentObject*> joints);
|
||||
JointGroup* getJointGroup() const;
|
||||
ViewGroup* getExplodedViewGroup() const;
|
||||
template<typename T>
|
||||
@@ -169,8 +131,6 @@ public:
|
||||
const std::vector<App::DocumentObject*>& excludeJoints = {}
|
||||
);
|
||||
std::unordered_set<App::DocumentObject*> getGroundedParts();
|
||||
std::unordered_set<App::DocumentObject*> fixGroundedParts();
|
||||
void fixGroundedPart(App::DocumentObject* obj, Base::Placement& plc, std::string& jointName);
|
||||
|
||||
bool isJointConnectingPartToGround(App::DocumentObject* joint, const char* partPropName);
|
||||
bool isJointTypeConnecting(App::DocumentObject* joint);
|
||||
@@ -210,7 +170,7 @@ public:
|
||||
|
||||
std::vector<App::DocumentObject*> getMotionsFromSimulation(App::DocumentObject* sim);
|
||||
|
||||
bool isMbDJointValid(App::DocumentObject* joint);
|
||||
bool isJointValid(App::DocumentObject* joint);
|
||||
|
||||
bool isEmpty() const;
|
||||
int numberOfComponents() const;
|
||||
@@ -259,12 +219,56 @@ public:
|
||||
fastsignals::signal<void()> signalSolverUpdate;
|
||||
|
||||
private:
|
||||
std::shared_ptr<MbD::ASMTAssembly> mbdAssembly;
|
||||
// ── Solver integration ─────────────────────────────────────────
|
||||
|
||||
KCSolve::IKCSolver* getOrCreateSolver();
|
||||
|
||||
KCSolve::SolveContext buildSolveContext(
|
||||
const std::vector<App::DocumentObject*>& joints,
|
||||
bool forSimulation = false,
|
||||
App::DocumentObject* sim = nullptr
|
||||
);
|
||||
|
||||
KCSolve::Transform computeMarkerTransform(
|
||||
App::DocumentObject* joint,
|
||||
const char* propRefName,
|
||||
const char* propPlcName
|
||||
);
|
||||
|
||||
struct RackPinionResult
|
||||
{
|
||||
std::string partIdI;
|
||||
KCSolve::Transform markerI;
|
||||
std::string partIdJ;
|
||||
KCSolve::Transform markerJ;
|
||||
};
|
||||
RackPinionResult computeRackPinionMarkers(App::DocumentObject* joint);
|
||||
|
||||
// ── Part ↔ solver ID mapping ───────────────────────────────────
|
||||
|
||||
// Maps a solver part ID to the FreeCAD objects it represents.
|
||||
// Multiple objects map to one ID when parts are bundled by Fixed joints.
|
||||
struct PartMapping
|
||||
{
|
||||
App::DocumentObject* obj;
|
||||
Base::Placement offset; // identity for primary, non-identity for bundled
|
||||
};
|
||||
std::unordered_map<std::string, std::vector<PartMapping>> partIdToObjs_;
|
||||
std::unordered_map<App::DocumentObject*, std::string> objToPartId_;
|
||||
|
||||
// Register a part (and recursively its fixed-joint bundle when bundleFixed is set).
|
||||
// Returns the solver part ID.
|
||||
std::string registerPart(App::DocumentObject* obj);
|
||||
|
||||
// ── Solver state ───────────────────────────────────────────────
|
||||
|
||||
std::unique_ptr<KCSolve::IKCSolver> solver_;
|
||||
KCSolve::SolveResult lastResult_;
|
||||
|
||||
// ── Existing state (unchanged) ─────────────────────────────────
|
||||
|
||||
std::unordered_map<App::DocumentObject*, MbDPartData> objectPartMap;
|
||||
std::vector<std::pair<App::DocumentObject*, double>> objMasses;
|
||||
std::vector<App::DocumentObject*> draggedParts;
|
||||
std::vector<App::DocumentObject*> motions;
|
||||
|
||||
std::vector<std::pair<App::DocumentObject*, Base::Placement>> previousPositions;
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ set(Assembly_LIBS
|
||||
PartDesign
|
||||
Spreadsheet
|
||||
FreeCADApp
|
||||
OndselSolver
|
||||
KCSolve
|
||||
)
|
||||
|
||||
|
||||
@@ -157,6 +157,12 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Export solver-native debug/diagnostic file (e.g. ASMT for OndselSolver).
|
||||
/// Default: no-op. Requires a prior solve() or run_kinematic() call.
|
||||
virtual void export_native(const std::string& /*path*/)
|
||||
{
|
||||
}
|
||||
|
||||
/// Whether this solver handles fixed-joint part bundling internally.
|
||||
/// When false, the caller bundles parts connected by Fixed joints
|
||||
/// before building the SolveContext. When true, the solver receives
|
||||
|
||||
@@ -784,4 +784,13 @@ std::vector<ConstraintDiagnostic> OndselAdapter::diagnose(const SolveContext& ct
|
||||
return extract_diagnostics();
|
||||
}
|
||||
|
||||
// ── Native export ──────────────────────────────────────────────────
|
||||
|
||||
void OndselAdapter::export_native(const std::string& path)
|
||||
{
|
||||
if (assembly_) {
|
||||
assembly_->outputFile(path);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KCSolve
|
||||
|
||||
@@ -80,6 +80,7 @@ public:
|
||||
|
||||
bool is_deterministic() const override;
|
||||
bool supports_bundle_fixed() const override;
|
||||
void export_native(const std::string& path) override;
|
||||
|
||||
/// Register OndselAdapter as "ondsel" in the SolverRegistry.
|
||||
/// Call once at module init time.
|
||||
|
||||
Reference in New Issue
Block a user