一段时间后,PointCloud.FindPlane停止工作

时间:2016-11-28 16:02:01

标签: android google-project-tango

您好我正在使用谷歌探戈和统一SDK!我正在制作一个应用程序,你应该在建筑物的3D模型中对齐自己。使用以下代码,您应该能够将探戈指向墙壁并在3D模型中单击该墙以通过PoinCloud.FindPlane和Physics.Raycast对齐它们。这非常有效!但。它只适用于app运行的开始。由于某种原因,PointCloud.FindPlane在应用运行时约30秒后总是失败。

我没有使用arealearning或区域描述,因为这应该是为了弥补学习本来应该解决的漂移。

我尝试过很多东西,比如使用arealearning等,但它无论如何都没有用。我怀疑PointCloud中的某些东西在需要多点时会被破坏,但我不知道如何修复它。我已经有了这个bug大约6个月了,并希望它会在以后的更新中修复,但它没有。

我认为这也发生在googles自己的一个例子中,我根据这个代码。

如果有人知道发生了什么并且导致了问题,或者你有一些方法可以偶尔刷新点云,因为它总是会工作几秒钟就会很棒!或者也许只使用最新的姿势使用FindPlane,因为我只在探戈面前使用FindPlane。谢谢!

值得一提的是,我不是"扫描"非常通过这个应用程序。只是穿过房间。

(编辑)我还读到,使用FindPlane,探戈正在检查点云中的每个点,每帧只应使用一次。也许它会在一段时间后变慢?然后我需要暂时刷新PointCloud,但我似乎无法找到任何方法。

public class ModelPositionRefiner : MonoBehaviour, ITangoLifecycle, ITangoDepth
{


    /// <summary>
    /// The tango gameObject to ray cast from.
    /// </summary>
    public GameObject m_virtualTangoDevice;

    /// <summary>
    /// The HAX fixed distance between the tango and the bim floor.
    /// </summary>
    public float m_tangoToFloorDistance;

    /// <summary>
    /// Position in model to align with point cloud interception.
    /// </summary>
    private Ray m_selectedEnvironmentSurface;

    /// <summary>
    /// The point cloud object in the scene.
    /// </summary>
    public TangoPointCloud m_pointCloud;

    /// <summary>
    /// The canvas to place 2D game objects under.
    /// </summary>
    public Canvas m_canvas;


    public Text m_errorField;
    public TouchEffect m_touchEffect;
    public TouchEffect m_errorTouchEffect;
    public TouchEffect m_loadingTouchEffect;

    /// <summary>
    /// If set, then the depth camera is on and we are waiting for the next depth update.
    /// </summary>
    private bool m_findPlaneWaitingForDepth;


    /// <summary>
    /// A reference to TangoApplication instance.
    /// </summary>
    private TangoApplication m_tangoApplication;

    /// <summary>
    /// Unity Start function.
    /// 
    /// We find and assign pose controller and tango applicaiton, and register this class to callback events.
    /// </summary>
    public void Start()
    {
        m_tangoApplication = FindObjectOfType<TangoApplication>();

        m_tangoApplication.Register(this);
    }


    /// <summary>
    /// This is called when the permission granting process is finished.
    /// </summary>
    /// <param name="permissionsGranted"><c>true</c> if permissions were granted, otherwise <c>false</c>.</param>
    public void OnTangoPermissions(bool permissionsGranted)
    {
    }

    /// <summary>
    /// This is called when succesfully connected to the Tango service.
    /// </summary>
    public void OnTangoServiceConnected()
    {
        m_tangoApplication.SetDepthCameraRate(1);
    }

    /// <summary>
    /// This is called when disconnected from the Tango service.
    /// </summary>
    public void OnTangoServiceDisconnected()
    {
    }

    /// <summary>
    /// This is called each time new depth data is available.
    /// 
    /// On the Tango tablet, the depth callback occurs at 5 Hz.
    /// </summary>
    /// <param name="tangoDepth">Tango depth.</param>
    public void OnTangoDepthAvailable(TangoUnityDepth tangoDepth)
    {
        // Don't handle depth here because the PointCloud may not have been updated yet.  Just
        // tell the coroutine it can continue.
        m_findPlaneWaitingForDepth = false;
    }

    /// <summary>
    /// Unity destroy function.
    /// </summary>
    public void OnDestroy()
    {
        m_tangoApplication.Unregister(this);
    }

    /// <summary>
    /// Unity Update function.
    /// </summary>
    public void Update()
    {
        UpdateCheckForManualRefining();
    }



    /// <summary>
    /// Checks for a manual click to align the bim surface clicked with the
    /// </summary>
    private void UpdateCheckForManualRefining()
    {
        // Check so that we don't click UI. The first is for computer and the 0 is required for which touch on touch device.
        if (EventSystem.current.IsPointerOverGameObject() || EventSystem.current.IsPointerOverGameObject(0))
            return;

        Vector2 clickPosition;

        if (Input.touchCount != 1)
            return;
        clickPosition = Input.GetTouch(0).position;

        // Add a progress animation when pressing to refine position.
        if (Utils.PressTimePassed(1f) && !Utils.PressDistancePassed(20))
        {
            m_loadingTouchEffect.Apply(m_canvas, clickPosition);
        }
        // When pressed enough time align clicked bim object with wath the tango is pointing toward!
        if (Utils.PressTimePassed(2.5f) && !Utils.PressDistancePassed(20))
        {

            RaycastHit hitInfo;

            // 10 is the environment model layer.
            if (Physics.Raycast(Camera.main.ScreenPointToRay(clickPosition), out hitInfo, 1000, 1 << 10))
            {  
                m_selectedEnvironmentSurface = new Ray(hitInfo.point, hitInfo.normal);
                m_touchEffect.Apply(m_canvas, clickPosition);
                StartCoroutine(_WaitForDepthAndCorrectModel(clickPosition));
            }
            else
            {
                m_errorTouchEffect.Apply(m_canvas, clickPosition);

            }
        }
    }


    private IEnumerator _WaitForDepthAndCorrectModel(Vector2 clickPosition)
    {
        m_findPlaneWaitingForDepth = true;

        // Turn on the camera and wait for a single depth update.
        m_tangoApplication.SetDepthCameraRate(TangoEnums.TangoDepthCameraRate.MAXIMUM);
        while (m_findPlaneWaitingForDepth)
        {
            yield return null;
        }
        m_tangoApplication.SetDepthCameraRate(1);


        // Find the plane.
        Camera cam = Camera.main;
        Vector3 cloudOrigin;
        Plane plane;
        if (!m_pointCloud.FindPlane(cam, new Vector3(Screen.width / 2, Screen.height / 2, 0), out cloudOrigin, out plane))
        {
            m_errorField.text = "Error: Tango has no depth. Valid distance: 0.5m - 4m. \nThe surface can't be too bright or too dark.";
            m_errorTouchEffect.Apply(m_canvas, clickPosition);
            yield break;
        }

        //cloudNormal is correctly oriented
        Vector3 modelNormal = m_selectedEnvironmentSurface.direction;
        Vector3 cloudNormal = plane.normal;


        float floorLimit = 45;
        float ceilingLimit = 180 - floorLimit;

        float modelAngle = Vector3.Angle(modelNormal, Vector3.up);
        float cloudAngle = Vector3.Angle(cloudNormal, Vector3.up);

        // 0 is floor, 1 is ceilling, 2 is wall.
        int modelNormalType = modelAngle < floorLimit ? 0 : (modelAngle > ceilingLimit ? 1 : 2);
        int cloudNormalType = cloudAngle < floorLimit ? 0 : (cloudAngle > ceilingLimit ? 1 : 2);

        if (modelNormalType != cloudNormalType)
        {
            m_errorField.text = "Error: If you click on a wall, floor or ceiling the Tango must be facing the same.";
            m_errorTouchEffect.Apply(m_canvas, clickPosition);
            yield break;
        }
        //Input is valid, reposition.
        m_errorField.text = "";

        //We can't click a floor or ceiling and rotate around the Y axis.
        if (cloudNormalType == 2) // && modelNormalType == 2
        {
            //Ignore X and Z rotation since the floor is expected to be parallell with the worlds.
            modelNormal.y = 0;
            cloudNormal.y = 0;


            float angle = Vector3.Angle(modelNormal, cloudNormal);
            Vector3 cross = Vector3.Cross(modelNormal, cloudNormal);

            angle = angle * Mathf.Sign(cross.y);



            //We use cloudNormal since the new Model is now expected to be cloudNormal.
            Location.ShowingLocation.Environment.transform.position += Vector3.Project(cloudOrigin - m_selectedEnvironmentSurface.origin, cloudNormal);

            Location.ShowingLocation.Environment.transform.RotateAround(cam.transform.position, Vector3.up, angle);
        }
        else //Preferably a floor.
        {
            //Only move us to the right height from the floor.
            Location.ShowingLocation.Environment.transform.position += Vector3.Project(modelNormal, cloudOrigin - m_selectedEnvironmentSurface.origin);
            //Move us to the pointed direction.
            //Location.ShowingLocation.Environment.transform.position += planeCenter - m_selectedEnvironmentSurface.origin;
        }

    }

}

0 个答案:

没有答案