Editing the Nav Stored Locations via SD Card

My Nissan Leaf Forum

Help Support My Nissan Leaf Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
Hi everyone!

Did someone figured this out? Would someone be kind enough to build a PHP function, that would output the 3 values (9,10,11) from the x and y coordinates (1,2)?

I'm currently building a repository for charge station that we will import to our leafs but i'm missing those 3 numbers.

Thanks so much!
 
I can't remember what fields stored the grid data but I believe those are the fields the last two posters were struggling with so here again is my explanatory post. Specifically, grid_data is field 9, x is field 10, and y is field 11, IIRC:
TimeHorse said:
Update: I think I have the equation for converting between the Map Data Grid, X and Y and longitude and latitude and rather than making anyone else suffer, let me spell it out here for all to see. This information wasn't meant to be proprietary, it was meant to be free as in speech, but in this case also free as in beer!

The Grid Data collectively stores a 25-bit number for the longitude (x) and a 25-bit number for the latitude (y). The North American Nissan LEAF maps only distend over a range from 172W to 52W Longitude and from 0N to 80N in Latitude. The North Pole is not part of the map, and neither is Iceland or Europe or the Prime Meridian. Thus one third of the Earth by Longitude (120 degrees or 432,000 arc-seconds) and almost half by Latitude (80 degrees or 288,000 arc-seconds). The mapping between x, y and Longitude, Latitude is a linear function mapping the 25-bit values to their degree, minute, second mapping, respectively, as follows:
Code:
x = (longitude + 172)*65,536 + 15,728,640
y = latitude*98,304 + 16,777,216

longitude = (x - 15,728,640)/65,536 - 172
latitude = (y - 16,777,216)/98,304
This is clearer if hexadecimal is used:
Code:
x = (longitude + 172)*0x10000 + 0x0f00000
y = latitude*0x18000 + 0x1000000

longitude = (x - 0x0f00000)/0x10000 - 172
latitude = (y - 0x1000000)/0x18000
Of course, that assumes you have x and y as the properly formatted, unsigned, 25-bit values. To get those you have to do quite a bit of jiggery-pokery. Specifically, the Data Grid is a negative, 32-bit value. I find it easier treat the grid data as an unsigned 32-bit value in my calculations so for instance -2,147,452,928 (-0x7fff8800) becomes 2,147,514,368 (0x80007800), specifically:
Code:
u = (grid_data & 0x7FFFFFFF) + 0x80000000
grid_data = -(-u & 0x7FFFFFFF)
It has to be done this way to preserve the sign, otherwise the grid_data will lose the upper bits.

That resolved, I've observed that, starting from 0x80000000 as bit zero and 0x00000001 as bit 31, bits 1, 12, 13, 28 and 29 are never used. In other words, 0x400C000C is a mask for all the bits never used in the grid data. Likewise, 0 and 18 are always set (bit 0 means the number is always negative), in other words 0x80002000 is a mask for the always-on bits. Ignoring bits 0, 1 and 18 for the moment, what's clear with bits 12, 13, 28 and 29 is that they don't enter into the calculation of position. What you effectively have when you ignore those bits is:
Code:
yyyyyyyyyyyy00yyxxxxxxxxxxxx00xx
for the format of the upper register of the x and y components, xh and yh, where each letter represents a bit in u starting with bit 0. The conversion is thus:
Code:
xh = ((u & 0xFFF0) >> 2) | (u & 0x0003)
yh = (((u >> 16) & 0xFFF0) >> 2) | ((u >> 16) & 0x3

u = ((yh & 0x3FFC) << 18) | ((yh & 0x0003) << 16) | ((xh & 0x3FFC) << 2) | (xh & 0x0003)
where << means bitwise shift left, >> means bitwise shift right, & means bitwise and and | means bitwise or.

Finally we have the Map Data X and Y components, which are each 11-bit, unsigned values, meaning they go from 0 to 2047; at 2048 the increment the high portion and go back to 0. We'll call these map X and Y points xl and yl respectively.Therefore:
Code:
x = (xh << 11) | xl
y = (yh << 11) | yl

xh = x >> 11
xl = x & 0x7FF
yh = y >> 11
yl = y & 0x7FF
And from x and y you can now compute longitude and latitude as a floating-point number similar to the way its stored in the NavTech app. I've found this calculation to be accurate within 1 arc-second, the resolution of the longitude and latitude floating-point values, which represents about 30m (100 ft) of accuracy in latitude and less in longitude (by a factor of the cosine of the latitude). Ideally, this should be within a half a degree which would be within rounding error. Currently, the error represents as much as one arc-second difference between the Grid Data Longitude and Latitude and the stored Longitude and Latitude.

Anyway, that's the total skinny you've been waiting for. Hope this helps any would-be developer.

Edit: Fixed equation for u in terms of xh and yh thanks to kcarmich.
 
I have discovered the exact formula several months ago independently.
It is slightly simpler than TimeHorse algorithm.
I integrated it into my windows-application (developed with C#) and well tested for the points located in Europe.
I can extract the translation formulas later and place here for free using, if it is necessary for someone. It will be two lines only.
 
Hello!

The algorithm is the following:

Code:
		public static void CalculateSpecialFields(String latitude, String longitude, out String field09, out String field10, out String field11)
		{
			Int32 i1 = Round(Decimal.Parse(latitude) * 48 * 2048);
			Int32 i2 = Round((Decimal.Parse(longitude) * 32 + 4992) * 2048);
			String s1 = "1" + Convert.ToString(i1, 2).PadLeft(24, '0').Insert(11, "00");
			String s2 = "1" + Convert.ToString(i2, 2).PadLeft(24, '0').Insert(11, "00");
			field09 = Convert.ToInt32(s1.Substring(0, 16) + s2.Substring(0, 16), 2).ToString();
			field11 = Convert.ToInt32(s1.Substring(16, 11), 2).ToString();
			field10 = Convert.ToInt32(s2.Substring(16, 11), 2).ToString();
		}

		public static Int32 Round(Decimal val)
		{
			return (Int32)Math.Round(val, MidpointRounding.AwayFromZero);
		}

I arrangeed it in several items to make it more readable.

The latitude and longitude are input parameters.
The field09, field10 and field11 are result values.

I also noticed the following thing. It is not so important, but only some observation :)
It is not necessary to write down any values into the field01 and field02. The Nissan navigation system will write some values to these fields by oneself. But as see, these values are not used by the navigation system at all. Furthermore the field01 and field02 values calculated by the navigation system are slightly differ from the original latitude and longitude which we use for the field09, field10 and field11 calculation. The difference is varied from 0 to 30 metres.
We can skip this difference and this feature at all, because the only field09, field10 and field11 (not field01 and field02) values are used within the navigation system for points displaying on the screen and for routes constructing.
It is easy to make sure of that. Find the point by the latitude and longitude values (which we use in the above algorithm) on the google maps and compare it position with the same point position in the Nissan navigation system. You will see, that the positions are equal in both places, though the field01 and field02 fo the point can differ from the latitude and longitude even to 30 metres sometimes.

I hope my formula is clear and understandable. Any questions are welcome!

Please pardom for my English. It is not my native language :)
 
CentralTransPoint said:
Hello!

The algorithm is the following:

Code:
		public static void CalculateSpecialFields(String latitude, String longitude, out String field09, out String field10, out String field11)
		{
			Int32 i1 = Round(Decimal.Parse(latitude) * 48 * 2048);
			Int32 i2 = Round((Decimal.Parse(longitude) * 32 + 896) * 2048);
			String s1 = "1" + Convert.ToString(i1, 2).PadLeft(24, '0').Insert(11, "00");
			String s2 = "11" + Convert.ToString(i2, 2).PadLeft(23, '0').Insert(10, "00");
			field09 = Convert.ToInt32(s1.Substring(0, 16) + s2.Substring(0, 16), 2).ToString();
			field11 = Convert.ToInt32(s1.Substring(16, 11), 2).ToString();
			field10 = Convert.ToInt32(s2.Substring(16, 11), 2).ToString();
		}

		public static Int32 Round(Decimal val)
		{
			return (Int32)Math.Round(val, MidpointRounding.AwayFromZero);
		}

Hi! Thanks so much for this! Only problem is that I need to convert it to PHP for use on a webpage.

I'm trying to use the follow exemple:
Lat: 45,652778
Long: -72,561944

so if I get it right: (Which I am probably sure I don't)

i1 = 4487851
i2 = -2861056
s1 = 100000000000000004487851
s2 = -11000000000000002861056.
field09 = Makes no sense with all those 0 from PadLeft
field10= Makes no sense with all those 0 from PadLeft
field11 = Makes no sense with all those 0 from PadLeft

The actual result imported from Nissan GPS give:

field09 = -1573672526
field10 = 30
field11 = 699

These number are not even the calculation, my understand is that, except for the i1 and i2 calculation, the number does not changes, it's only data conversion, to fix the format (adding zeros)..

Thanks!
 
I'm surprised to find an entire thread of folks who actually use and wish to improve the Nav. After viewing the outdated data and totally unintuitive Nav app on my 2012SL, I gave up and haven't looked back. Thank goodness Waze was invented!
 
Raiden38 said:
Hi! Thanks so much for this! Only problem is that I need to convert it to PHP for use on a webpage.

I'm trying to use the follow exemple:
Lat: 45,652778
Long: -72,561944

so if I get it right: (Which I am probably sure I don't)

i1 = 4487851
i2 = -2861056
s1 = 100000000000000004487851
s2 = -11000000000000002861056.
field09 = Makes no sense with all those 0 from PadLeft
field10= Makes no sense with all those 0 from PadLeft
field11 = Makes no sense with all those 0 from PadLeft

The actual result imported from Nissan GPS give:

field09 = -1573672526
field10 = 30
field11 = 699

These number are not even the calculation, my understand is that, except for the i1 and i2 calculation, the number does not changes, it's only data conversion, to fix the format (adding zeros)..

Thanks!

Hello Raiden38!

I have got some another results with my formulas and your source data.
So,
i1=4487851
i2=-2920412
s1="101000100011001101010101011"
s2="111111111111000100110111000000100100"

But in any case, as I see, my formulas work wrong with coordinates which are less than zero.
As I said before I tested my program with points located in Europe. So my formulas do not take into account negative coordinates.
If it is not so hard for you, please input some test coordinates within your Nissan navigation system, export points to USB-card and send me exported file. I will try to make my formulas workable with negative coordinates.
Unfortunatelly my Nissan navigation system does not allow me input any coordinates on the Western hemisphere because, the navigation system does not contain any maps for that coordinates. There are only European maps within.
 
Hello!

Thanks a lot to Raiden38 for his file with points. I have changed my formulas. Now they work properly both with East and West points.
I have updated my original message where the formulas are placed.
 
TimeHorse said:
I finished my python script except for parsing the Grid Data location which others who figured out the algorithm are no longer following this thread. You can see the Python code at https://svn.timehorse.com/public-repos/trunk/Code/NissanLEAF/parse_addresses.py"

Replying to an old thread, but big thanks to TimeHorse for his python function. I am swapping my 24kWh LEAF for a 30kWh model and tidying my address book while I transfer it.
 
CentralTransPoint said:
Raiden38 said:
Hi! Thanks so much for this! Only problem is that I need to convert it to PHP for use on a webpage.

I'm trying to use the follow exemple:
Lat: 45,652778
Long: -72,561944

so if I get it right: (Which I am probably sure I don't)

i1 = 4487851
i2 = -2861056
s1 = 100000000000000004487851
s2 = -11000000000000002861056.
field09 = Makes no sense with all those 0 from PadLeft
field10= Makes no sense with all those 0 from PadLeft
field11 = Makes no sense with all those 0 from PadLeft

The actual result imported from Nissan GPS give:

field09 = -1573672526
field10 = 30
field11 = 699

These number are not even the calculation, my understand is that, except for the i1 and i2 calculation, the number does not changes, it's only data conversion, to fix the format (adding zeros)..

Thanks!

Hello Raiden38!

I have got some another results with my formulas and your source data.
So,
i1=4487851
i2=-2920412
s1="101000100011001101010101011"
s2="111111111111000100110111000000100100"

But in any case, as I see, my formulas work wrong with coordinates which are less than zero.
As I said before I tested my program with points located in Europe. So my formulas do not take into account negative coordinates.
If it is not so hard for you, please input some test coordinates within your Nissan navigation system, export points to USB-card and send me exported file. I will try to make my formulas workable with negative coordinates.
Unfortunatelly my Nissan navigation system does not allow me input any coordinates on the Western hemisphere because, the navigation system does not contain any maps for that coordinates. There are only European maps within.

I looked through your formula and it's very snowball in that it relies heavily on strings. I think though going over your numbers of where you insert zeroes and ignored bits they are more or less the same. The main difference is mine works in Europe and North America. I had Nikki test it when she was still in Britain. I also worked with her to define two regions for the python script (Python, BTW, may be easier to translate to PHP as Perl and Python are similar though as a Python programmer I know they helava-not! :D Anyway, this is the region covered by my script: https://fusiontables.google.com/embedviz?q=select+col14+from+1e9nF7jYXcC1U2jeiL1-9PFgXvrsFPlrcKX7RsOYc&viz=MAP&h=false&lat=22.29227308596727&lng=5.890045166015625&t=1&z=2&l=col14&y=2&tmplt=3&hml=KML

As you can see, a European LEAF can go anywhere from Afghanistan to Iceland, though not all of Iceland or Afghanistan. I wanted to work with someone in Iceland in fact to see what regions their LEAF covered. I would also love to work with someone in Australia and Japan to get those regions covered. The Python Script is agnostic with respect to region, it's only in field 7 of the first record (The Address Book header). Beyond that, there is no regional encoding except for that field where North America is 32 and Europe is 48. I would love to learn the other regions and have someone with a LEAF in Australia, Japan, or another region not covered by the map above to create a new address book with bookmarks for the far north-east, far north-west, far south-east, and far south-west regions of their Navigation map and send me the file from the car so I could verify it works in other regions and lock down what field 7 should be in those regions.

Thanks.

Jeffrey.

https://svn.timehorse.com/public-repos/trunk/Code/NissanLEAF/parse_addresses.py

(Sorry, it's still Python 2.7; someone modified it for Python 3.x on Git Hub so feel free to use that; git hub should inform me of changes in case I need to backport.)
 
I have a little update around the storedlocation.slc file.

I wrote some javascript to generate a GPX file with longitude, latide and name of the waypoint. With that script you can generate a GPX file, which you then can convert to a storedlocation.slc with the Python script gpx2slc.py from "goingelectric" (based on parse_adresses.py).

Not a complete automated chain, but it works for me :)

Generator and details:
http://www.arachnon.de/wb/pages/en/nissan-leaf/gpx.php

Greetinx from Munich

marxx
 
I went the extra mile and rewrote the page, so you can now enter latitudes and longitudes and then generate the storedlocation.slc directly online :cool: Even with a little openstreetmap implementation :cool: :cool:

slcgpx_en.jpg


Should work in any browser.

Greetinx

marxx
 
Back
Top