A More Complete iOS Solution to the China GPS Offset Problem
This is a guest post by a friend, [unnamed for now]. It goes quite in-depth into China’s GPS issue, which I’ve complained about here before. The hope is that, armed with the following information, non-Chinese developers will be able to get around the issue more quickly and more effectively. Note that while the information below was applied to iOS app development, it isn’t strictly iOS-specific.
Description of the Problem
One problem that often comes up when people stay in China for an extended period of time is that they find their GPS devices don’t work. Sure your iPhone or Android phone will report your own location just fine, but try using a route tracking feature when you’re jogging or if you use an app showing other people’s GPS locations like Find My Friends, you’ll likely see they’re standing in a river or some place 500 meters away even if they’re standing right next to you.
This is the mysterious China GPS offset problem. This has been covered in a few posts [in Chinese] here, here, and here. Basically the Chinese government strictly controls mapping data within China. It’s illegal to map or create GPS traces within China without authorization. There have been stories of a few foreigners who created hiking trails near sensitive buildings w/ GPS devices being arrested due to relevant local laws.
For popular map apps such as Google Maps or Apple Maps on iOS, the user’s own location will be correct. This is because licensed companies that register with the government will be given the corrected algorithm to adjust the user’s position. Google Maps, Bing and others allow you to search for a location based on the GPS coordinates, but no local Chinese map providers such as Baidu Maps allow you to.
If you had taken a photo near the Forbidden City, load the photo into iPhoto or Picasa and look at where it is on the map you’ll see the location is just a bit off, 300-500 meters and typically about a block or two away. Not far enough to be extremely inaccurate but incorrect enough to annoy and not place you in the proper position.
Two GPS standards
The most common GPS standard used internationally is based on a coordinate system called WGS-84. The globe is an imperfect sphere and any mapping from 3D to 2D introduces some compromises. People who get really into it will note that as you get further away from the equator, the way GPS coordinates for latitude and longitude change aren’t the same even if you’re traveling the same distance. However this is the GPS we’ve come to know and is used globally.
China uses a standard called GCJ-02 which is based off an older Soviet system of coordinates introduced in the 1940’s. It’s converting from WGS-84 to GCJ-02 that we’d like to accomplish. Chinese programmers refer to this coordinate system as the 火星坐标系统 or “Mars coordinate system” (as in you’re mapping from Earth with WGS-84 to Mars in GCJ-02).
Preliminary tries to correct the problem
The first tries in the English-language world to correct for this China offset problem noticed that in local areas like within the city of Shanghai or Beijing, the difference was relatively fixed. That is, if you just subtract a few degrees from the latitude and add a few for longitude, you can correct the position. They quickly realized that the translation was non-linear, though, changing from city to city.
Collecting data points
Approaching this problem myself, I found out that as long as I was within China’s IP range, I would see the iOS simulator report my simulated location correctly, but if I dropped a pin on the same GPS coordinates it would be off. I created a simple app that let you drag the pin back to your real location and after scraping Wikipedia’s list of cities in China, had 657 data points.
Using Excel’s LINEST function you can split the data up into groups and actually get a pretty decent correction that works across the whole country although it will still be off by a few meters. Enough to put you across the street from where you really were or down a few stores.
It turns out if you search in Chinese, several people sell massive data sets of tens of thousands of points within China with their corresponding offset. Apparently people have run into this need before. On Taobao you can find sets from 400 RMB to 900 RMB.
Hints at already solved code
A few English language posts stated that Chinese Android coders had already released the proper algorithm in open source. After several searches in Chinese, finding relevant posts was easy. But the actual ones that solve the problem took more hunting until I found the personal website of Rover Tang and a post on a popular tech site called XCoder.cn.
Solution found and explained
Keeping it brief, the originally released code was a C file that took into account all sorts of height, GPS time and date etc. even though they were unused. This could be found several places online. A refactored and cleaner version of the code is available in C# on EvilTransform.cs.
It’s basically a complicated transform using equations describing an ellipsoid (what the Earth is) from one system of coordinates to another. Once you throw in GPS in WGS-84 you get the same ones back in GCJ-02.
You’ll note that the code interprets that anything within China needs this conversion, anything outside of China, doesn’t. And that China is defined as anything between Latitude 0.83 to 56 and Longitude 72 to 138. I think there’s a few countries caught in that rectangle that might object.
So what now?
So now any web or mobile app developers who need to record GPS paths, post GPS locations, or anything else on top of a map can now have the proper locations. It was a huge relief to me to finally find a solution that works anywhere in China so we can all go back to creating apps that work.
- Overall summary of the situation
- Baidu Baike definition of the Mars Coordinate system
- Explanation of the algorithm with links
- EvilTransform.cs – The most legible version of the code
- iOS code that does Baidu and GCJ-02 to WGS-84
- Links to Taobao offers for data sets: 1, 2, 3
Dec. 23, 2014 Update:
A developer recently found this post vey useful in solving his own China location app problems, but needed some additional information to properly implement the above advice. I’m sharing that extra information below in the hope that it’s useful to more developers:
Apple returns their coordinates in the WGS format and offsets the map when rendering (I thought the coordinates themselves were offset, not the rendered map).
Not mentioned but deduced from the above was that Google does it the other way around… if I’m not mistaken, Google returns the GCJ coordinates for a China location (even if you are not in China)… This explains why Apple’s coordinates are off when input into Google until they are converted into GCJ.
MapKit only offsets the map from devices within China.
Because we were testing on devices in and out of China we weren’t sure where the root problem was; we had tried the conversion, but then tested the results with MapKit on a device that was outside of China.
Fascinating. I put the correction algorithm into python to make it usable for OSX and Linux-users as well.
This is very cool. Should have known someone would be able to figure this out. Now if only the satellite view on Google Maps matched up with the map view.
Hopefully this will be found and used by other map using app coders!
Amazing, this is a very helpful post, thank you!
Has anyone tried entering WGS-84 coordinates and displaying the result on Google Maps in the States?
Hi there great post and the best explanation I’ve found in the web so far. What I’m still puzzled about is why this is the case. Is it because google maps somehow collaborates with the Chinese government. Surely the GPS is accurate as it comes from US Satellites so why don’t google just use maps that correspond with that and cut the Chinese out of the equation. Also many posts state that satellite view is correct but the street view is incorrect. I’ve found this to be the other way round on google maps for iPad (quite new I believe). On my iphone it seems to be correct in both views on apple and google maps.
Now I dare say there won’t be a logical answer to this but Why Oh Why! This is nonsensical if the US military wanted to bomb China they won’t be relying on google maps. Either this is completely paranoid and illogical (wouldn’t surprise me at all in China) o there must b some commercial reason behind this that benefits Chinese companies. Any explanation much appreciated particularly in regard to the google collaboration but. Cheers
Okay slight correction. Google maps on my iPhone also displaying wrong location in Satellite view. Apple Maps perfect. I guess any potential wrongdoer should just get an iPhone to beat China’s paranoid mapping bureau
Thanks a lot . The code works really well. I also find a project on github which looks like ported from java.
Isn’t it a case that the GPS is true, and that’s why they match with satellite imagery (not controlled by China) but don’t match the maps because the maps are offset (controlled by China).
You are actually making your true GPS location inaccurate to match an inaccurate map, however this is desirable from a practical point of view if you want to see your traces/points align with the map view.
Is that correct?
[…] is the actual story? The best I’ve found is this post, but the explanations it links to are in Chinese. This looks like the type of pervasive problem […]
That’s an amazing explanation! Thank you!
[…] this is why the reference frame upon which China bases all its maps is known as ‘Mars Coordinates’ — as if they are not describing Earth’s geography at all! Mars Coordinates, or GCJ-02 […]
hey author, thanks for the post.
Just a small question, will the mapkit provide directions and ETA for the POI’s in china?
Right now, when i check them on simulator, it never shows any directions and say it doesnt have any directions for this location.
but works for other supported countries outside china.
Hi, Since 2013 I’ve been to China about 8 times (to Beijing, Shanghai and Taipei). My google maps in iOS had always worked until my last trip last summer 2017. It was fine for 2 days in Beijing, and as soon as I arrived in Shanghai, the offset appeared. It didn’t go away until I flew out of Shanghai and went to Taipei. All was fine again in Taipei. Any clues what happened there? Is there anything I can do as a user to fix this if it appears again? I’m going again in a few months, and I was contemplating buying a Garmin GPS device. I think theres a way to install an offset file in that thing. Any enlightening comments greatly appreciated.