Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Bug / Crash  Issue with Grasping ObiRope Using Two ToolsGood morning, I’m encountering a strange
#1
Good morning,
I’m encountering a strange issue with grasping a closed-loop ObiRope using two tools. My goal is to grasp different points on the rope with each tool, without using constraints.
The Problem:
  • If I grasp the rope with the left tool first and then with the right tool, everything works as expected. Both tools hold their grasping points correctly.
  • However, if I grasp the rope with the right tool first and then with the left tool, the following happens:
    • The right tool keeps its constraint but the grasped particle shifts to a position far away from the intended grasping point, while still visually connected to the tip of the tool.
    • The rope responds to tool movements but maintains this unnatural offset for the right tool.
  • The issue only happens when the right tool is the second to grasp, and it occurs inconsistently.
I’ve attached an image showing the situation. The rope becomes distorted, with the grasped particle connected incorrectly.
What I’ve Tried:
  • Confirming the attachments are created dynamically at runtime without pre-existing constraints.
  • Checking that particle indices are updated correctly during grasping.
  • Ensuring the tools have unique attachment components.
Image Explanation:
In the attached image:
  • The left tool is holding the rope correctly.
  • The right tool exhibits the described offset issue when grasping second.

Question: Why does this behavior occur when the right tool is the second one to grasp? Could this be a bug in ObiRope's particle attachment system, or am I missing something in the setup?
Thank you for any insights or suggestions!
Reply
#2
Hi Alice,

Can't see any images attached to or posted along with your description of the issue. Also, how are you implementing grasping? could you share your code? otherwise it's quite difficult to tell what might be going on.

kind regards,
Reply
#3
(10-12-2024, 10:50 AM)josemendez Wrote: Hi Alice,

Can't see any images attached to or posted along with your description of the issue. Also, how are you implementing grasping? could you share your code? otherwise it's quite difficult  to tell what might be going on.

kind regards,
Hi,

now the image should be there, sorry
this is my code 

using UnityEngine;
using Obi;
using System.Collections.Generic;

[RequireComponent(typeof(ObiActor))]
public class DistanceAnchor : MonoBehaviour
{
    ObiActor actor;
    public ObiParticleAttachment rightAttachment;
    public ObiParticleAttachment leftAttachment;
    public Transform anchorRight;
    public Transform anchorLeft;
    public float anchorRadius = 5f; // Radius for grasping
    public DistanceCalculation forcepsRight; // Reference to the DistanceCalculation script
    public DistanceLeft forcepsLeft; // Reference to the DistanceCalculation script
    private bool isRightGrasping = false;
    private bool isLeftGrasping = false;
   
    private bool isLeftInRelease = false; // Indicates if the left elastic is in release state
    private bool isRightInRelease = false;

    public bool IsLeftInRelease => isLeftInRelease;
    public bool IsRightInRelease => isRightInRelease;



    void Awake()
    {
        actor = GetComponent<ObiActor>();
        forcepsRight = FindObjectOfType<DistanceCalculation>();
        forcepsLeft = FindObjectOfType<DistanceLeft>();

        if (forcepsRight != null)
        {
            forcepsRight.OnForcepsClosingRight += () => CheckAndGraspParticles(anchorRight, ref isRightGrasping, ref rightAttachment, GraspRight);
            forcepsRight.OnForcepsOpeningRight += HandleRightForcepsOpening; // Handles release when opening.
        }

        if (forcepsLeft != null)
        {
            forcepsLeft.OnForcepsClosingLeft += () => CheckAndGraspParticles(anchorLeft, ref isLeftGrasping, ref leftAttachment, GraspLeft);
            forcepsLeft.OnForcepsOpeningLeft += HandleLeftForcepsOpening; // Handles release when opening.
        }
    }

    void CheckAndGraspParticles(Transform anchor, ref bool isGrasping, ref ObiParticleAttachment attachment, System.Action<ObiActor, int> graspAction)
    {
        Debug.Log($"Checking grasping for anchor {anchor.name}, isGrasping: {isGrasping}");

        if (actor.isLoaded && !isGrasping)
        {
            for (int i = 0; i < actor.solverIndices.Length; ++i)
            {
                int solverIndex = actor.solverIndices[i];
                float distance = Vector3.Distance(actor.GetParticlePosition(solverIndex), anchor.position);
                Debug.Log($"Particle {i}: Solver Index {solverIndex}, Distance: {distance}");

                if (distance < anchorRadius)
                {
                    Debug.Log($"Grasp condition met for particle {i}.");

                    graspAction(actor, i);
                    break;
                }
            }
        }
    }

    private void GraspRight(ObiActor actor, int index)
    {
        rightAttachment = CreateAttachment(actor, index, anchorRight, ref isRightGrasping);
        isRightInRelease = false;
        Debug.Log(" RIGHT GRASP");
    }

    private void GraspLeft(ObiActor actor, int index)
    {
        leftAttachment = CreateAttachment(actor, index, anchorLeft, ref isLeftGrasping);
        isLeftInRelease = false;
        Debug.Log(" LEFT GRASP");
    }

    private ObiParticleAttachment CreateAttachment(ObiActor actor, int index, Transform anchor, ref bool isGrasping)
    {
        Debug.Log($"Creating attachment: isGrasping = {isGrasping}, index = {index}, anchor = {anchor.name}");

        if (isGrasping) return null; // Prevent double attachment

        var attachment = actor.gameObject.AddComponent<ObiParticleAttachment>();
        attachment.target = anchor; // Attach to the specified anchor
        attachment.particleGroup = actor.blueprint.AppendNewParticleGroup("GraspedParticles");
        attachment.particleGroup.particleIndices = new List<int> { index };
        attachment.compliance = 0;
        attachment.attachmentType = ObiParticleAttachment.AttachmentType.Static;

        Debug.Log($"Attachment created for particle index {index} at anchor {anchor.name}.");

        actor.solver.RemoveActor(actor); // Refresh the actor in the solver
        actor.solver.AddActor(actor);
        Debug.Log("Actor re-added to solver.");

        isGrasping = true;
        return attachment;
    }

    private void ReleaseRight()
    {
        Release(ref rightAttachment, ref isRightGrasping);
        isRightInRelease = true;
    }

    private void ReleaseLeft()
    {
        Release(ref leftAttachment, ref isLeftGrasping);
        isLeftInRelease = true;
    }

    private void Release(ref ObiParticleAttachment attachment, ref bool isGrasping)
    {
        if (attachment != null)
        {
            Destroy(attachment);
            isGrasping = false;
        }
    }

    private void HandleRightForcepsOpening()
    {
        if (isRightGrasping)
        {
            Debug.Log(" RIGHT RELEASE");
            ReleaseRight();
        }
    }

    private void HandleLeftForcepsOpening()
    {
        if (isLeftGrasping)
        {
            Debug.Log(" LEFT RELEASE");
            ReleaseLeft();
        }
    }

    void OnDestroy()
    {
        // Ensure to release any grasped particles
        Release(ref rightAttachment, ref isRightGrasping);
        Release(ref leftAttachment, ref isLeftGrasping);

        // Unsubscribe from events to avoid memory leaks
        if (forcepsRight != null)
        {
            forcepsRight.OnForcepsClosingRight -= () => CheckAndGraspParticles(anchorRight, ref isRightGrasping, ref rightAttachment, GraspRight);
            forcepsRight.OnForcepsOpeningRight -= HandleRightForcepsOpening;
        }

        if (forcepsLeft != null)
        {
            forcepsLeft.OnForcepsClosingLeft -= () => CheckAndGraspParticles(anchorLeft, ref isLeftGrasping, ref leftAttachment, GraspLeft);
            forcepsLeft.OnForcepsOpeningLeft -= HandleLeftForcepsOpening;
        }
    }
}

Also i noticed that i the the following error when at runtime i click on the partcile Group menu in the obi Attachment component
NullReferenceException: Object reference not set to an instance of an object
Obi.ObiParticleAttachmentEditor.OnInspectorGUI () (at C:/Users/Alice Catalano/Desktop/Alice/ObiTraining/Assets/Obi/Editor/Common/Utils/ObiParticleAttachmentEditor.cs:75)
UnityEditor.UIElements.InspectorElement+<>c__DisplayClass72_0.<CreateInspectorElementUsingIMGUI>b__0 () (at <9920ff0c944845d7b9f9a61ef1478edc>:0)
UnityEngine.GUIUtilityLenguarocessEvent(Int32, IntPtr, Boolean&)


and this path doesn't exist anymore. I cleared the cache and rebuilt but still this happens


Attached Files Thumbnail(s)
   
Reply
#4
Hi Alice,

The following code is unnecessary, and may lead to incorrect behavior as it resets the state of the rope every time you attach a particle:
Code:
actor.solver.RemoveActor(actor); // Refresh the actor in the solver
actor.solver.AddActor(actor);
Debug.Log("Actor re-added to solver.");

What this does is take out all particles and constraints from the solver and reorder all other actor's data (which is expensive), then re-add the actor using the data stored in the blueprint. Adding attachments at runtime does not require doing this.

Additionally you're adding new particle groups to the blueprint:
Code:
actor.blueprint.AppendNewParticleGroup("GraspedParticles");

but never deleting them. This might not be a problem but over time can add up to a significant amount of scriptable objects being created.

Also keep in mind that having multiple attachments on the same particle will yield undefined behavior as warned in the manual. Your code does not check whether the particle about to be attached is already attached, so in case both left and right hands grasp the same particle you'll be in trouble:

Quote:Particles affected by more than one attachment will follow the attachment that was updated last. The update order for attachment is undefined.

kind regards,
Reply
#5
(10-12-2024, 11:47 AM)josemendez Wrote: Hi Alice,

The following code is unnecessary, and may lead to incorrect behavior as it resets the state of the rope every time you attach a particle:
Code:
actor.solver.RemoveActor(actor); // Refresh the actor in the solver
actor.solver.AddActor(actor);
Debug.Log("Actor re-added to solver.");

What this does is take out all particles and constraints from the solver and reorder all other actor's data (which is expensive), then re-add the actor using the data stored in the blueprint. Adding attachments at runtime does not require doing this.

Additionally you're adding new particle groups to the blueprint:
Code:
actor.blueprint.AppendNewParticleGroup("GraspedParticles");

but never deleting them. This might not be a problem but over time can add up to a significant amount of scriptable objects being created.

Also keep in mind that having multiple attachments on the same particle will yield undefined behavior as warned in the manual. Your code does not check whether the particle about to be attached is already attached, so in case both left and right hands grasp the same particle you'll be in trouble:


kind regards,
Thank you for the answer, but unfortunately all of this work is lost.

yesterday my laptop crashed while the simulaiton was running and now seems like the simulation is not able to run anymore without continous lags.
I created another simulation that would have the same objects and behaviours but when I imported obi and used the same exact codes nothing was working anymore.  
 the behavior of the elastic is totally different even if i keep the same values of the characteristics. Now when i grasp it the grasped particle is visually detached from the grasping point and the elastic "updates" when i grasp it, by fastly appearing and disappearing. the code is exactly the same as the one i provided you before.
Reply
#6
(12-12-2024, 11:34 AM)alicecatalano Wrote: the simulation is not able to run anymore without continous lags.

Hi Alice,

If you're using Burst in the editor, make sure the jobs debugger is disabled as that will have a *huge* negative effect on performance.

(12-12-2024, 11:34 AM)alicecatalano Wrote: I created another simulation that would have the same objects and behaviours but when I imported obi and used the same exact codes nothing was working anymore.  
 the behavior of the elastic is totally different even if i keep the same values of the characteristics.

Code can't just stop working due to a crash, it is impossible. More likely your current setup and/or parameters are not entirely identical to the original one.

(12-12-2024, 11:34 AM)alicecatalano Wrote: Now when i grasp it the grasped particle is visually detached from the grasping point and the elastic "updates" when i grasp it, by fastly appearing and disappearing. the code is exactly the same as the one i provided you before.

If the code is the same but behavior is different, that means the parameters used for simulation are not the same. I can't possibly know however, since I don't know how your project was set up before this incident and how it is set up now.

let me know if I can be of any help,

kind regards
Reply