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.