示例#1
0
    /// <summary>
    /// Given a camera result/frame, adds it to the calibration pool
    /// </summary>
    private void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame frame)
    {
        if (result.success)
        {
            Debug.Log("SNAP!!!");

            WebcamSystem.CaptureFrameInstance currFrame = new WebcamSystem.CaptureFrameInstance(frame);

            if (DEBUG)
            {
                Debug.LogWarning("dumping img...");
                int res = NativeFiducialFunctions.image_u8_write_pnm(currFrame.unmanagedFrame, "m:\\debugImg\\garbooggle.pnm");
            }

            int prevCount = calibImgs.Count;
            int newCount  = NativeFiducialFunctions.supply_calibration_image(currFrame.unmanagedFrame);

            if (newCount > prevCount)
            {
                Debug.Log(string.Format("Good picture! Currently have {0} pictures stored out of the needed {1}.", newCount, MINIMUM_CALIBRATION_IMGS));
                calibImgs.Add(currFrame);
            }
            else
            {
                Debug.Log("Couldn't detect the checkerboard. Please try again.");
            }
        }
        else
        {
            Debug.LogError("Unable to take photo!");
        }

        calibButton.UpdateState(calibImgs.Count >= MINIMUM_CALIBRATION_IMGS);
    }
示例#2
0
    // Start is called before the first frame update
    private void Start()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(this);

            RclCppDotnet.Init();
            _listener = new TransformListener();
            _detector = NativeFiducialFunctions.apriltag_detector_create();
            _family   = NativeFiducialFunctions.tagStandard41h12_create();
            // Start detecting Apriltags from the 41h12 family:
            // https://github.com/AprilRobotics/apriltag-imgs/tree/master/tagStandard41h12
            NativeFiducialFunctions.apriltag_detector_add_family_bits(this._detector, this._family);

            _active = true;
        }
        else
        {
            Debug.LogWarning("Duplicate FiducialSystem tried to initialize in scene on gameobject " + this.gameObject + "; Destroying self!");
            Destroy(this);
            return;
        }

        if (tagSize == 0)
        {
            Debug.LogError("Fiducial system is missing information about how large the physical AprilTag squares are!");
        }
    }
示例#3
0
 private void Shutdown()
 {
     if (calibImgs.Count > 0)
     {
         calibImgs.Clear();
         NativeFiducialFunctions.clear_calibration_images();
     }
 }
示例#4
0
    private void Shutdown()
    {
        if (_active)
        {
            RclCppDotnet.Shutdown();
            NativeFiducialFunctions.apriltag_detector_destroy(_detector);
            NativeFiducialFunctions.tagStandard41h12_destroy(_family);

            _active = false;
        }
    }
示例#5
0
    public async void DoCalibration()
    {
        if (calibImgs.Count < MINIMUM_CALIBRATION_IMGS)
        {
            Debug.LogError("Attempted calibration before acquiring the minimum required images!");
        }
        else
        {
            // Calibration will take a noticeable amount of time, so put it in its own thread

            Task <Intrensics> task = Task.Run(() =>
            {
                Debug.Log("Dispatching background thread to perform calibration!");
                Intrensics intr = new Intrensics();
                int success     = NativeFiducialFunctions.calibrate(squareSize, out intr);
                return(intr);
            });

            // Start UI feedback indicating work is being done...
            loadingComet.SetActive(true);

            Intrensics foundIntr = await task;

            if (!CameraIntrensicsHelper.WriteIntrensics(foundIntr))
            {
                Debug.LogError("Failed to write intrensics to disk!!");
                return;
            }

            // End UI feedback/transition scene

            loadingComet.SetActive(false); // Not strictly needed, since we change scenes
            this.Shutdown();               // Clear the unmanaged memory!
            SceneManager.LoadScene("RobotScene");
        }
    }
示例#6
0
    /// <summary>
    /// Attempts to locate the ROS world origin, placing a world anchor at that location if found.
    /// </summary>
    /// <returns>
    /// true if a world anchor is created successfully, otherwise false.
    /// A world anchor could fail to be created for a number of reasons: webcam image did not have
    /// an identifiable apriltag, tf2 messages are not being found (no robot discovered, incorrect frame name)
    /// etc.
    /// </returns>
    private bool UpdateSpacePinning(WebcamSystem.CaptureFrameInstance captureFrame)
    {
        if (_pinning != null)
        {
            return(false);
        }

        if (DEBUG_DUMP_IMAGE)
        {
            Debug.LogWarning("dumping processed img...");
            int res = NativeFiducialFunctions.image_u8_write_pnm(captureFrame.unmanagedFrame, DEBUG_DUMP_IMAGE_NAME + "_" + System.DateTime.Now.Ticks + "_processed.pnm");
        }

        IntPtr nativeDetectionsHandle = NativeFiducialFunctions.apriltag_detector_detect(_detector, captureFrame.unmanagedFrame);

        _detections = Marshal.PtrToStructure <ZArray>(nativeDetectionsHandle);
        Dictionary <int, RelTransform> fiducialCentersRelWebcam = new Dictionary <int, RelTransform>();

        // Iterate over all detected apriltags in image
        for (int i = 0; i < _detections.size; i++)
        {
            IntPtr detPtr = IntPtr.Add(_detections.data, i * (int)_detections.el_sz);
            detPtr = Marshal.ReadIntPtr(detPtr);  // the zarray stores an array of detection ptrs
            ApriltagDetection det = Marshal.PtrToStructure <ApriltagDetection>(detPtr);
            Debug.Log("Detected an apriltag of id: " + det.id);

            AprilTagDetectionInfo info = new AprilTagDetectionInfo();
            info.det     = detPtr;
            info.tagsize = tagSize;
            info.fx      = _intrensics.fx;
            info.fy      = _intrensics.fy;
            info.cx      = _intrensics.cx;
            info.cy      = _intrensics.cy;

            AprilTagPose pose = new AprilTagPose();
            double       err  = NativeFiducialFunctions.estimate_tag_pose(in info, out pose);


            Matd t = Marshal.PtrToStructure <Matd>(pose.t);
            Matd R = Marshal.PtrToStructure <Matd>(pose.R);

            Vector3?   fiducialCenterRelWebcamTranslation = TransformHelper.VectorAprilToUnity(t);
            Quaternion?fiducialCenterRelWebcamRotation    = TransformHelper.QuatAprilToUnity(R);

            if (fiducialCenterRelWebcamTranslation.HasValue && fiducialCenterRelWebcamRotation.HasValue)
            {
                fiducialCentersRelWebcam.Add(det.id, new RelTransform(fiducialCenterRelWebcamTranslation.Value,
                                                                      fiducialCenterRelWebcamRotation.Value));
            }
            else
            {
                Debug.LogError("A TransformHelper apriltag conversion failed!");
            }
        }

        // Deallocate the Zarray of detections on native side
        NativeFiducialFunctions.apriltag_detections_destroy(nativeDetectionsHandle);
        nativeDetectionsHandle = IntPtr.Zero;

        // Use the fiducial tag labeled '1' to pin the anchor
        if (fiducialCentersRelWebcam.ContainsKey(1))
        {
            // Raw TF values follow a different xyz coordinate system, must be converted with the TransformHelper class
            TfVector3?   worldZeroRelFiducialCenterTranslationTF = _listener.LookupTranslation("fiducial_link", "odom");
            TfQuaternion?worldZeroRelFiducialCenterRotationTF    = _listener.LookupRotation("fiducial_link", "odom");

            if (worldZeroRelFiducialCenterTranslationTF.HasValue && worldZeroRelFiducialCenterRotationTF.HasValue)
            {
                Vector3    worldZeroRelFiducialCenterTranslation = TransformHelper.VectorTfToUnity(worldZeroRelFiducialCenterTranslationTF.Value);
                Quaternion worldZeroRelFiducialCenterRotation    = TransformHelper.QuatTfToUnity(worldZeroRelFiducialCenterRotationTF.Value);
                // translate from camera pos -> fiducial tag pos
                Vector3 fiducialPos = Camera.main.transform.position + fiducialCentersRelWebcam[1].translation;
                // rotate from camera space -> fiducial space
                Quaternion fiducialRot = Camera.main.transform.rotation * fiducialCentersRelWebcam[1].rotation;

                GameObject anchor = new GameObject("WorldZero");
                _pinning = anchor.AddComponent <WorldAnchor>();
                // first put anchor at fiducial location...
                anchor.transform.position = fiducialPos;
                anchor.transform.rotation = fiducialRot;
                // use fiducial location to utilize fiducial-spaced translation

                /*anchor.transform.position = anchor.transform.position + anchor.transform.right * worldZeroRelFiducialCenterTranslation.x
                 + anchor.transform.up * worldZeroRelFiducialCenterTranslation.y + anchor.transform.forward * worldZeroRelFiducialCenterTranslation.z;*/

                // end anchor positioning!
                Collocator.StartCollocation(_pinning);
                Debug.Log("Anchor laid at Unity-space coords" + anchor.transform.position);
                return(true);
            }
            else
            {
                Debug.LogError("TF2 failed to query between fiducial tag and ROS world zero... is the ROS graph active?");
            }
        }

        return(false);
    }