AR-js-org / AR.js

Image tracking, Location Based AR, Marker tracking. All on the Web.
MIT License
5.46k stars 931 forks source link

location based ar drift issue #490

Closed marcusx2 closed 1 year ago

marcusx2 commented 1 year ago

It's the same issue as this one. See this video. Apparently, it's working as intended. Is there a way to reduce the drift and make it look more like it's anchored? The AR content moves as I move until a certain point...I don't like this. Once the AR content shows up, I want it to stay fixed on that spot. Is there any way to achieve this? Or will the content always move with me in the general vicinity it's supposed to be?

nickw1 commented 1 year ago

Hi @marcusx2 , have you looked at the comments made by @nicolocarpignoli in the linked issue?

Have you tried this example here?

https://github.com/AR-js-org/AR.js/tree/master/aframe/examples/new-location-based/basic-js

This should produce 4 boxes to the north, south, east and west of your initial GPS position. The boxes don't move, but as you walk around, you should notice a change in their relative position, for example if you walk north a short distance (100-200 metres or so I think) from your initial GPS position, you should pass the red box.

If that doesn't work, make sure you have given your browser permission to access both the GPS and the sensors - I believe on iDevices you have to explicitly grant permission for the latter.

Also, at the moment location based AR uses only the GPS and sensors. It does not attempt to "anchor" the content to the ground.

However the intention is to use the AlvaAR project (https://github.com/alanross/AlvaAR/) to attempt to add SLAM-based more realistic placement of content to location-based AR.js. This is something I'm intending to look at in the near future.

marcusx2 commented 1 year ago
This should produce 4 boxes to the north, south, east and west of your initial GPS position. The boxes don't move, but as you walk around, you should notice a change in their relative position, for example if you walk north a short distance (100-200 metres or so I think) from your initial GPS position, you should pass the red box.

If that doesn't work, make sure you have given your browser permission to access both the GPS and the sensors - I believe on iDevices you have to explicitly grant permission for the latter.

I walked quite a bit, couldn't get past any box. They are always in front of me, the distance from the camera is always the same. I gave all the permissions necessary. They are always positioned the same relative to each other. I tried disabling the GPS as asked as well.

Also, at the moment location based AR uses only the GPS and sensors. It does not attempt to "anchor" the content to the ground.

However the intention is to use the AlvaAR project (https://github.com/alanross/AlvaAR/) to attempt to add SLAM-based more realistic placement of content to location-based AR.js. This is something I'm intending to look at in the near future.

Thanks for the info!

marcusx2 commented 1 year ago

@nickw1 I tried again and walked some more - I was finally able to get past a box. I know it does not attempt to "anchor" the content to the ground, but as it is right now it just looks like it doesn't work, because the content keeps following you for a good while. What is the use case for an AR like this if it's so imprecise? Don't mean to sound rude, but I don't see the point unless it's coupled with SLAM.

As it is right now, it's not much better than gyroscope based AR(look around AR), where you place AR content around the user and it follows you and stay fixed in relation to the camera, because you have to walk so much for the GPS to even start to notice to leave the content behind. I could just have gyro AR, and check the gps to see if I'm on the vicinity, and if not, disable the AR. Maybe I'm missing something here or my GPS just sucks, but I tried with 2 different androids.

I have an idea for a fake SLAM. What if after you are on the AR location, each step that you give makes the AR content move in the opposite direction? For example, if the cube is in front of me, and I start moving towards it, it slowly start moving towards me, at an adjustable speed/rate. This way, even though the content won't actually be anchored, it will somewhat give the impression that it is, and might be a better experiences than having to walk 2km before the content starts staying behind.

nickw1 commented 1 year ago

@marcusx2 I'm still wondering if this is an issue with your device, or the GPS sensors; it does reject inaccurate GPS readings (by default 1000 metres or more, so it should accept most).

When testing it, and I walk towards a cube it does gradually get bigger (noticeable in less than 100m, you certainly shouldn't have to walk 2km!) so the library certainly "can" do that. Maybe you are only receiving a new GPS position once in a while, again it may be to do with your device settings.

See this video for the sort of thing you should be getting: https://hikar.org/video/hikarweb.mp4

Admittedly this is for roads and paths, rather than POIs, and has some flaws ("floating content", inevitable without SLAM) and is a rather older version of AR.js but you should see that every few seconds the content does change its apparent size. (I think I set it to only update every 5 seconds or so, to conserve battery).

marcusx2 commented 1 year ago

I don't know then ;_;. It just doesn't work well for me. I even tried with 2 different Android phones.

@nickw1 Can the properties described on https://ar-js-org.github.io/AR.js-Docs/location-based/#a-frame be updated at runtime via javascript, or must they be provided on the html and changing them later does not take effect?

nickw1 commented 1 year ago

I have to admit I'm a bit puzzled in that case. Only thing I suggest is you try and do a bit of debugging if possible, for example by editing the code and displaying an alert when you get a new GPS location.

The properties should be able to be dynamically updated. See the update() method of the camera component to see which ones are handled, e.g. https://github.com/AR-js-org/AR.js/blob/master/aframe/src/new-location-based/gps-new-camera.js

marcusx2 commented 1 year ago

Hey @nickw1 quick question, sorry for deviating a bit from the topic now. Where can I get the position, scale, and rotation of the entity that is being positioned with geo AR? It looks like the transforms of the entity are always the same. See this code


<!DOCTYPE html>
<html>
<head>
<title>AR.js A-Frame Location-based</title>
<script src="https://aframe.io/releases/1.0.4/aframe.min.js"></script>
<script type='text/javascript' src='https://raw.githack.com/AR-js-org/AR.js/master/three.js/build/ar-threex-location-only.js'></script>
<script type='text/javascript' src='https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar.js'></script>
<script type='text/javascript' src='screenlog.min.js'></script>
</head>
<body>
<p id='positionx'>
<script>
screenLog.init();
AFRAME.registerComponent('transform', {
    tock: function(time, timeDelta){
        let position = new THREE.Vector3();
        let rotation = new THREE.Quaternion();
        let scale = new THREE.Vector3();

        (new THREE.Matrix4().makeScale(1, 1, -1).multiply(this.el.object3D.matrix.clone())).multiply(new THREE.Matrix4().makeRotationX(Math.PI/2).makeRotationY(Math.PI)).decompose(position, rotation, scale);

        console.log(position);
        console.log(rotation);
        console.log(scale);
        //console.log("position: " + position.x + " , " + position.y + " , " + position.z + " rotation: " + rotation + " scale: " + scale);

    }
});
</script>
<a-scene vr-mode-ui='enabled: false' arjs='sourceType: webcam; videoTexture: true; debugUIEnabled: false' renderer='antialias: true; alpha: true'>
    <a-camera gps-new-camera='gpsMinDistance: 5'></a-camera>
    <a-entity material='color: red' geometry='primitive: box' gps-new-entity-place="latitude: mylatitude; longitude: mylongitude" scale="10 10 10" transform></a-entity>
</a-scene>
</body>
</html>

You just need to set your latitude and longitude. I'm also using screenlog.js for debugging purposes.

The console.log always logs the same position, rotation, and scale. However this shouldn't be the case, should it? Because the box gets closer/further away, etc. The transforms must change somewhere. I can understand the scale not changing since I set it to 10, but not even the position changes? The idea is that I want to use this transform information, do some additional calculations to place the content inside other game frameworks like PlayCanvas. So I don't want to use the entities directly but just retrieve their transform informations.

nickw1 commented 1 year ago

Hello @marcusx2, the world position of the objects do not change at all: they are fixed at a certain world x,y,z coordinate, only their position relative to the camera. It's the camera which changes position as you move around. Does that answer your question?

marcusx2 commented 1 year ago

@nickw1 Yes it does. So the objects are only positioned once(assigned a x,y,z coordinate) based on their latitude and longitude, is that it? I guess they must be positioned at least once, or whenever I change their latitude and/or longitude values. Is that right? Is a rotation and scale also assigned, or only a position? I guess scale isn't because I say the scale myself.

nickw1 commented 1 year ago

@marcusx2 yes that's correct. The objects are positioned once, when the first GPS position is received. If you look at the logic of the code you can see that there is a boolean which controls this.

After they are positioned, they will be fixed in space, but the camera will (or should) move as you walk around.

nickw1 commented 1 year ago

@marcusx2 just to let you know, the "four boxes" example (which generates four boxes around your initial GPS position) is available online at:

https://hikar.org/arjs/aframe/examples/new-location-based/basic-js/

Feel free to try this out when you have a moment; it definitely works for me (in that the size of the boxes changes noticeably if I walk 100 metres or so), and if I walk away from them they all get smaller and smaller.

marcusx2 commented 1 year ago

@marcusx2 just to let you know, the "four boxes" example (which generates four boxes around your initial GPS position) is available online at:

https://hikar.org/arjs/aframe/examples/new-location-based/basic-js/

Feel free to try this out when you have a moment; it definitely works for me (in that the size of the boxes changes noticeably if I walk 100 metres or so), and if I walk away from them they all get smaller and smaller.

Do I keep the default values? That 1000? Do I need to tap on go?

EDIT

I tried again. It does work but I need to walk a lot, so it just feels like it doesn't work well. Tried with 2 different phones. I guess I was just expecting it to be way more precise. Anyways, thanks for the help!

nickw1 commented 1 year ago

@marcusx2 due to the accuracy of GPS it will not be completely precise, but it should work reasonably well for a use-case such as labelling a point of interest. Remember GPS accuracy is perhaps around 6-20 metres typically; location-based AR without SLAM will only be as accurate as the GPS chip is. Nonetheless as I said above we are looking to add SLAM.

The 1000 is the minimum GPS accuracy which is accepted. So any GPS readings with 1km accuracy or more will be accepted.

The default frequency of update should be "update as often as possible".

nickw1 commented 1 year ago

Closing this now as this appears to be due to inherent limitations with GPS accuracy.

marcusx2 commented 1 year ago

@nickw1 Hello again Nick, I hope you had a great new year celebration. I hope you don't mind that I few more questions.

1- What is the variable type of the properties described here? I suspect they are all floats except for alert which is obviously a bool and gpsTimeInterval which is a long. Am I right? For example positionMinAccuracy's default value is 100, but it accepts a float as well I think. It would be useful to add this information to the docs.

2- I noticed on the latest commit that you added the distance property to gps-new-entity-place but it's not documented. Could you add this to the docs?

3-Regarding the latLonToWorld(lat, lon) method, is there an example of this method being used with the gps-new-camera ? Is it something deprecated that I should forget about?

4- Are there other methods/properties that I can use for the aframe version that are not described in the docs? I saw that the threejs version has methods such as startGps, do they work on aframe as well or are they for threejs only? Aframe has no methods?

Sorry that I'm using github to ask these questions, ARJS gitter is dead (no replies ever) and I can't post on StackOverflow ;_;. I'll promise to bother you very little and won't spam you with questions. Thank you for your understanding.

nickw1 commented 1 year ago

Hi @marcusx2 I did thanks, hope you did too.

It's fine to ask here but I would recommend moving to the Discussions tab for general discussion, so maybe open a Discussion if you want to ask any further questions.

1 - you are right with the types, I'll try and update the docs when I have a moment.

2 - this is actually documented, if you look at the properties section of gps-new-entity-place on the location-based docs you can see it's described as the current distance in metres from the camera position for that entity.

3 - latLonToWorld() is only used for some specialised cases, such as drawing roads and paths, where the augmented content needs to be created from scratch rather than using A-Frame primitives. It's not needed for displaying POIs. It converts a latitude/longitude into the underlying world coordinates, based on the Spherical Mercator ("Google" projection). You would use it as follows (note: corrected typo, this belongs to gps-new-camera not gps-new-entity-place):

const [worldX, worldZ] = document.querySelector("[gps-new-camera]").components["gps-new-camera"].latLonToWorld(lat,lon);

4 - there are no others, no. The A-Frame version starts and stops the GPS automatically. Note that the A-Frame gps-new-camera is actually a wrapper round the three.js version, this has been done to avoid duplication of functionality and to ease maintenance. Is there any other functionality you were expecting or would like? (EDIT - you can access the underlying three.js location-based object using the threeLoc property of the gps-new-camera).

If you look through the new-location-based examples in the repo, you should be able to see a range of examples of what you can do with the location based components.

marcusx2 commented 1 year ago

Hi @marcusx2 I did thanks, hope you did too.

I did, thank you!

4 - there are no others, no. The A-Frame version starts and stops the GPS automatically. Note that the A-Frame gps-new-camera is actually a wrapper round the three.js version, this has been done to avoid duplication of functionality and to ease maintenance. Is there any other functionality you were expecting or would like? (EDIT - you can access the underlying three.js location-based object using the threeLoc property of the gps-new-camera).

I expected some start/stop and/or a pause/unpause methods, like on mindarjs. I can't start or stop the arjs engine it seems. It just autoruns. What if I have an app that is not solely arjs, and I want to pause the AR functionality to do something else for example?

nickw1 commented 1 year ago

@marcusx2 ok thanks for those ideas. I think we will have to keep the autorun, otherwise existing applications will break.

Note that the pause() and play() methods of the gps-new-camera component stop and start the GPS, respectively. You can force this behaviour by calling those methods yourself, see A-Frame documentation here: https://aframe.io/docs/1.3.0/core/component.html#pause

nicolocarpignoli commented 1 year ago

@marcusx2 A note about AR.js and the missing start/stop methods. You're right, even on NFT and Marker Based AR.js there is no such methods. I think it would be fairly easy to set them up, we didn't for lack of need from ours and other developers.

Anyway, I recently developed an AR.js marker based web app where I needed to change "context" and show an overlay content without having the underlying camera continuously tracking. The trick that currently works is to change the "active" parameter for the AR.js aframe camera (or the correspondent camera for the three.js side). And then active it back when you want to start tracking again. The main loop is still going, but it is not tracking.

document.querySelector('a-entity[camera]').setAttribute('camera', 'active: false');

document.querySelector('a-entity[camera]').setAttribute('camera', 'active: true');

marcusx2 commented 1 year ago

hey @nickw1 I created a topic in the discussion tab. Do you get notifications there as well? Thanks!

nickw1 commented 1 year ago

hey @nickw1 I created a topic in the discussion tab. Do you get notifications there as well? Thanks!

Yes, I've answered that one.