Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lastest Unity DEMO pointclound :out of memory and unity crash! #1477

Closed
Zhangliuwei opened this issue Apr 4, 2018 · 6 comments
Closed
Assignees

Comments

@Zhangliuwei
Copy link

  • Before opening a new issue, we wanted to provide you with some useful suggestions (Click "Preview" above for a better view):


Required Info
Camera Model { R200 / F200 / SR300 / ZR300 / D400 }
Firmware Version (Open RealSense Viewer --> Click info)
Operating System & Version {Win (10)
Platform unity
SDK Version latest }

Issue Description

<Describe your issue / question / feature request / etc..>

@dorodnic
Copy link
Contributor

dorodnic commented Apr 4, 2018

Hi @Zhangliuwei
We are looking into the issue, but did not find decent solution yet. It is related to recent textured pointcloud feature. Disabling it can offer a work-around while we find a better fix.

@Zhangliuwei
Copy link
Author

I know,thanks!

@ducminhpham
Copy link

Hi @Zhangliuwei
I also experienced the same issue. After isolating and testing different parts of PointCloudGenerator.cs, I have found that the reason may be how FrameQueue pointsQueue manages its frames. At the line 69 (pointsQueue.Enqueue(points);), the reference count of points is increased by pointsQueue but I could not find where it is decreased in the native code.

So I think that garbage collector is not able to clean up unused memory of pointsQueue. I have decided not to use this queue and implemented two alternative queues to store the vertices and texture coordinates instead. It seems to work well so far if running on Unity Thread. I haven't found how to solve the issue when processing the frames with Multithread.

Here is my alternative implementation of PointCloudGenerator.cs

public class PointCloudGenerator : MonoBehaviour
{
    private ParticleSystem.Particle[] particles = new ParticleSystem.Particle[0];
    private PointCloud pc = new PointCloud();
    //FrameQueue pointsQueue = new FrameQueue(1);
    Points.Vertex[] vertices;
    Points.TextureCoordinate[] textureCoordinate;
    private byte[] lastColorImage;
    Texture2D colorTexture;
    private int colorFrameWidth;
    private int colorFrameHeight;

    public bool mirrored;
    public float pointsSize = 0.01f;
    public int skipParticles = 2;
    public ParticleSystem pointCloudParticles;

    Queue textureQueue = Queue.Synchronized(new Queue());
    Queue vertexQueue = Queue.Synchronized(new Queue());

    // Use this for initialization
    void Start()
    {
        //RealSenseDevice.Instance.onNewSample += OnFrame;
        RealSenseDevice.Instance.onNewSampleSet += OnFrames;

    }
    object l = new object();
    private void OnFrames(FrameSet frames)
    {
        if(frames.DepthFrame == null)
        {
            Debug.Log("No depth frame in frameset, can't create point cloud");
            return;
        }

        if (!UpdateParticleParams(frames.DepthFrame.Width, frames.DepthFrame.Height))
        {
            Debug.Log("Unable to create point cloud");
            return;
        }
    
        using (var points = pc.Calculate(frames.DepthFrame))
        {
            if (frames.ColorFrame != null)
            {
                if (frames.ColorFrame.BitsPerPixel == 24)
                {
                    pc.MapTexture(frames.ColorFrame);
                    colorFrameWidth = frames.ColorFrame.Width;
                    colorFrameHeight = frames.ColorFrame.Height;
                    var newSize = frames.ColorFrame.Stride * colorFrameHeight;
                    lock (l)
                    {
                        if (lastColorImage == null || lastColorImage.Length != newSize)
                            lastColorImage = new byte[newSize];

                        frames.ColorFrame.CopyTo(lastColorImage);
                    }
                }
            }

            Points.Vertex[] tmpvertices = new Points.Vertex[points.Count];
            points.CopyTo(tmpvertices);
            vertexQueue.Enqueue(tmpvertices);

            Points.TextureCoordinate[] tmpTextureCoordinate = new Points.TextureCoordinate[points.Count];
            points.CopyTo(tmpTextureCoordinate);
            textureQueue.Enqueue(tmpTextureCoordinate);

            //pointsQueue.Enqueue(points);
        }
    }

    private bool UpdateParticleParams(int width, int height)
    {
        var numParticles = (width * height);
        if (particles.Length != numParticles)
        {
            particles = new ParticleSystem.Particle[numParticles];
        }

        return true;
    }

    void Update()
    {
        /*
        Frame frame;
        if (pointsQueue.PollForFrame(out frame))
        {
            using (Points points = frame as Points)
            {
                if (points == null)
                    throw new Exception("Frame in queue is not a points frame");

                vertices = vertices ?? new Points.Vertex[points.Count];
                points.CopyTo(vertices);

                lock (l)
                {
                    if (textureCoordinate == null || textureCoordinate.Length != points.Count)
                        textureCoordinate = new Points.TextureCoordinate[points.Count];

                    points.CopyTo(textureCoordinate);

                    if (lastColorImage != null)
                    {
                        if (colorTexture == null || colorTexture.width != colorFrameWidth || colorTexture.height != colorFrameHeight)
                        {
                            colorTexture = new Texture2D(colorFrameWidth, colorFrameHeight, TextureFormat.RGB24, false, true)
                            {
                                wrapMode = TextureWrapMode.Clamp,
                                filterMode = FilterMode.Point
                            };
                        }

                        colorTexture.LoadRawTextureData(lastColorImage);
                        colorTexture.Apply();
                    }
                }
            
                Debug.Assert(vertices.Length == particles.Length);
                int mirror = mirrored ? -1 : 1;
                for (int index = 0; index < vertices.Length; index += skipParticles)
                {
                    var v = vertices[index];
                    if (v.z > 0)
                    {
                        particles[index].position = new Vector3(v.x * mirror, v.y, v.z);
                        particles[index].startSize = pointsSize;
                        particles[index].startColor = colorTexture.GetPixelBilinear(textureCoordinate[index].u, textureCoordinate[index].v);
                    }
                    else //Required since we reuse the array
                    {
                        particles[index].position = Vector3.zero;
                        particles[index].startSize = 0;
                        particles[index].startColor = Color.black;
                    }
                }
            }
        }
        */

        if (vertexQueue.Count > 0 && textureQueue.Count > 0)
        {
            vertices = (Points.Vertex[])vertexQueue.Dequeue();
            textureCoordinate = (Points.TextureCoordinate[])textureQueue.Dequeue();

            lock (l)
            {
                if (lastColorImage != null)
                {
                    if (colorTexture == null || colorTexture.width != colorFrameWidth || colorTexture.height != colorFrameHeight)
                    {
                        colorTexture = new Texture2D(colorFrameWidth, colorFrameHeight, TextureFormat.RGB24, false, true)
                        {
                            wrapMode = TextureWrapMode.Clamp,
                            filterMode = FilterMode.Point
                        };
                    }

                    colorTexture.LoadRawTextureData(lastColorImage);
                    colorTexture.Apply();
                }
            }

            Debug.Assert(vertices.Length == particles.Length);
            int mirror = mirrored ? -1 : 1;
            for (int index = 0; index < vertices.Length; index += skipParticles)
            {
                var v = vertices[index];
                if (v.z > 0)
                {
                    particles[index].position = new Vector3(v.x * mirror, v.y, v.z);
                    particles[index].startSize = pointsSize;
                    particles[index].startColor = colorTexture.GetPixelBilinear(textureCoordinate[index].u, textureCoordinate[index].v);
                }
                else //Required since we reuse the array
                {
                    particles[index].position = Vector3.zero;
                    particles[index].startSize = 0;
                    particles[index].startColor = Color.black;
                }
            }

        }

        //Either way, update particles
        pointCloudParticles.SetParticles(particles, particles.Length);
    }
}

@Zhangliuwei
Copy link
Author

This version still has a problem, when can the new version be available?

@RealSense-Customer-Engineering
Copy link
Collaborator

[Realsense Customer Engineering Team Comment]
hi @Zhangliuwei
would like to confirm if solution for #1394 works for you?
thanks.

@RealSense-Customer-Engineering
Copy link
Collaborator

[Realsense Customer Engineering Team Comment]
let me close this ticket here and please feel free to create new ticket if any question.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants