google-ar / arcore-ios-sdk

ARCore SDK for iOS
https://developers.google.com/ar/
Apache License 2.0
282 stars 84 forks source link

Error When Trying to Host an Anchor #5

Closed azamsharp closed 6 years ago

azamsharp commented 6 years ago

I am trying to host the anchor with the following code:

private func addAnchorWithTransform(transform :matrix_float4x4) {

    self.arAnchor = ARAnchor(transform: transform)
    self.sceneView.session.add(anchor: self.arAnchor)

    do {
        try
            self.garAnchor = self.gSession.hostCloudAnchor(self.arAnchor)

    } catch {
        print(error.localizedDescription)
    }

}

and I get the following error. Do I need to have Firebase Real Time Database configured in order to use ARCore Cloud Anchors?

Printing description of error: Error Domain=GARSession Code=-3 "(null)" (id) [0] =

sammcd commented 6 years ago

Sorry you ran into this!

Yes, you do need a Real Time Database Configured in order to use the sample. We have added instructions on how to do that to this quickstart guide: https://developers.google.com/ar/develop/ios/cloud-anchors-quickstart-ios

azamsharp commented 6 years ago

Ok. I am unable to understand what exactly are you storing in the Real Time Database. The sample code is written by an intern. There is one file in Objective-C which contains hundreds of line of code. In the docs you mentioned there is no mention of how and where the Real Time Database is being used. Is there another sample that actually works?

azamsharp commented 6 years ago

The quickstart docs are suggesting run the app! The app does not run at all.

azamsharp commented 6 years ago

Can I get some support on this? What happens when I host an anchor? How does it know where to store the anchors? If it already knows where to store the anchors then why should I use Real Time Database.

sammcd commented 6 years ago

I apologize, when you asked about Firebase I assumed that you were running the sample app. Firebase is not required at all to use our Cloud Anchors API it is just used by the sample to share anchor IDs.

Since you are jumping in and writing an app this guide might be more helpful: https://developers.google.com/ar/develop/ios/cloud-anchors-developer-guide-ios

Your error message seems to be: GARSessionErrorCodeNotTracking

This means that the ARSession is not tracking properly. Looking at your sample code there are two things I think you need to do:

1) Listen to the session delegate and forward frames to the google session. There is an example of this in the guide I just linked.

2) You will need to wait some time before calling host because the ARKit session will need to start tracking the scene before you can host an anchor. The best practices section of that guide might also provide some tips to help you successfully host an anchor.

azamsharp commented 6 years ago

Is there anyway to log to Google Console and delete the cloud identifier? Can I see what kind of information is being collected when hosting Cloud Anchors? What happens if I add the cloud anchors to a place where the cloud anchors have already been added.

sammcd commented 6 years ago

We don't have a way to delete an identifier. They have a lifetime of 24 hours.

We have a lot more information on the data collected in the "Data storage and access limitations" section of this guide: https://developers.google.com/ar/develop/ios/overview.

Cloud anchors have no knowledge of each other, so if you add a new cloud anchor at the same place, you will simply host a new cloud anchor with a new ID.

azamsharp commented 6 years ago

Thanks! I am still confused about the workings on Cloud Anchor. Here is what I understand.

Person A maps a room using their phone and then hosts an anchor. The visual features of the room gets uploaded to Google cloud. Person B goes to the same room and resolve the anchor. Now, they are sharing the same anchor.

Does that mean that if Person A attaches anything to anchor A it will be automatically visible to Person B?

What if there is only Person A? If I attach a chair to a cloud anchor then if I resolve an anchor will I also get the chair back or cloud anchors are more about getting the anchors and then I will have to write code to add the chair myself?

azamsharp commented 6 years ago

Hosting an anchor takes a very very very long time (10-15) seconds. Resolving an anchor almost fails since cloud anchors is not able to find out if the raw points belongs to any anchor or not.

azamsharp commented 6 years ago

I am trying to resolve a cloudIdentifier by putting the identifier as a hardcoded value. This cloud anchor is placed right in front of me. But when I move away or look up or down and try to resolve the identifier then it puts the anchor at the wrong position.

Why does it matter that the person should be looking at the same surface/place in order to correctly resolve the cloud anchors?

sammcd commented 6 years ago

Without seeing your code I'm not completely sure what is happening, but I do have a guess.

If I had to guess you are probably programmatically resolving the anchor very quickly after an the ARSession has started. This would mean that ARKit hasn't had time to build up a model of the space around you, so the localized anchor moves around quickly.

You will notice that many AR apps you download, when the session first starts they have some UI asking you to move your phone around for a bit before they allow you to place anything in the world. The ARKit docs mention this in this document: https://developer.apple.com/documentation/arkit/about_augmented_reality_and_arkit

I would suggest spending a little more time allowing the ARKit to understand the world around you, and then trying to resolve to see if that helps.

Also that is mostly a guess, so feel free to post some code in a followup if you have a different issue.

To answer a few other questions:

azamsharp commented 6 years ago

Couple of different problems:

// Finding the position on the plane

` @objc func tapped(recognizer :UITapGestureRecognizer) {

    let sceneView = recognizer.view as! ARSCNView
    let touch = recognizer.location(in: sceneView)

    let hitTestResults = sceneView.hitTest(touch, types: .existingPlane)
    if !hitTestResults.isEmpty {

        if let hitTestResult = hitTestResults.first {

            print("plane hit test")
            print(hitTestResult.worldTransform)
            addAnchorWithTransform(transform: hitTestResult.worldTransform)
        }
    }
}`

// hosting the anchor ` private func addAnchorWithTransform(transform :matrix_float4x4) {

    self.arAnchor = ARAnchor(transform: transform)
    self.sceneView.session.add(anchor: self.arAnchor)

    do {
        try
            self.garAnchor = self.gSession.hostCloudAnchor(self.arAnchor)

    } catch {
        print(error.localizedDescription)
    }
}`

// adding a block/virtual object to the anchor position

` @objc func addBlock() {

    let grAnchor = try? self.gSession.resolveCloudAnchor(withIdentifier: self.cloudIdentifier)

    print("addBlock")
    print(grAnchor?.transform)

    if let cloudAnchor = grAnchor {

        let box = SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)
        let material = SCNMaterial()
        material.diffuse.contents = UIColor.red
        box.materials = [material]

        let node = SCNNode(geometry: box)
        node.position = SCNVector3(cloudAnchor.transform.columns.3.x, cloudAnchor.transform.columns.3.y, cloudAnchor.transform.columns.3.z)
        self.sceneView.scene.rootNode.addChildNode(node)
    }

}`

// closing the app and then resolving the anchor using the anchor id which is saved on the clipboard.

` @objc func resolveAnchor() {

    // even by giving the hard-coded value the anchor is resolved at an incorrect position.
    // I get the cloud identifier once, I have hosted the anchor.
    let grAnchor = try? self.gSession.resolveCloudAnchor(withIdentifier: "ua-3a4376036801c8411de0f9bc375a2b3d")

    if let cloudAnchor = grAnchor {

        let box = SCNBox(width: 0.3, height: 0.3, length: 0.3, chamferRadius: 0)
        let material = SCNMaterial()
        material.diffuse.contents = UIColor.red
        box.materials = [material]

        let node = SCNNode(geometry: box)
        node.position = SCNVector3(cloudAnchor.transform.columns.3.x, cloudAnchor.transform.columns.3.y, cloudAnchor.transform.columns.3.z)
        self.sceneView.scene.rootNode.addChildNode(node)
    }

}`

The anchor comes back but at a wrong location even though I provided the correct cloud identifier. The box appears at a wrong position.

sammcd commented 6 years ago

By wrong location are we talking a few inches off? Or very far away?

When exactly are you resolving the anchor? I don't see the call to resolveAnchor() in your sample. As you are calling this after ARKit has some amount of time to learn about its environment, your code looks reasonable.

azamsharp commented 6 years ago

The resolveAnchor code is above in function called resolveAnchor. I start the app map the area, perform plane detection and then I put a cube on the plane. I get the cloudIdentifier which I copy it in clipboard. I kill the app and update the cloudIdentifier with the one I recieved.

The cube is resolving few feet away.

sammcd commented 6 years ago

Sorry I wasn't more specific. Of the two resolveAnchor() calls, I meant to ask about the one you wrote.

In the code snippet you added I am unable to see where you call your resolveAnchor() function, if this is being called immediately after the ARKit session starts, it is possible that ARKit itself doesn't yet have a good understanding of its surroundings. So when you add the box it quickly moves around because ARKit does not have enough information about your surroundings.

A few feet away is far outside of what we would expect. Would you mind trying to call resolve later? Or sharing some more info on when you call your resolveAnchor() method?

sammcd commented 6 years ago

Closing this ticket for now due to inactivity.

Feel free to reach out if you have any more questions!