Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
interactive animation based on orientation data of IMU
-
Hi,
I wanted to ask if they are any examples of how to make up an animation moving based on incoming orientation data that is sent via Bluetooth from a wearable sensor?
I tried to use pygame but it did not work? I checked scene but it looks like it is not the right one.
-
@ProgrammingGo, what kind of an animation are you planning? Some kind of s pointer? 2D or 3D?
-
This post is deleted! -
Hi thank you for your feedback,
I want to depict a cube that is moving based on the incoming data from the wearable sensor. Maybe I could use Euler angles and Quaternions. I think it should be 3d. An example of something similar to that I want to do is this video: link text -
@ProgrammingGo Is your problem only a problem of animation or also the incoming of the data in BT?
-
I know how to get the data, the problem is how to do the animation. Or what do you mean by problem with the data?
-
@ProgrammingGo ok, just to be sure that you know how to get the data in BT because, for this, I can't help you.
In a few hours, I'll send something to test... -
Okay thank you soo much! Could I display human body as well?
-
@ProgrammingGo wooo,wooo, one thing at a time. If you want to display a body, do you have a lot of IMU sensors, for instance one for each finger? 😀
-
@ProgrammingGo, check this thread and the linked github repo for a SceneKit wrapper with lots of samples.
Mr @pulbrich can surely help you get going with it.
-
@ProgrammingGo sorry, not a lot free time now, please, try this
from objc_util import * import ctypes import ui from math import pi from ImageColor import getrgb load_framework('SceneKit') SCNView, SCNScene, SCNBox, SCNNode, SCNMaterial, SCNCamera, SCNLight, SCNAction, SCNLookAtConstraint = map(ObjCClass, ['SCNView', 'SCNScene', 'SCNBox', 'SCNNode', 'SCNMaterial', 'SCNCamera', 'SCNLight', 'SCNAction', 'SCNLookAtConstraint' ]) @on_main_thread def demo(): global bt,i_bt main_view = ui.View() main_view.name = 'SceneKit IMU' main_view.background_color = 'white' b = ui.ButtonItem() b.title = 'simul bt' i_bt = 0 bt = [ (pi/2,pi/3,pi/4), (pi/3,pi/3,pi/4), (pi/2,pi/5,pi/4), (pi/2,pi/3,pi/8) ] @on_main_thread def b_action(sender): global i_bt,bt # EulerAngles is a SCNVector3 # The order of components in this vector matches the axes of rotation: # Pitch (the x component) is the rotation about the node’s x-axis. # Yaw (the y component) is the rotation about the node’s y-axis. # Roll (the z component) is the rotation about the node’s z-axis. x = bt[i_bt] geometry_node.setEulerAngles(x) i_bt += 1 if i_bt == len(bt): i_bt = 0 b.action = b_action main_view.right_button_items = (b,) main_view_objc = ObjCInstance(main_view) scene_view = SCNView.alloc().initWithFrame_options_(((0, 0),(main_view.width,main_view.height)), None).autorelease() scene_view.setAutoresizingMask_(18) scene_view.setAllowsCameraControl_(True) main_view_objc.addSubview_(scene_view) scene = SCNScene.scene() scene_view.setScene_(scene) root_node = scene.rootNode() camera = SCNCamera.camera() camera_node = SCNNode.node() camera_node.setCamera(camera) camera_node.setPosition((-30,30,30)) root_node.addChildNode_(camera_node) geometry = SCNBox.boxWithWidth_height_length_chamferRadius_(10, 10, 10, 0) geometry_node = SCNNode.nodeWithGeometry_(geometry) root_node.addChildNode_(geometry_node) Materials = [] colors = ['red','blue','green','yellow','orange','pink'] for i in range(0,6): rgb = getrgb(colors[i]) r,g,b = tuple(c/255.0 for c in rgb) Material = SCNMaterial.material() Material.contents = ObjCClass('UIColor').colorWithRed_green_blue_alpha_(r,g,b,1.0) Materials.append(Material) geometry.setMaterials_(Materials) # Add a constraint to the camera to keep it pointing to the target geometry constraint = SCNLookAtConstraint.lookAtConstraintWithTarget_(geometry_node) constraint.gimbalLockEnabled = True camera_node.constraints = [constraint] light_node = SCNNode.node() light_node.setPosition_((30, 0, -30)) light = SCNLight.light() #light.setType_('spot') light.setType_('probe') #light.setType_('directional') light.setCastsShadow_(True) light.setColor_(UIColor.whiteColor().CGColor()) light_node.setLight_(light) root_node.addChildNode_(light_node) main_view.present('fullscreen') demo()
-
@cvp this is what you meant? 😉
from objc_util import * import ui from math import pi import sceneKit as scn @on_main_thread def demo(): global bt,i_bt main_view = ui.View() w, h = ui.get_screen_size() main_view.frame = (0,0,w,h) main_view.name = 'SceneKit IMU' main_view.background_color = 'white' b = ui.ButtonItem() b.title = 'simul bt' i_bt = 0 bt = [ (pi/2,pi/3,pi/4), (pi/3,pi/3,pi/4), (pi/2,pi/5,pi/4), (pi/2,pi/3,pi/8) ] @on_main_thread def b_action(sender): global i_bt,bt # EulerAngles is a SCNVector3 # The order of components in this vector matches the axes of rotation: # Pitch (the x component) is the rotation about the node’s x-axis. # Yaw (the y component) is the rotation about the node’s y-axis. # Roll (the z component) is the rotation about the node’s z-axis. x = bt[i_bt] geometry_node.setEulerAngles(x) i_bt += 1 if i_bt == len(bt): i_bt = 0 b.action = b_action main_view.right_button_items = (b,) scene_view = scn.View(main_view.frame, superView=main_view) scene_view.autoresizingMask = (scn.ViewAutoresizing.FlexibleHeight, scn.ViewAutoresizing.FlexibleRightMargin) scene_view.allowsCameraControl = True scene_view.backgroundColor = 'white' scene = scn.Scene() scene_view.scene = scene root_node = scene.rootNode camera = scn.Camera() camera_node = scn.Node() camera_node.camera = camera camera_node.position = (-30,30,30) root_node.addChildNode(camera_node) geometry = scn.Box(10, 10, 10, 0) geometry_node = scn.Node.nodeWithGeometry(geometry) root_node.addChildNode(geometry_node) Materials = [] colors = ['red','blue','green','yellow','orange','pink'] for i in range(0,6): Material = scn.Material() Material.contents = colors[i] Materials.append(Material) geometry.materials = Materials # Add a constraint to the camera to keep it pointing to the target geometry constraint = scn.LookAtConstraint.lookAtConstraintWithTarget(geometry_node) constraint.gimbalLockEnabled = True camera_node.constraints = [constraint] light_node = scn.Node() light_node.position = (30, 0, -30) light = scn.Light() #light.setType_('spot') light.type = scn.LightTypeProbe #light.setType_('directional') light.castsShadow = True light.color = 'white' light_node.light = light root_node.addChildNode(light_node) main_view.present('fullscreen') demo()
-
@pulbrich it seems, yes 😀
-
Hi guys, thank you soo much for your support. I need some time to go through the code, because I want to understand it. Thank you soo much and don't worry @cvp it is perfectly okay.
-
@ProgrammingGo please try this one, automatic (instead of manual) simulation of Bluetooth values and using continuous animation
from objc_util import * import ctypes import ui from math import pi from ImageColor import getrgb import threading from random import random load_framework('SceneKit') SCNView, SCNScene, SCNBox, SCNNode, SCNMaterial, SCNCamera, SCNLight, SCNAction, SCNLookAtConstraint = map(ObjCClass, ['SCNView', 'SCNScene', 'SCNBox', 'SCNNode', 'SCNMaterial', 'SCNCamera', 'SCNLight', 'SCNAction', 'SCNLookAtConstraint' ]) class my_thread_bt(threading.Thread): def __init__(self, geometry_node): threading.Thread.__init__(self) self.name = 'bt' self.stop = False self.geometry_node = geometry_node def run(self): pitch = 0 yaw = 0 roll = 0 delta_ang = pi/10 SCNTransaction = ObjCClass('SCNTransaction').alloc() while True: # EulerAngles is a SCNVector3 # The order of components in this vector matches the axes of rotation: # Pitch (the x component) is the rotation about the node’s x-axis. # Yaw (the y component) is the rotation about the node’s y-axis. # Roll (the z component) is the rotation about the node’s z-axis. pitch += (random() - 0.5) * delta_ang yaw += (random() - 0.5) * delta_ang roll += (random() - 0.5) * delta_ang # change euler angles but by an animation SCNTransaction.begin() SCNTransaction.setAnimationDuration(0.3) self.geometry_node.setEulerAngles((pitch, yaw, roll)) SCNTransaction.commit() if self.stop: break class MyView(ui.View): ###@on_main_thread def __init__(self,w,h): self.width = w self.height = h self.name = 'SceneKit IMU' self.background_color = 'white' main_view_objc = ObjCInstance(self) scene_view = SCNView.alloc().initWithFrame_options_(((0, 0),(self.width,self.height)), None).autorelease() scene_view.setAutoresizingMask_(18) scene_view.setAllowsCameraControl_(True) main_view_objc.addSubview_(scene_view) scene = SCNScene.scene() scene_view.setScene_(scene) root_node = scene.rootNode() camera = SCNCamera.camera() camera_node = SCNNode.node() camera_node.setCamera(camera) camera_node.setPosition((-30,30,30)) root_node.addChildNode_(camera_node) geometry = SCNBox.boxWithWidth_height_length_chamferRadius_(10, 10, 10, 0) geometry_node = SCNNode.nodeWithGeometry_(geometry) root_node.addChildNode_(geometry_node) Materials = [] colors = ['red','blue','green','yellow','orange','pink'] for i in range(0,6): rgb = getrgb(colors[i]) r,g,b = tuple(c/255.0 for c in rgb) Material = SCNMaterial.material() Material.contents = ObjCClass('UIColor').colorWithRed_green_blue_alpha_(r,g,b,1.0) Materials.append(Material) geometry.setMaterials_(Materials) # Add a constraint to the camera to keep it pointing to the target geometry constraint = SCNLookAtConstraint.lookAtConstraintWithTarget_(geometry_node) constraint.gimbalLockEnabled = True camera_node.constraints = [constraint] light_node = SCNNode.node() light_node.setPosition_((30, 0, -30)) light = SCNLight.light() #light.setType_('spot') light.setType_('probe') #light.setType_('directional') light.setCastsShadow_(True) light.setColor_(UIColor.whiteColor().CGColor()) light_node.setLight_(light) root_node.addChildNode_(light_node) thread_bt = my_thread_bt(geometry_node) thread_bt.start() def will_close(self): for t in threading.enumerate(): if t.name == 'bt': t.stop = True return def main(): w, h = ui.get_screen_size() MainView = MyView(w, h) MainView.present('fullscreen', hide_title_bar=False) # Protect against import if __name__ == '__main__': main()
-
@cvp Hi cvp thank you soo much. I will give a look on that. Thank you for your time. If I will have questions I will write here. I am thinking that it would be better to use quaternions instead of euler angler to avoid gimbal lock. I think there should be a lib for that, right?
-
@ProgrammingGo said:
I think there should be a lib for that
I suppose but I really don't know anything about that.
-
okay, I will give a trial. What for me is unclear is how I can map the sensor values to the graphic. I mean I know that I have a referential coordinate system and based on that my sensor is moving, but it is not clear how to do it.
-
@ProgrammingGo Euler angles are orientation data of your object (here a cube) versus the 3 axes, thus SceneKit geometry node is easy to orientate.
-
@cvp you don’t need a separate thread with all the overhead to update the scene objects. There is the scene renderer delegate (can be the same class instance as your main), which has an 'update' method to take care of exactly these type of tasks.