Controlling the speed of movement along a path

I have a document with a list of coordinates of an object, a ship in this case, each coordinate also has the time when it was logged. I’ve made a script which can import all the coordinates and make my object follow the path. However I’m stumped as how to implement the speed at which the object is traveling. From the data points I can extract the speed simply by dividing the distance between subsequent points over time, but how do I get this into Blender?

To travel along the path you have a range of 0.0-1.0 for the Offset value when Fixed Position is enabled. So a percentage. Figure out where you need to be, percentage wise, along the path at what time. Then set keyframes on the Offset value for the path constraint.

So if you need to be at 50% along the path at 3 seconds you would factor in your FPS (lets assume 30) and insert an Offset keyframe at frame #90 with a value of 0.5.


def returnFollowPathConstraint(passedName, passedObject, passedTarget, passedValue = 1.0):
    # Create or fetch a follow path constraint and return it.
    try:
        # See if our constraint exists.
        con_name = passedName
        con_name = con_name[:MAX_NAME_SIZE]
        my_constraint = fetchIfConstraint(con_name, passedObject)
        if my_constraint == None:
            # Create a new constraint.
            my_constraint = passedObject.constraints.new("FOLLOW_PATH")
            my_constraint.name = con_name
        my_constraint.use_curve_follow = True
        my_constraint.up_axis = 'UP_Z'   
        my_constraint.forward_axis = 'FORWARD_X'
        my_constraint.target = passedTarget
        my_constraint.influence = passedValue
        my_constraint.use_fixed_location = True 
        my_constraint.offset_factor = 0.0   # Animate this value to move along the path.
        result = my_constraint
    except:
        print("returnFollowPathConstraint: Problem assigning constraint [%s]." % passedName)
        result = None
    return result

# Assign a follow path constraint to this temp object.
cn = returnFollowPathConstraint(target_constraint_name, temp_ob, ob_particle_path)
if cn != None:
    cn.up_axis = 'UP_Y'   
    #cn.forward_axis =  'FORWARD_Z'
    
    if KEYFRAME_EMITTER == True:
        # Insert a linear keyframe to animate this object along the path.
        keyInterp = context.user_preferences.edit.keyframe_new_interpolation_type
        context.user_preferences.edit.keyframe_new_interpolation_type ='LINEAR'
        cn.offset_factor = my_value
        cn.keyframe_insert(data_path='offset_factor', frame=(my_frame))
        context.user_preferences.edit.keyframe_new_interpolation_type = keyInterp


Thanks. Sadly that doesn’t really solve my problem as far as I can see though. This is because the path is made up of points with a fixed time in between them. So the distance between each point should be traveled during the same time, and the speed is therefore determined by the distances between points. So I don’t know exactly how far along the path in % the object should be at time x.

I’ve partly solved it in a different manner by importing two f curves, one for x and one for y. Each point along each f-curve has the same number of frames between them, so the speed is determined by the distances between the points. Now my problem is that I need to figure out the rotation and the curves aren’t as smooth as the path I had previously.

Importing the f-curves for x and y point by point seems to work reasonably well, but I have a problem with the rotation. I calculate the rotation by using the python function math.atan2 between the dx and dy of two subsequent points and then use the Z Euler rotation in Blender. This gives the correct angle of the object along the path, however the interpolation in the graph editor gives my object a spin when the angle crosses the horizontal due to angle flipping positive to negative (see image). Any idea how to solve this?


Can anyone help with the rotation? Maybe I need to use quaternions, but I don’t know how to enable them in python. Now I’m using the following line to control rotation, but it gives the problem illustrated in my previous post.

bpy.context.object.animation_data.action.fcurves.new(data_path=“rotation_euler”, index=2)

Thanks again Atom, I looked at your idea again because I couldn’t fix my rotation issues, and found a way to implement the offset factor. I simply calculated the distance traveled between each subsequent point, and then calculated the offset factor by dividing the cumulative distance at time t by the total distance traveled at the end time.