Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An interface proposal for a CoreMotion wrapper #357

Closed
colinta opened this issue Mar 29, 2014 · 5 comments
Closed

An interface proposal for a CoreMotion wrapper #357

colinta opened this issue Mar 29, 2014 · 5 comments

Comments

@colinta
Copy link
Contributor

colinta commented Mar 29, 2014

Hi, this is a first-draft of an interface for CoreMotion. @markrickert, @clayallsopp - what do you guys think?

Motion

Interface for the accelerometer, gyroscope, and magnetometer sensors (the
CoreMotion framework). You can access each sensor individually, or you can get
data from all of them at once using the BW::Motion.device interface, which
delegates to CMMotionManager#deviceMotion.

Each sensor has an every and once method. every expects a time interval,
and you will need to retain the object it returns and call #stop on it when
you are done with the data.

The every and once methods can accept a :queue option. The default value
is a queue that runs on the main loop, so that UI updates can be processed in
the block. This is useful, but not recommended by Apple, since the events can
come in at a high rate. If you want to use a background queue, you can either
specify an NSOperationQueue object, or you can use one of these symbols:

  • :main - NSOperationQueue.mainQueue, this is the default value.
  • :background - BubbleWrap will create a new NSOperationQueue.
  • :current - BubbleWrap will use NSOperationQueue.currentQueue.

If you pass a string instead, a new queue will be created and its name
property will be set to that string.

The CMDeviceMotion interface (BW::Motion.device) accepts a :reference
option, which specifies the CMAttitudeReferenceFrame. The default value is
the same as the one that CMMotionManager uses, which is returned by the
CMMotionManager#attitudeReferenceFrame method. This option should be passed
to the every or once method.

Accelerometer
BW::Motion.accelerometer.available?
BW::Motion.accelerometer.data  # returns CMAccelerometerData object or nil

# ask the CMMotionManager to update every 5 seconds
listener = BW::Motion.accelerometer.every(5) do |result|
  # result contains the following data (from CMAccelerometerData#acceleration):
  p result[:x]
  p result[:y]
  p result[:z]
  p result[:data]  # the CMAccelerometerData object
end
# you can specify a :queue where the operations will be executed.  See above for details
listener = BW::Motion.accelerometer.every(5, queue: :background) { |result| ... }
listener = BW::Motion.accelerometer.every(5, queue: :main) { |result| ... }
listener = BW::Motion.accelerometer.every(5, queue: :current) { |result| ... }
listener = BW::Motion.accelerometer.every(5, queue: 'my queue') { |result| ... }

# later, you will need to turn off these events:
listener.stop

BW::Motion.accelerometer.once do |result|
  # ...
end
Gyroscope
BW::Motion.gyroscope.available?
BW::Motion.gyroscope.data  # returns CMGyroData object or nil

# ask the CMMotionManager to update every second.
listener = BW::Motion.gyroscope.every(1) do |result|
  # result contains the following data (from CMGyroData#rotationRate):
  p result[:x]
  p result[:y]
  p result[:z]
  p result[:data]  # the CMGyroData object
end
listener.stop

BW::Motion.gyroscope.once do |result|
  # ...
end
Magnetometer
BW::Motion.magnetometer.available?
BW::Motion.magnetometer.data  # returns CMMagnetometerData object or nil

# ask the CMMotionManager to update every second
listener = BW::Motion.magnetometer.every(1) do |result|
  p result[:x]
  p result[:y]
  p result[:z]
  p result[:accuracy]  # this will be a symbol, :low, :medium, :high, or nil if the magnetic data is uncalibrated
end
listener.stop

BW::Motion.magnetometer.once do |result|
  # ...
end
Device Motion

This is an amalgam of all the motion sensor data.

BW::Motion.device.available?
BW::Motion.device.data  # returns CMDeviceMotion object or nil

BW::Motion.device.every(1) do |result|
  # result contains the following data:
  # orientation data, from CMDeviceMotion#attitude
  p result[:roll]
  p result[:pitch]
  p result[:yaw]
  # rotation data, from CMDeviceMotion#rotationRate
  p result[:rotation_x]
  p result[:rotation_y]
  p result[:rotation_z]
  # gravity+acceleration vector, from CMDeviceMotion#gravity
  p result[:gravity_x]
  p result[:gravity_y]
  p result[:gravity_z]
  # just the acceleration vector, from CMDeviceMotion#userAcceleration
  p result[:acceleration_x]
  p result[:acceleration_y]
  p result[:acceleration_z]
  # the magnetic field, from CMDeviceMotion#magneticField
  p result[:magnetic_x]
  p result[:magnetic_y]
  p result[:magnetic_z]
  p result[:magnetic_accuracy]  # this will be a symbol, :low, :medium, :high, or nil if the magnetic data is uncalibrated

  # less useful data, unless you're into the whole linear algebra thing:
  p result[:matrix]  # CMAttitude#rotationMatrix
  p result[:quarternion]  # CMAttitude#quarternion

  p result[:data]  # the CMDeviceMotion object
end

# the reference frame should be one of the CMAttitudeReferenceFrame constants.
ref = CMAttitudeReferenceFrameXArbitraryZVertical
BW::Motion.device.every(1, queue: :background, reference: ref) { |result| ... }

BW::Motion.device.once do |result|
  # ...
end
@markrickert
Copy link
Collaborator

I like it! However, do you feel like this should go into BubbleWrap? What about making it its own thing?

@colinta
Copy link
Contributor Author

colinta commented Mar 31, 2014

It could, but it bears a striking resemblance to BW::Compass and BW::Location... I like that we have a collection of "Core-*" wrappers in a community project, too.

@clayallsopp
Copy link
Contributor

Looks good - I wonder if CMDeviceMotion#attitude, CMDeviceMotion#gravity, CMAttitude#rotationMatrix and CMAttitude#quarternion should have their own convenience methods, since (I believe) the only way to get those with this API is with device.every.

or maybe allow BW::Motion.device to be scoped like BW::Motion.device(:attitude, :gravity, :matrix) etc?

@colinta
Copy link
Contributor Author

colinta commented Apr 1, 2014

I looked at the device motion stuff again, and it's not able to be scoped; the data will be there regardless, so might as well have it in the result object.

I'm not a big fan of how the result objects looks for the BW::Motion.device interface, though. It would make sense to 'scope' those results, so that they look like the other result objects.

The hash interface was meant to be similar to the other Location & Compass result objects.

@colinta
Copy link
Contributor Author

colinta commented Apr 18, 2014

See #366

@colinta colinta closed this as completed Apr 18, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants