Hi all, and thank you for your help!
Let me give you an orderly update on where I am, for what it's worth:
@JonB (first post):
I followed your advice as follows;
- first, I did create that custom view class you suggested in order to accomodate the 'will_close' actions (I basically copy/pasted @Phuket2 approach from another thread; I had read about 'custom classes' before and understood the overall concept, but had no idea how to implement them; in the process I finally learned where all those 'event' calls (on load, on close...) would go, which I was wondering since some time now; thx @Phuket2!); as soon as I did that, the heading updates kept up on coming regularly with no interruption; beats me why? Closing the view did not stop the updates from coming up, as I had not added the stopUpdatingHeading() command yet.
- I then added the stopUpdatingHeading() in the 'will_close' method; as expected, this would now stop the updates when the view was closed. Again, something I did not know where to fit in the script. Thx!
- I then proceeded to add the startUpdatingLocation / stopUpdatingLocation in the same fashion, and behaviour was as expected: I was getting now heading and location updates regularly.
- I also turned back the filter to 1 degree change thresholds; updates continued to be received regularly as expected in 1 degree changes now.
- I'll discuss the calibration and actual update analysis at the end of the post.
Well, I did check the location and motion modules some weeks ago as they seemed what I needed , but mixed results encouraged me to go another route (this might be my misunderstanding or I was not using them properly, and I may need to revisit them):
- concerning the motion module (.getmagneticfield()), initially I fell in the (0,0, 0.0, 0.0, -1) trap that has been reported in old posts, and that seemed to be related to the calibration; somehow this seemed to get resolved on its own -I frankly do not remember exactly how, I think t did move the device around for calibration and then it started pumping updates; however, i than realized that I did not know how to 'convert' the x,y,z vector into a heading in degrees, and did not find any 'simple' readings that could help me there. (Any suggestions?)
- concerning that location module, I did get the lat/lon readings, but 'course' and 'speed' was always -1 (I first thought this was an issue of not moving fast enough or having enough data for the device to calculate, but I remember doing some tests in a moving car and the values were always -1; still, I have the feeling now that his is just a matter of not understanding well how this works, so open to suggestions / pointers to tutorials.
@JonB (second post):
just saw it (I'm on GMT timezone), so I will look into your kind code example for further help, and particularly for those 'best practices' and more robust foolproof checks;
Now, so far so good, that's some progress there thanks to you all;
However after my success into getting those heading and location updates, I ran some tests in a moving car running the script on the iPhone8 and the iPad2 simultaneously and I'm puzzled with the results; in a nutshell,
location readings were accurate and consistent in both,
the headings they reported were highly different readings (tens, even hundreds of degrees offset),
to make things worse, checking occasionally with the iPhone compass app gave a third different set of readings; I moved both devices in the 'calibration' pattern several times; when I did that, it looked like the readings made a 360° circle themselves, but that did not seem to make the readings more consistent between devices/apps. Note that I have NOT yet implemented the locationManagerShouldDisplayHeadingCalibration: I'm aware of that but need to look at the documentation and figure out how to do it first!
I also remarked that the rate of change in headings in the script is way 'faster' (meaning much more 'sensitive' to change, if that makes sense) than in the iPhone compass app, giving me the impression that the Apple app is somehow 'smoothed' or averaged;
So I'm now wondering:
- do magnetometers behave somehow like traditional compasses in boats or planes, where each compass is different from one another and is delivered with an individual 'deviation curve' that needs to be factored-in in the reading? Basically, the deviation curve tells you how many degrees to add/subtract for every heading indication (0° to 359°) in order to get a proper reading;
- I'm no physician, but should I expect that using the two devices simultaneously (or even the script and the Apple app on the same device simultaneously) would impact each other because of the presence of different magnetometers? or is the influence of the metallic mass of the car so important as to make the readings so disparate? but if this is so, what would be the use in a plane, where you also have other compasses and a big metallic mass?
So I ended up going to sleep wondering whether external precision magnetometers exist that you can use via Bluetooth offering an API in order to get precise and reliable readings.....
As I said, open to suggestions and pointers I may have missed,
PS: I promised it would be short, but it's still a long post...
This is my first post here, but before I go into details, a big thank you to @omz for this amazing tool and all the Pythonista community for all the help I've been silently getting from your posts. Thank you all!
I apologize in advance for this first long post, I promise future ones will be shorter.
I'm relatively confident with Python and I've been programming in different languages (namely VB, Perl and Python) for many years, both for business and mostly for pleasure. I'm quite new to Pythonista and IOS programming, though, and all in all by no means a professional coder, more of a 'quick and dirty' inefficient DIY builder, which I'm sure you'll easily spot in my poor code. I'm also stubborn, and don't like to bother people if I can learn from others independently or find a way to do the job myself, so I've been delaying the moment to come for help; but the moment has now arrived.
I'm a private pilot in my spare time, and I'm writing a prototype app for a custom flight log and associated utilities that I would like to have in my flights. At this point in time, I wanted to add heading (from magnetometer) and then course (from GPS) information in order to compute wind drift conditions, so I started writing a little separate module using the objc_util bridge.
For the time being, this simply creates a CLLocation manager object, starts the heading updates, uses the didUpdateHeading delegate to receive the updates and presents the information in a simple view with a couple of label objects. I'm also printing out to the console for debugging purposes.
It took me quite some time to figure out how to get this heading information working, but now that I finally I got it I'm stuck with the fact that the heading updates simply stop after a random number of updates are received (say in 5 to 10 seconds); as I start moving the device pointing at different positions, sometimes I may receive forty or fifty updates, sometimes only five or six. I get no error message (or at least I can't see any), it just looks like the script is frozen. I can close the view, but when I do this the [x] button in the console is grayed out; for some reason I have the feeling that the process is still running and listening for updates but these are simply either not received or not reflected in the view label or printed out to the console. It would seem to me that the systems might be overloaded with updates? This seems odd to me, since any other 'compass' app out there is obviously reporting all updates constantly. I need best accuracy and frequency for my purposes, but still I tried to use the filter variable to reduce the frequency and report only updates greater than 3 degrees; the filter works, but the behaviour is still the same, updates stop rather quickly.
If I try to use location updates (startUpdatingLocation() for GPS lat/lon position), it is even worse; I get a couple of location updates at most, maybe a couple of heading updates, sometimes none, and then it freezes. So I commented out location updates for the time being.
So all this still leads me to believe there is some kind of problem regarding competing resources, several script processes running or something similar going on, but I have no idea how to even debug the situation.
I have been testing on two different platforms with similar results:
- iPad 2nd gen, GPS and GSM capabilities on IOS 9.3.5
- iPhone 8 on IOS 12.1.2
And Here is my code:
Any help truly appreciated!
# coding: utf-8 from objc_util import * import ui def printMethods(whichObject): #print (dir(whichObject)) for method in dir(whichObject): print (method) #- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading; def locationManager_didUpdateHeading_(self, _cmd, manager, newHeading): headingObj = ObjCInstance(newHeading) print ("Magnetic:", headingObj.magneticHeading()) print ("True:",headingObj.trueHeading()) print ("ACCURACY:",headingObj.headingAccuracy()) v['m_Heading_value'].text = str(int(headingObj.magneticHeading())) def locationManager_didUpdateLocations_(_self,_cmd,manager,locations): locations=ObjCInstance(locations) print (locations.coordinate().a) print (locations.coordinate().b) def locationManager_didFailWithError_(_self,_cmd,manager,error): error=ObjCInstance(error) print (error) methods = [locationManager_didUpdateHeading_,locationManager_didUpdateLocations_,locationManager_didFailWithError_] protocols = ['CLLocationManagerDelegate'] MyLocationManagerDelegate = create_objc_class('MyLocationManagerDelegate', methods=methods, protocols=protocols) v = ui.load_view() @on_main_thread def mymain(): CLLocationManager = ObjCClass ('CLLocationManager') myloc = CLLocationManager.alloc().init().autorelease() #print (printMethods(myloc)) delegate = MyLocationManagerDelegate.alloc().init() myloc.setDelegate_(delegate) locationAvailable = CLLocationManager.headingAvailable() print ("HEADING AVAILABLE") print (locationAvailable) print ("CURRENT HEADING ORIENTATION") print (myloc.headingOrientation()) print ("NEW HEADING ORIENTATION") myloc.headingOrientation = 3 print (myloc.headingOrientation()) myloc.headingFilter = 3 print ("NEW THRESHOLD") print (myloc.headingFilter()) print ("START MONITORING ") #myloc.startUpdatingLocation() myloc.startUpdatingHeading() v.present('sheet') if __name__ == '__main__': mymain()