- 26 Feb 2024
- 3 Minutes to read
- Print
- DarkLight
Intro to SMFit - iOS
- Updated on 26 Feb 2024
- 3 Minutes to read
- Print
- DarkLight
SMFit is a 'core level' SDK which allows direct access to SencyMotion's fitness domain functionalities and features. Using this SDK you'll get full flexibility to create your own workout structures by simply implementing easy to use APIs, and build your own UI on top of it.
Installing SMFit
Install via Cocoapods:
source 'https://bitbucket.org/sency-ios/sency_ios_sdk.git'
source 'https://github.com/CocoaPods/Specs.git'
target 'YourApp' do
use_frameworks!
pod 'SMFit', '0.2.0'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '14.5'
end
end
end
Configuring SMFit
Configure the SDK on app launch:
import UIKit
import SMFit
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
SMExerciseFlowManager.configure(authKey: "YOUR_AUTH_KEY") {
// success
} onFailure: { error in
// failure
}
return true
}
}
Call SMSessionManager to configure with your auth key. This process might take a few seconds and if you try to do anything else with SMFit before it completes, you will receive an error.
Using SMFit
InitSMExerciseFlowManager
First, init the SMExerciseFlowManager
class ViewController: UIViewController {
var flowManager:SMExerciseFlowManager?
override func viewDidLoad() {
super.viewDidLoad()
//If Auth passes successfuly
do{
flowManager = try SMExerciseFlowManager(delegate: self)
}catch{
print(error)
}
}
}
extension ViewController:SMFitSessionDelegate{
func captureSessionDidSet(session: AVCaptureSession) {
//You can use this to present the camera output
}
func captureSessionDidStop() {
//If the camera session stops this function will be called
}
func handleDetectionData(movementData: MovementFeedbackData?) {
//In here you will receive all of the detection data
}
func handlePositionData(poseData: [Joint : CGPoint]?) {
}
func handleSessionErrors(error: Error) {
print("handleSessionErrors: ", error)
}
}
Make sure to conform to SMFitSessionDelegate:
- captureSessionDidSet - Once the camera data is available this function will be called with a AVCaptureSession you then can use it to present the camera output
- captureSessionDidStop - If the camera session stops this function will be called
- handleDetectionData- This function will be called every frame with the following data:
- MovementFeedbackResultData- This struct holds all the feedback data
- didDetectRep - (Dynamic exercise) If user did perform repetition
- isGoodRep - (Dynamic exercise) true if the repetition was good
- isInPosition - (Static/Isometric exercise type) true if the user in position
- currentRomValue - The current Range Of Motion of the user
- specialParams - some dynamic exercises will have some special params for example the exercise "Jumps" has "JumpPeakHeight" and "currHeight"
- MovementFeedbackResultData- This struct holds all the feedback data
- handlePositionData -This function will be called every frame with the following data:
- poseData - This a dictionary of joints and there position (can be empty if the user was not detected in the camera field of view)
Start the exercise session
Initiate the session:
func startSession(){
do{
try flowManager?.startSession()
}catch{
print(error)
}
}
Start detection:
func startDetection(){
do{
try flowManager?.startDetection(exercise: "HighKnees")
}catch{
print(error)
}
}
Go to Sency's exercise library to view the currently supported exercise types
Stop detection:
func stopDetection(){
do{
let exerciseSummary = try flowManager?.stopDetection()
}catch{
print(error)
}
}
When you stop exercise detection you will get all detected data packed in a struct of type SMExerciseInfo:
- sessionId - current session Id
- startTime - the exercise start time
- endTime - the exercise end time
- totalTime- time in seconds from start to end detection
In addition you will get different data according to the type of the workout:
- SMExerciseDynamicInfo
- numberOfPerformedReps - the number of the performed reps
- repsTechniqueScore - the exercise score
- performedReps - array of RepData
- SMExerciseStaticInfo
- timeInActiveZone - time the user was in position
- positionTechniqueScore - the exercise score
Stop session:
func stopSession(){
let allSummary = flowManager?.stopSession()
}
When you stop session detection you will getall of the session's detected data packed in a struct of type DetectionSessionResultData which is the summary of the entire session:
- exercises - all SMExerciseInfo of the session
- startDate - the start date of the session
- endData - the end date of the session
Calibration observers
Device motion observer:
flowManager?.setDeviceMotionActive(
phoneCalibrationInfo: SMPhoneCalibrationInfo(
YZAngleRange: 63.0..<70.0,
XYAngleRange: Float(-5.0)..<Float(5.0)
),tiltDidChange: { (tiltInfo) in
// handle tilt data
})
Body positioning observer:
flowManager?.setBodyPositionCalibrationActive(delegate: self, screenSize: self.view.frame, boundingBox: rect)
extension ViewController:SMBodyCalibrationDelegate{
func didEnterFrame() {
// indicates the user is positioned 'inside' the 'rect' defined in "setBodyPositionCalibrationActive"
}
func didLeaveFrame() {
// indicates the user is positioned 'outside' the 'rect' defined in "setBodyPositionCalibrationActive"
}
func didRecivedBoundingBox(box:CGRect){
// since 'boundingBox' is optional in "setBodyPositionCalibrationActive", you will get the default 'rect' if you haven't added this argument
}
}
List of possible SMFit errors
- AuthKeyNotAccepted
- UnableToGetNNModels
- FailedLoadingNNModel
- DidNotFindModelPath
- CouldNotGetVisionRequest
- ROMModelNoImplementationError
- FailedToInitDetector
- IllegalJumpThreshold
- NNModelTypeNoImplementationError
- NNModelMissingLocalUrl
- CameraIsAlreadyRunning
- DetectionAlreadyRunning
- NoDetectionSessionRunning
- UnableToStartCamera
- UnexpectedCameraError