MoffKalast / vizanti

A mission planner and visualizer for controlling outdoor ROS robots.
https://wiki.ros.org/vizanti
BSD 3-Clause "New" or "Revised" License
133 stars 26 forks source link

Navsat Tile Zoom Levels (ROS2) #74

Closed MoffKalast closed 1 month ago

MoffKalast commented 2 months ago

Addressing https://github.com/MoffKalast/vizanti/issues/4

MoffKalast commented 2 months ago

This also brings up that the grid is clamped to 10km as the max cell size, so it might be good to also add another two zeros there if we're going up to these scales. :smile:

MoffKalast commented 2 months ago

Ah I've figured out what the weird cross-zoom flashing was, when a fix is received a few zoom-dependant calculations are baked into the main object and that's used until the next one is received. So if your NavSatFix is being published at higher than rendering rate you wouldn't notice anything. I had a debug setup with a 5hz publisher which made it glaringly obvious. 😄

The fix for that is to just re-run those calculations when the zoom level changes and the flicker is gone for good.

So moving the calculations from the listener:

    listener = map_topic.subscribe((msg) => {

        if(isNaN(msg.longitude) || isNaN(msg.latitude)){
            status.setError("Invalid fix.");
            return;
        }

        map_fix = msg;
        updateFixData();
        drawTiles();
    });

To a function:

function updateFixData(){
    const tilePos = navsat.coordToTile(map_fix.longitude, map_fix.latitude, zoomLevel);
    const tileCoords = navsat.tileToCoord(tilePos.x, tilePos.y, zoomLevel);
    const nextTileCoords = navsat.tileToCoord(tilePos.x+1, tilePos.y+1, zoomLevel);
    const metersSize = navsat.tileSizeInMeters(map_fix.latitude, zoomLevel);

    fix_data = {
        tilePos: tilePos,
        tileCoords: tileCoords,
        offset:{
            x: navsat.haversine(map_fix.latitude, tileCoords.longitude, map_fix.latitude, map_fix.longitude),
            y: navsat.haversine(tileCoords.latitude, map_fix.longitude, map_fix.latitude, map_fix.longitude)
        },
        metersSize: metersSize,
        degreesPerMeter: {
            longitude: Math.abs(tileCoords.longitude - nextTileCoords.longitude)/metersSize,
            latitude: Math.abs(tileCoords.latitude - nextTileCoords.latitude)/metersSize
        }
    }
}

And then also calling it here:

    if(tempZoomLevel != zoomLevel){
        navsat.clear_queue();
        zoomLevel = tempZoomLevel;
        updateFixData();
    }

I'm looking into tile culling a bit, but it's still every bit as confusing as it was last time. My working theory is that it might have something to do with WGS meters not being consistent with ROS meters (tiles along the equator are smaller than at the poles in meters), so some kind of error builds up as you get further away from the origin. Messing around with that hasn't really yielded any positive results on my end though.

MoffKalast commented 2 months ago

We should also add this wrap around to the drawTile function so it correctly handles the date line, otherwise nothing loads beyond it since the tile coords are out of range:

    function drawTile(screenSize, i, j, tempMeterSize ,tempZoomLevel){
    const maxtile = Math.pow(2, tempZoomLevel) - 1;

    //wrap around the date line
    const x = (fix_data.tilePos.x + i + maxtile + 1) % (maxtile + 1);
    const y = (fix_data.tilePos.y + j + maxtile + 1) % (maxtile + 1);

It might make sense to also somehow wrap around the actual view metric coordinate system at that point, since if you end up going all the way around back to the tf origin there's nothing there because it's technically super far away lol.

MoffKalast commented 1 month ago

Alright I'll merge this into ros2-navsat-additions for now so I can implement a few extra ideas and upstream it to Noetic too, though I still don't have any clear solution on the culling issue. It's looking more and more like the calculations are correct and it might be a genuine precision problem. Let me know if you figure out anything more regarding that @kosmonauta144