Forum Replies Created
-
AuthorPosts
-
12 October 2017 at 19:06 in reply to: [SOLVED] Error while Adding Compliance nodes in the simulation (Compliant module) #10072maxBlocked
Hello Mahmoud,
I’m not exactly sure what you mean by adding/removing components, but if you’re doing it from a python script controller, then make sure to call
init()
on the compliance component you create dynamically (i.e. not at scene creation).The
init
method is called automatically for you on scene creation, but it is not called on components created *after*, so this might fix your issue.Hope this helps,
29 September 2017 at 20:03 in reply to: [SOLVED] Visualizing DiagonalCompliance (Compliance Plugin) #10022maxBlockedHi Mahmoud,
Since compliances are generally expressed on point differences (or relative rigid transforms, in your case), it will be a little difficult to visualize directly.
Basically you have two options:
– implement some custom opengl drawing code in DiagonalCompliance::draw, but keep in mind that your compliance works on the relative transformation between your two rigid frames and you don’t have access to the source rigid frames
– use a python script controller to either:
a. debug using print() calls in the entry points onBeginAnimationStep/onEndAnimationStep
b. implement custom rendering in the draw entry point, using PyOpengGL. From there it is fairly easy to access your rigid frame dofs and draw stuff accordingly.Probably the easiest way will be to use python, but it will not scale very well if you have plenty of these. However, for debugging purpose it should be fine.
Hope this helps,
maxBlockedHi Sen,
It’s not clear whether you want the SOFA algorithm or the general idea.
I’ll give you the general idea, but for the details you need to look it up yourself. And if you need the SOFA way, just study the default scene (the snake).
The collision detection between two objects gives you a normal direction and a 2D tangent plane. The normal force is obtained using a linear complementarity problem (LCP) to prevent penetration of the objects (unilateral constraint).
The tangent force is more complex as it needs to satisfy Coulomb’s Law for frictional contacts: ||f_T|| <= \mu f_N
So you see that both normal and tangent forces are coupled: if you change f_N you need to update f_T and conversely.
Now, there are several methods to solve this problem (which is *hard*):
– non-symmetric LCP using an approximate friction pyramid (IIRC Anitescu & Potra 97?)
– coupled convex-qp a.k.a staggered projections (Kaufman 2008?) with Gauss-Seidel variants that work well in practice
– a variant of Lemke’s algorithm for friction cones by Baraff (91?)
– coupled second-order cone projections by Cadoux 2009?
– and many others I don’t remember ๐There are other approximate schemes depending on the friction model you want.
Best,
maxBlockedHi all,
The problem with
RigidMapping
is that the displacement field will be rigid: your deformable object will no-longer be able to deform once its DOFs are mapped rigidly from a rigid frame.There might be a workaround in the scene you mentioned
DeformableOnRigidFrameMapping
, but I suspect there will be numerical issues since the DOFs become redundant: you can translate the rigid frame and your points (in the local rigid frame) in opposite directions and get no motion in the world frame. Maybe the mapping in the example deals with this issue, I don’t know.But more generally, what you really need is to attach both ends of your muscles to the bone. For that you need to
RigidMap
attach points from the rigid body, then place a stiff spring or a constraint between the attach point and some point on your muscle.HTH,
maxBlockedHi all,
Just to mention that it is *way* easier to write scenes in Python, unless you *really* have to do it in c++.
In any case, the learning curve for grasping SOFA concepts will be much less steep using Python, since you’ll just focus on the scene creation rather than SOFA internal book-keeping.
Should you choose this option, you need to enable the
SofaPython
plugin during compilation. Then a minimal python scene would look like:def createScene(node): # create a node in the scene graph (i.e. 'Node' in xml scenes) child_node = node.createChild('child name') # create a component under the graph node child_dofs = child_node.createObject('MechanicalObject', template = 'Vec3', name = 'dofs')
Please refer to the documentation for more.
Hope this helps,
maxBlockedHello again,
Most likely CMake did not take the changes into account. Try reconfiguring the project using
cmake-gui
or start a clean build:cd sofa; mkdir -p build; cd build; cmake ..
BTW if anyone has a way to force cmake reconfiguration from the command-line, please let me know ๐
Also, maybe we should mark GLEW as required in the CMakeLists.txt so that users don’t make it to the compilation phase unless GLEW is installed.
Best regards,
maxBlockedHello again,
Most likely you don’t have GLEW installed. On Debian/Ubuntu, try
sudo apt-get install libglew-dev
.Hope this helps,
Maxime
maxBlockedHello Elek,
You need a c++11 compiler for compiling SOFA, e.g. gcc >= 4.6.
Best regards,
Maxime
maxBlockedHello Elek,
Your issues are Github-related and not specific to SOFA, so your questions are off-topic here.
I don’t know about the Github Desktop, but you can definitely ‘git clone’ using the address just above the two buttons on the webpage.
The documentation for GitHub Desktop can be found here: https://help.github.com/desktop/guides/getting-started/
You should first make sure that everything is configured properly.
A complete guide to pull requests is also available: https://help.github.com/categories/collaborating-with-issues-and-pull-requests/
Basically, this goes: fork, clone, branch, hack-commit-hack-commit…, push, then use the web interface to file a pull request on your clone branch once ready.
Hope this helps,
Maxime.
10 February 2017 at 16:40 in reply to: [SOLVED] End simulation from a python script controller #8562maxBlockedHello again,
Sorry for misunderstanding your request.
It turns out I have the exact same problem as yours, and a fix is being discussed here.
So you need a little more patience ๐
Best,
10 February 2017 at 15:59 in reply to: [SOLVED] Rigid flexible body collision/deformation (anatomy modeling) #8561maxBlockedHello @jlefley,
As Hugo said, having your scene file would help but here are some general considerations.
For collisions to happen you need to:
1. setup the collision pipeline
2. have collision models on the objects you want to collide, e.g. for meshes, add a TriangleModel next to the topology describing your mesh
3. use a numerical solver that can handle contacts, depending on the contact response chosen in 1.For 1, you need to add:
– DefaultPipeline, that tells the animation loop to enable collision detection,
– BruteForceDetection, that setup a naive O(n2) collision detection pass between collision models,
– NewProximityIntersection that computes the intersections, distances and contact points based on member data alarmDistance and contactDistance
– DefaultContactManager, which is responsible for creating the response graph sections in case of a collision (mapping a point from its parent dofs, putting forcefields/constraints, etc). The contact manager has a ‘response’ attribute describing which response class to use, and a ‘responseParams’ string that sets attributes for the response class (yes I know this is complicated!)Some of the examples in the core SOFA repository have penalty force constraints, but the general idea should be the same. The default SOFA scene (the snake) is a deformable object with frictional contacts IIRC, so my advice is to study this scene to see how things are setup.
Best,
maxBlockedHello,
Try setting the ‘animate’ attribute of the root node to False in the script.
Best,
maxBlockedHello Wong,
You are correct, when bilateral/unilateral constraints are defined on the system, the compliant plugin builds the KKT system corresponding to the QP to be solved.
This is the job of the OdeSolver/integrator component: it takes an integration scheme and the system state, and builds a QP for the numerical solver to solve. The standard one in Compliant is CompliantImplicitSolver, which is Implicit Euler time integration.
Now, there are various choices for solving the QP: you could work from the large indefinite KKT system directly, or you could compute the Schur complement then solve a smaller LCP instead. The standard for Compliant would be SequentialSolver, which is a Projected Gauss-Seidel-like LCP solver. It can also handle frictional constraints, but there may be anisotropy in the result so use it with caution.
If you only have bilateral constraints though, you might prefer iterative solvers like MinresSolver, or direct solvers like LDLTSolver depending on your requirements for speed/precision.
So the numerical solver solves the QP and computes Lagrange multipliers corresponding to contraint forces, then feed them back to the ode solver, which steps the system forward in time.
IIRC, most (all?) ode solvers in Compliant have a “propagate_lambda” flag that will cause the constraint forces to be written at the end of the time step in the “force” state vector of the degrees of freedom where the corresponding compliance component is defined, and these forces will be propagated all the way up to the independent dofs through the mapping Jacobian transposes.
This means that if you enable the flag on a scene with contacts, at the end of any time step the force vector for independent dofs will containt the **net** constraint forces (the sum of all the constraints acting on this object), which you can further process using e.g. a python script controller.
Let me know if you need help with this, I will try to add a simple example to demonstrate it.
Best,
maxBlockedHi Wong,
If you want a nice intro to constrained dynamics, I suggest you start with David Baraff’s SIGGRAPH courses: https://www.cs.cmu.edu/~baraff/sigcourse/. A bit old but still relevant.
Generally, constrained dynamics involve solving a system of equations for constraint forces (usually noted lambda) so that the dynamics satisfy some constraints. In most cases, after proper time discretization the problem to solve is a quadratic program (QP), for which different (read: a whole lot of) solvers exist based on the properties of the QP.
In the case of Implicit Euler time stepping, the matrix A will be the inverse of the integration matrix A = inv(M – h^2 K) and matrix H will be the Jacobian matrix for the constraint mapping.
Because there are some many possible combination of (constrained) time-stepping schemes and constraint solvers, there are many ways of formulating constrained dynamics in SOFA. Unfortunately, I do not know what is the preferred/official way of dealing with this.
However, I can point you to the Compliant plugin that has a simple approach to it: the Compliant plugin defines Compliance components that act like the inverse of Stiffness components (i.e. ForceFields). In some sense, kinematic constraints are like infinitely stiff materials, which correspond to zero compliance.
For instance, you can consider a distance constraint between two points as an infinitely stiff spring between the points. So the Compliant plugin approach is this: you just put Compliance components at the end of mappings, the output of which should be constrained to zero, then using the adequate solvers you get constrained dynamics. Using non-zero compliance gives you soft constraints. For more information, you may check the examples.
Hope this helps,
4 April 2016 at 10:40 in reply to: [SOLVED] I am confused on the dependencies when compiling Sofa On WIN10. vs2015 #6451maxBlockedHi Sen,
I just stumbled upon the exact same issue, and found a solution: you need to export the CMAKE_PREFIX_PATH environment variable to your Qt directory before configuring the project in CMake.
EDIT example: C:\Qt\Qt5.3.2\5.3\msvc2013_opengl in my case
See http://stackoverflow.com/questions/15639781/how-to-find-qt5-cmake-module-on-windows for reference.
HTH,
maxBlockedHello Lionel,
The position vector is copied when accessed from python, so you need to copy it back for the changes to happen. When using numpy arrays, you also need to convert it to a python list first using .tolist(). Here is a short example:
import numpy as npdef createScene(node):
# create some dofs
dofs = node.createObject('MechanicalObject', template = 'Vec3')# positions are copied
pos = dofs.position# modification
pos[0][0] = 1# debug
print 'before:', dofs.position# commit changes
dofs.position = pos# debug
print 'after:', dofs.position# numpy array
pos = np.zeros( (10, 3) )
dofs.position = pos.tolist()print 'numpy:', dofs.position
Hope this helps.
Best,
max.
edit: we really need a preview system for posts + unescaped code characters
maxBlockedHello Deimel, and sorry for the delay.
You are correct, the multiplication order is inconsistent.
2c9f6b4 on master applies your changes (+ float rigid types). Do we need to backport it to another branch ?
Thanks again for your patch.
Best,
max.
maxBlockedHello Raphael,
I had a quick look at your test scene and it seems that the
repartition
is the issue.More precisely, if you get rid of the repartition field in the mapping, like this:
<RigidRigidMapping globalToLocalCoords="1" />
then the problem seems to go away. Can you confirm this ?
The semantic for
repartition
is somewhat complex, and admittedly the doc does not help much. I did not dwelve into it yet (anyone?) but as long as you simply want 1->1 mappings between rigid bodies, you’d better removerepartition
andindex
informations altogether.Hope this helps,
Maxime
-
AuthorPosts