Move an Object smoothly according to a Data Flow

Hello everyone,

I started using Unity a week ago for a university project. Right now, I am a bit stuck on an issue and I could not find an existing topic that solved it.
In our lab, we have a small room equipped with cameras and a system to get the coordinates (translation + rotation) of a moving object (a drone) inside the room. Then we use ROS (http://www.ros.org/) to publish this information in real time (with a frequency of 100 Hz) in our wifi network. So with my computer connected to the network, I can receive and use the flow of data (positions of the drone) directly in Unity.
Basically, what I want to do is move an object smoothly in Unity scene according to the movement of the drone using this data flow.

Until now, I haven’t been successful : the object follow the drone’s movement but it is very laggy with a lot of jittering…

Here is what I tried :

First I initialize the connection in the Start method : after the subscribe method is called, the callback method OnMessage will be called each time we receive data from the network.

    Subscriber<TransformStamped> sub;
    NodeHandle nh;
    float x, y, z;
    static readonly object _locker = new object();
    UnityEngine.Vector3 positions;
    //public float smoothTime = 0.3F;
    //private UnityEngine.Vector3 velocity = UnityEngine.Vector3.zero;


    // Use this for initialization
    void Start()
    {
        x= 0;
        y = 0;
        z = 0;
        positions = new UnityEngine.Vector3(0,0,0);
        ROS.Init(new string[0], "example_listener");
        nh = new NodeHandle();
        sub = nh.subscribe<TransformStamped>("/vicon/Quad7/Quad7", 1, onMessage);

    }

    private void onMessage(TransformStamped tr)
    {
        lock (_locker)
        {
       
            x = -(float)tr.transform.translation.y;
            y = (float)tr.transform.translation.z;
            z = (float)tr.transform.translation.x;
           
        }

    }

Then I use the update method to change the position of the object at each frame :

    void Update()
    {
        lock (_locker)
        {
            positions.x = x;
            positions.y =  y;
            positions.z = z;

            //UnityEngine.Vector3 targetPosition = new UnityEngine.Vector3(x, y, z);
            //transform.position = UnityEngine.Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, smoothTime);

            //transform.position = UnityEngine.Vector3.Lerp(transform.position, positions, Time.deltaTime);
            transform.position = positions;
        }
    }

I thought it would help to put a lock in the callback method OnMessage and in the Update method, because I didn’t want x,y,z to be modified while I was updating the position, and maybe the lock slows down the Update method and that’s bad.

Also I tried different method to try and make the movement between the successive position smoother, but I didn’t succeed, it didn’t change anything.

I am a beginner in Unity, so I am pretty sure I did a lot of mistakes/bad practice…

Thank you for the help,

Cyril

OK, first, take the lock out. All MonoBehaviour callbacks run on the main thread; I don’t know exactly how that subscriber mechanism works, but it seems unlikely that it’s going to interrupt your Update method to do its thing, and unlikely to cause a problem if it does.

You could simplify your code by eliminating the separate x, y, and z fields and just have onMessage assign to positions directly. Then your update method becomes a one-liner (transform.position = positions).

If it’s still jittery, then I think it’s the data itself. That doesn’t surprise me; determining the position and orientation of an object with perfect precision is, well, impossible. Unity is probably showing you the quality of your actual data.

If you don’t care about accuracy and just want it to look smoother, then you could do something like a running average on your position. Or better yet, use a PID loop, which (if tuned correctly) can dampen out noisy inputs while still tracking the current position pretty well.

It sounds like a really interesting project — please feel free to write back with more questions if the above doesn’t help!

1 Like

First of all, thank you for the fast answer!

I added the modifications you suggested, the jittering is still there but the code is more simple so thank you for that.

Concerning the data, it has a 10^-4 m precision : the software which is used to get the position of the drone with the cameras is called Vicon, it has a simple graphic window where you can see the drone represented by a triangle moving in a 3D grid. And this is super smooth and precise even if you move the drone really fast. That’s why I think that the issue comes from the way I use Unity and not from the data itself.

The solution you propose with the PID seems like a good idea! I will try to dig into that direction to achieve a smoother movement.

Well, the other thing you might do to help debug it is to log the data to a file (using standard C# file I/O, which works fine in Unity). You could dump every coordinate as it comes in, or dump them as they’re applied in Update. Try it both ways and compare.

Be sure to include the time — for precise time info, you should probably use the Stopwatch class (again this is a standard C# thing, as described here for example).

Then you can take these log files and graph them in a spreadsheet. My guess is that you’ll see the same wiggles and noise that you observe in real time in Unity, and that the Vicon software is hiding this through some sort of data smoothing.

Small update on my issue.

I tried many different things, none of them worked. So I gave up and tried to advance in the project. Until now I was just getting the translations x,y,z from the real drone and I wanted to make that smooth before adding the rotations.
Today I added the rotations and … everything is SUPER SMOOTH now, no jitter AT ALL. I even tried to just fix the rotation to 0,0,0,1 in the code and that makes the translations smooth as well…

I don’t really know why it fixed the issue, but it works now !

Weird!