Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Knot in suturing simulator
#1
Pregunta 
Hi!
I'm currently developing a suturing simulator for medicine students, and I'm having big trouble finding a way to replicate this exercise in my app (https://www.youtube.com/watch?v=DIUy3jeM6sY). As you can see from this second video (https://www.youtube.com/watch?v=5ZXG9LiYFdc), even with self and surface-based collisions activated and using only distance fields for collisions, the rope passes through itself and objects, making creating a knot impossible. Do you have any suggestions to solve or "bypass" (IDK, maybe dynamically substituting the rope blueprint with a "baked knot" by hitting a controller button at the right time?) this problem?
In the attachment, you can find screenshots of the solver and rope parameters.
Thank you for your attention!


Attached Files Thumbnail(s)
                   
Reply
#2
(18-03-2022, 04:26 PM)Portz Wrote: Hi!
I'm currently developing a suturing simulator for medicine students, and I'm having big trouble finding a way to replicate this exercise in my app (https://www.youtube.com/watch?v=DIUy3jeM6sY). As you can see from this second video (https://www.youtube.com/watch?v=5ZXG9LiYFdc), even with self and surface-based collisions activated and using only distance fields for collisions, the rope passes through itself and objects, making creating a knot impossible. Do you have any suggestions to solve or "bypass" (IDK, maybe dynamically substituting the rope blueprint with a "baked knot" by hitting a controller button at the right time?) this problem?
In the attachment, you can find screenshots of the solver and rope parameters.
Thank you for your attention!

Hi!

Can’t be sure what the problem is without really delving into specifics of your user input implementation (are these manipulators force-driven rigidbodies or simply kinematic transforms?) but one thing stands a lot in your settings: you’re using 20 collision iterations (that is, collider-particle collisions have very high priority) but only 1 particle collision iteration (very low priority for particle-particle collisions).

At the very least you should use the same amount of particle collision iterations that you do for all other constraints, since these are what determine how robust rope-rope collision detection is.
Particle friction constraints are also quite important when making knots, as these determine the quality of forces tangential to contact points.


On a side note, 20 iterations and 10 substeps is absolute overkill, it yields 200 iterations per step (not even per frame). Try 2 iterations for all constraints and 10 substeps.

Let me know whether this improves the results.
Reply
#3
(18-03-2022, 05:57 PM)josemendez Wrote: Hi!

Can’t be sure what the problem is without really delving into specifics of your user input implementation (are these manipulators force-driven rigidbodies or simply kinematic transforms?) but one thing stands a lot in your settings: you’re using 20 collision iterations (that is, collider-particle collisions have very high priority) but only 1 particle collision iteration (very low priority for particle-particle collisions).

At the very least you should use the same amount of particle collision iterations that you do for all other constraints, since these are what determine how robust rope-rope collision detection is.
Particle friction constraints are also quite important when making knots, as these determine the quality of forces tangential to contact points.


On a side note, 20 iterations and 10 substeps is absolute overkill, it yields 200 iterations per step (not even per frame). Try 2 iterations for all constraints and 10 substeps.

Let me know whether this improves the results.

Thanks for your reply!

I've first tried to set all the solver constraints to 2 (keeping 10 substeps) but did not notice significant improvements. So, I've gradually increased the most relevant ones to 5 (distance, particle collision, particle friction, collision, friction), but again, the simulation looks smoother, but the problem with the collisions and the knot remains.

Sorry, I've forgot to give some details about the interaction with the rope itself. Every manipulator has a rigidbody, set to kinematic while grabbed by the user.
For the rope grabbing script I've followed an old thread. This is my code: all the manipulators have a small obi collider in the pliers' region, used only for this interaction.

using UnityEngine;
using Obi;



public class RopePicker : BaseCommand
{
    [SerializeField] float _sensitivity = 0.1f;
    [SerializeField] ObiRope _rope;

    private bool canGrab = true;
    ObiSolver solver;
    ObiCollider obiCollider;
    ObiSolver.ObiCollisionEventArgs collisionEvent;
    ObiPinConstraintsBatch newBatch;
    ObiConstraints<ObiPinConstraintsBatch> pinConstraints;
   
    void Awake()
    {
        solver = FindObjectOfType<ObiSolver>();
        obiCollider = GetComponent<ObiCollider>();
    }
   
    // Start is called before the first frame update
    void Start()
    {
        // get a hold of the constraint type we want, in this case, pin constraints:
        pinConstraints = _rope.GetConstraintsByType(Oni.ConstraintType.Pin) as ObiConstraints<ObiPinConstraintsBatch>;
    }

    private void OnEnable()
    {
        if (solver != null)
            solver.OnCollision += Solver_OnCollision;
    }

    private void OnDisable()
    {
        if (solver != null)
            solver.OnCollision -= Solver_OnCollision;
    }

    private void Solver_OnCollision(object sender, Obi.ObiSolver.ObiCollisionEventArgs e)
    {
        collisionEvent = e;
    }
   
    public override void Activate(float value)
    {
        if (value > _sensitivity)
        {
            Grab();
        }
        else
        {
            Release();
        }
    }
   
    public void Grab()
    {
        var world = ObiColliderWorld.GetInstance();
        //Debug.Log(pinConstraints);

        if (solver != null && collisionEvent != null)
        {
            //Debug.Log("Collision");
            foreach (Oni.Contact contact in collisionEvent.contacts)
            {
                if (contact.distance < 0.00001f)
                {
                    var contactCollider = world.colliderHandles[contact.bodyB].owner;
                    ObiSolver.ParticleInActor pa = solver.particleToActor[contact.bodyA];

                    //Debug.Log(pa + " hit " + contactCollider);
                    if (canGrab)
                    {
                        if (contactCollider == obiCollider)
                        {
                            //Debug.Log("Hand Collision");
                            var batch = new ObiPinConstraintsBatch();
                            int solverIndex = _rope.solverIndices[contact.bodyA];
                            Vector3 positionWS = solver.transform.TransformPoint(solver.positions[solverIndex]); // particle position from solver to world space
                            Vector3 positionCS = obiCollider.transform.InverseTransformPoint(positionWS); // particle position from world to collider space
                            batch.AddConstraint(_rope.solverIndices[contact.bodyA], obiCollider, positionCS, Quaternion.identity, 0, 0, float.PositiveInfinity);
                            batch.activeConstraintCount = 1;
                            newBatch = batch;
                            pinConstraints.AddBatch(newBatch);

                            canGrab = false;

                            // this will cause the solver to rebuild pin constraints at the beginning of the next frame:
                            _rope.SetConstraintsDirty(Oni.ConstraintType.Pin);
                        }
                    }
                }
            }
        }
    }
   
   
    public void Release()
    {
        if (!canGrab)
        {
            //Debug.Log("Release");
            pinConstraints.RemoveBatch(newBatch);
            _rope.SetConstraintsDirty(Oni.ConstraintType.Pin);
            canGrab = true;
        }
    }
}


Thanks again for your help!
Reply
#4
(21-03-2022, 11:02 AM)Portz Wrote: Every manipulator has a rigidbody, set to kinematic while grabbed by the user.

Kinematic rigidbodies have infinite mass. In practice this means they will ignore any forces exerted upon them, and they will apply infinite force to any object interacting with them.

In the case of a rope attached to a kinematic rigidbody, this means the rope won't be able to prevent rigidbody movement once it's tensed up. Instead, the rigidbody will pull from it with infinite force. This will not only undo any knots in the rope, but also allow it to stretch indefinitely.

If you want the rope to be able to act upon the manipulator, you need to keep the manipulator non-kinematic and move it around using forces/accelerations.
Reply
#5
(22-03-2022, 11:41 AM)josemendez Wrote: Kinematic rigidbodies have infinite mass. In practice this means they will ignore any forces exerted upon them, and they will apply infinite force to any object interacting with them.

In the case of a rope attached to a kinematic rigidbody, this means the rope won't be able to prevent rigidbody movement once it's tensed up. Instead, the rigidbody will pull from it with infinite force. This will not only undo any knots in the rope, but also allow it to stretch indefinitely.

If you want the rope to be able to act upon the manipulator, you need to keep the manipulator non-kinematic and move it around using forces/accelerations.
I'm sorry to bother you again Triste .
I've tried turning the manipulators non-kinematic, but unfortunately, since I'm working on the expansion of an existing simulator, this is causing me many problems. Is there, by any chance, some workaround to keep kinematic manipulators?
Actually, my goal is to replicate the movements of the pliers in the first video with the manipulators, so the students may train on that actions. I don't need to keep the rope in that position, but just to "close" the knot, so I'm thinking: is it possible to freeze a rope section or substitute it at run time (even with an input with the controller) with another one? Because in that case, maybe I could use a closed-loop blueprint to give the feedback a correctly done exercise.
Reply
#6
(23-03-2022, 06:05 PM)Portz Wrote:
I'm sorry to bother you again Triste .
I've tried turning the manipulators non-kinematic, but unfortunately, since I'm working on the expansion of an existing simulator, this is causing me many problems. Is there, by any chance, some workaround to keep kinematic manipulators?

Having kinematic manipulators will prevent any kind of force feedback for the user, which imho is a must for any simulator. There won't be any physics going on for the user's "hands", so he won't be able to tell if he's pulling too lightly or too strong, will be able to pass/clip trough static colliders or other kinematics (unless you perform custom collision detection), etc.

Kinematic rigidbodies are -as the name implies- "non-dynamic". They ignore forces, so there's no way to get proper force simulation using them no matter what.

(23-03-2022, 06:05 PM)Portz Wrote: Actually, my goal is to replicate the movements of the pliers in the first video with the manipulators, so the students may train on that actions. I don't need to keep the rope in that position, but just to "close" the knot, so I'm thinking: is it possible to freeze a rope section or substitute it at run time (even with an input with the controller) with another one? Because in that case, maybe I could use a closed-loop blueprint to give the feedback a correctly done exercise.

While you can't "freeze" or "rigidbodify" a section of the rope, you can place an object at a given position along the rope. See the Assets/Obi/Scripts/RopeAndRod/Utils/ObiRopeAttach.cs utility script: add it to any object you want to attach to the rope, and then set its "m" coordinate (normalized coord along the rope, 0 means start and 1 means end) to place the object along it.

kind regards,
Reply
#7
(24-03-2022, 08:47 AM)josemendez Wrote: Having kinematic manipulators will prevent any kind of force feedback for the user, which imho is a must for any simulator. There won't be any physics going on for the user's "hands", so he won't be able to tell if he's pulling too lightly or too strong, will be able to pass/clip trough static colliders or other kinematics (unless you perform custom collision detection), etc.

Kinematic rigidbodies are -as the name implies- "non-dynamic". They ignore forces, so there's no way to get proper force simulation using them no matter what.


While you can't "freeze" or "rigidbodify" a section of the rope, you can place an object at a given position along the rope. See the Assets/Obi/Scripts/RopeAndRod/Utils/ObiRopeAttach.cs utility script: add it to any object you want to attach to the rope, and then set its "m" coordinate (normalized coord along the rope, 0 means start and 1 means end) to place the object along it.

kind regards,

Ok, clear, I'll try this way!
Thank you again for the help!
Reply
#8
(18-03-2022, 04:26 PM)Portz Wrote: Hi!
I'm currently developing a suturing simulator for medicine students, and I'm having big trouble finding a way to replicate this exercise in my app (https://www.youtube.com/watch?v=DIUy3jeM6sY). As you can see from this second video (https://www.youtube.com/watch?v=5ZXG9LiYFdc), even with self and surface-based collisions activated and using only distance fields for collisions, the rope passes through itself and objects, making creating a knot impossible. Do you have any suggestions to solve or "bypass" (IDK, maybe dynamically substituting the rope blueprint with a "baked knot" by hitting a controller button at the right time?) this problem?
In the attachment, you can find screenshots of the solver and rope parameters.
Thank you for your attention!

I'm making a similar thing and I'm facing the same issue. In addition, when going through the "skin", the particles inside the skin object get really crazy. Any idea about how to achieve that?
Reply
#9
(25-03-2022, 11:04 AM)manurocker95 Wrote: I'm making a similar thing and I'm facing the same issue. In addition, when going through the "skin", the particles inside the skin object get really crazy. Any idea about how to achieve that?

Is the skin a collider? in that case, particles might simply be trying to get out of it which is completely normal. you might want to disable collision between these particles and the collider using collision filters., which can also be set on a per-particle basis at runtime, see the very end of: http://obi.virtualmethodstudio.com/manua...sions.html
Reply
#10
(25-03-2022, 01:31 PM)josemendez Wrote: Is the skin a collider? in that case, particles might simply be trying to get out of it which is completely normal. you might want to disable collision between these particles and the collider using collision filters., which can also be set on a per-particle basis at runtime, see the very end of: http://obi.virtualmethodstudio.com/manua...sions.html

I would like to achieve something like this: 

[video=youtube]http://https://youtu.be/wnmFIdYDWhI[/video]

The thing is what would be the best approach to know when the particles are passing through the "skin" so I can pull from it without the particles being crazy
Reply