Awesome
Motion - iOS accelerometer, gyroscope, magnetometer readings and more for Fuse
<p align="center"> <img alt="App preview" src="https://github.com/AlexGustafsson/fuse-motion/raw/master/assets/preview.gif"> <p>Motion is an easy to use integration of all iOS's sensors reflecting motion, made for Fuse. It enables easy creation of compasses, motion trackers, activity trackers and so on.
Quickstart
<a name="quickstart"></a>
Install Motion
Right now a manual installation is required. Requires Fuse 0.30.0 or above.
Copy the following files to your project:
- Motion.js
- Motion.hh
- Motion.mm
- Motion.uno
Update your .unoproj
to reflect the following changes:
"Packages": [
"Fuse",
"FuseJS",
"Fuse.Scripting"
],
"Includes": [
"Motion.hh:ObjCHeader:iOS",
"Motion.mm:ObjCSource:iOS",
"*"
],
"iOS": {
"PList": {
"NSMotionUsageDescription": "Motion access motivation"
}
}
note, the user is only asked to allow motion usage when subscribing to activity
Implementing Motion
Subscribe to sensor updates:
<JavaScript>
var Motion = require("Motion");
Motion.Subscribe("accelerometer magnetometer gyroscope motion activity", 0.2);
</JavaScript>
Optional:
Include Motion in your App's MainView.ux
to export all measurements as observables:
<JavaScript File="MotionJS.js"/>
Table of contents
Quickstart<br/> Using Motion<br/> Examples<br/> Contributing<br/> Disclaimer
Using Motion
<a name="how"></a>
Note: API is due to change, stay updated. Until then, use the source, Luke.<br />
The API is pretty final. If you've got any feedback, please make your voice heard.
Implementing observables
Include Motion in your App's MainView.ux
:
<JavaScript File="MotionJS.js"/>
Access the values using the same names as the JS API. See the "values" example for all available values.
<Text Value="{magnetometer.magneticField.x}" FontSize="20"/>
Subscribing to updates
To save resources when they are not needed, subscription is used to only grab values from the device when needed. Subscribe only to the events you need and when you need them.
<JavaScript>
//Global module with a static instance - can be used anywhere
var Motion = require("Motion");
//Subscribe to changes from all available sensors with an interval of 0.2 seconds
Motion.Subscribe("accelerometer magnetometer gyroscope motion activity", 0.2);
</JavaScript>
To release resources when they are no longer needed, unsubscribe to updates whenever possible.
//Unsubscribe to all changes
Motion.Unsubscribe("accelerometer magnetometer gyroscope motion activity");
See the Apple webpage on selecting a proper interval.
Interval (s) | Usage |
---|---|
0.1 - 0.05 | Suitable for determining a device’s current orientation vector. |
0.03 – 0.017 | Suitable for games and other apps that use the accelerometer for real-time user input. |
0.014 – 0.01 | Suitable for apps that need to detect high-frequency motion. For example, you might use this interval to detect the user hitting the device or shaking it very quickly. |
Listening for updates
To retrieve the actual values, events are used.
Note: In their current state, Fuse <br />
Fuse 0.30.0 came with an overhauled event system. As such proper events are now implemented in Motion.NativeEvents
don't allow for more than one "listener". As such you can only subscribe to the events once. Subscribing again will override any previous subscriptions. Since Motion already listens to the updates in order to share the values to UX, listening for the updates will disable that feature.
<JavaScript>
Motion.on("accelerometerChanged", function(values){
values = JSON.parse(values);
if(!values.error)
console.log("Accelerometer values:", values);
});
Motion.on("gyroscopeChanged", function(values){
values = JSON.parse(values);
if(!values.error)
console.log("Gyroscope values:", values);
});
Motion.on("motionChanged", function(values){
values = JSON.parse(values);
if(!values.error)
console.log("Motion values:", values);
});
Motion.on("magnetometerChanged", function(values){
values = JSON.parse(values);
if(!values.error)
console.log("Magnetometer values:", values);
});
Motion.on("activityChanged", function(values){
values = JSON.parse(values);
if(!values.error)
console.log("Activity values:", values);
});
</JavaScript>
Accessing values directly in UX
Motion exposes several values directly to UX Markup.
Note: In their current state, Fuse <br />
Fuse 0.30.0 came with an overhauled event system. As such proper events are now implemented in Motion.NativeEvents
don't allow for more than one "listener". As such you can only subscribe to the events once. Subscribing again will override any previous subscriptions. Since Motion already listens to the updates in order to share the values to UX, listening for the updates will disable this feature.
The following values are exposed:
var accelerometer = Observable({
acceleration: {x: 0, y: 0, z: 0}
}),
gyroscope = Observable({
rotationRate: {x: 0, y: 0, z: 0}
}),
magnetometer = Observable({
magneticField: {x: 0, y: 0, z: 0}
}),
motion = Observable({
attitude: {yaw: 0, pitch: 0, roll: 0},
rotationRate: {x: 0, y: 0, z: 0},
gravity: {x: 0, y: 0, z: 0},
magneticField: {accuracy: -1, x: 0, y: 0, z: 0},
userAcceleration: {x: 0, y: 0, z: 0}
}),
activity = Observable({
unknown: true,
stationary: false,
walking: false,
running: false,
automotive: false,
cycling: false,
confidence: "low"
});
If you are unsure how to use values exposed from javascript through Observables
check out the Fuse documentation and this example.
Examples
<a name="examples"></a>
Demo app
When built, this project will act as an app showcasing all the examples.
Values
Displays all available values.
Gravity
Uses the magnetometer to apply a gravity effect to a dropshadow.
Shock
Uses the accelerometer to detect when the phone is hit.
Swipe
No more phone thumb from "swiping right"! Train your wrist by using the gyroscope to enable a swipe like feature.
Contributing
<a name="contributing"></a>
Any help with the project is more than welcome. This is my first take on Uno and Objective-C so some things might not be following best practices or be incorrectly implemented all together.
TODO:
- Integrate Motion in UX via
animators
Implementactivity updates
Make multiple event listeners possibleMake API more developer-friendlyImprove documentation- Add more examples
- Make compatible with fusepm
Disclaimer
<a name="disclaimer"></a>
Although the project is very capable, it is not built with production in mind. Therefore there might be complications when trying to use Motion for large-scale projects meant for the public. Motion was created to easily integrate sensor readings on iOS and as such it might not promote best practices nor be performant.
Built with Fuse 0.30.0 (build 8529) and Xcode Version 8.1 (8B62), tested on iPhone 6 iOS 10.2 and 10.2.1. Tested with Fuse 1.1.0 (build 13808).