1

I am trying to add add keyframes to an object from values in a csv file using python. It successfully reads the file and puts it into a list. However, it just gives me this error when adding the keyframes.

AttributeError: Writing to ID classes in this context is not allowed: Camera, Object datablock, error setting Object.<UNKNOWN>

This is the code that i have so far:

def draw(self, context):
    results = []
    layout = self.layout

    obj = context.object

    with open('record.txt', newline='') as inputfile:
        for row in csv.reader(inputfile):
            results.append(row)
    line = 0
    for x in results:
        line += 1
        if line > 2:
            currentFrame = str(x)
            xRot, yRot, zRot,_,_ = currentFrame.split(';')
            xRot = xRot.replace("['", "")
            print(xRot + " " + yRot + " " + zRot)
            obj.rotation_euler[0] += float(xRot)
            obj.keyframe_insert(data_path="rotation_euler", frame= float(line), index=0)
            obj.rotation_euler[1] += float(yRot)
            obj.keyframe_insert(data_path="rotation_euler", frame= float(line), index=1)
            obj.rotation_euler[2] += float(zRot)
            obj.keyframe_insert(data_path="rotation_euler", frame= float(line), index=2)                 

I would appreciate suggestions in how to solve this issue.

geooot
  • 223
  • 1
  • 4
  • 1
    Can you post a sample line from the csv file? – Todd McIntosh Jul 12 '15 at 20:33
  • Also see : http://blender.stackexchange.com/questions/17919/importing-trajectories-to-create-an-animation?rq=1 it's related – zeffii Jul 13 '15 at 08:52
  • @geooot i'm pretty sure the code as you wrote it - for adding keyframes - doesn't work as intended, a sample line (or several lines) of the record.txt file would let us give working solutions. – zeffii Jul 13 '15 at 09:06
  • @zeffii Here is a line of the csv file http://pastebin.com/pygPSnRA – geooot Jul 13 '15 at 15:44
  • @geooot I've adjusted my answer. care to share a file I could test it on - seems like fun. – zeffii Jul 14 '15 at 15:34
  • those gyro components might be outputting on a range of 0..360, but blender rotation_euler expects the range of 0..2*PI – zeffii Jul 14 '15 at 16:50
  • @zeffii i converted the gyro variables using the standard math.radians() function. However the gyro data is sensitive and the camera still spins out of control. It was stabilized once i scaled the f-curves down. but it still works. :) – geooot Jul 14 '15 at 17:08
  • I just noticed, it's degrees per second, given in ms - meaning you might be getting many more updates than your frame-rate (24 hz?) ..so yeah, some smoothing and quantization may be in order. – zeffii Jul 14 '15 at 17:56

1 Answers1

1

The draw function is for UI only (defining layout and visibility of properties, sliders etc). It's called multiple times per second, sometimes 20 or more times, as you move your mouse around

You can't change bpy.data (including keyframes) from inside draw, it is blocked by design. You probably don't want to repeatedly execute that code anyway. A standard approach is to Run it from Text Editor with or without an enclosing function.

If this represents the first and second line of the the dataset, and the next lines are all formatted like line 2.

dataset.txt

GYROSCOPE X (°/s);GYROSCOPE Y (°/s);GYROSCOPE Z (°/s);Time since start in ms ;YYYY-MO-DD HH-MI-SS_SSS
9.08;-1.04;-9.51;20;2015-07-03 14:17:34:206

code

import csv
import bpy

def some_function(fp):

    obj = bpy.data.objects['Camera']

    results = []
    with open(fp, newline='') as inputfile:
        row_gen = csv.reader(inputfile)
        next(row_gen) # skip first line.

        for row in row_gen:
            results.append(row[0].split(';'))

    # start making frames at frame 1
    for idx, frame_data in enumerate(results, 1):
        xRot, yRot, zRot = frame_data[:3]
        print(xRot, yRot, zRot)
        obj.rotation_euler[0] += float(xRot)
        obj.rotation_euler[1] += float(yRot)
        obj.rotation_euler[2] += float(zRot)
        obj.keyframe_insert(data_path="rotation_euler", frame=idx, index=-1)

some_function(fp='/home/zeffii/Desktop/zen/dataset.txt')

The -1 at the end indicates that the keyframe is to be added after the other existing keyframes.


For info about paths; whether to use back or forward slashes, see:

https://blender.stackexchange.com/tags/path/info

Adding this for completeness, because it differs across Operating Systems.

zeffii
  • 39,634
  • 9
  • 103
  • 186