Trying to make an animation of a double planet orbiting their sun and sharing a common barycentre.
My solution is to use an empty (Empty1) as the Moon/Planet barycentre which follows a large path representing the star orbit. The moon and Planet each have a path that follows Empty1 around the Star.
Here you can see a Constraint example:
These are the loops indicating days and a year:
Of course the large orbit path should also be eccentric but I doubt that the difference in mass here would be noticeable ;-)
I know of two ways of going about this:
Method 1: Using Armatures
This is probably the more flexible and common method, just create an Armature for your solar system, have the root bone be placed in the centre of your sun, then position child bones for where you want things to rotate, in your case, the common barycentre shared by your two planets, after that, go ahead and:
A. parent each planet to the child bone of the barycentre. or
B. assign them each to the vertex group of the bone with an armature modifier.
You can now rotate the bones within the armature to animate orbits.
Method 2: Using Empties
This is probably less common and flexible, but can be easier to understand, for some.
Create an Empty, parent it to your sun, and place it in the centre of your sun. Create a second empty for your barycentre, and parent it to your first Empty. Position this empty on a single axis, whatever distance you desire it to be from the centre of your sun. Now parent both your planets to your second empty, and position them the desired distance apart from the barycentre on a single axis.
You can now rotate the empties to animate orbits.
Driving follow path fixed offset
Edit: code update for 2.8x. images from 2.79x see revision history for 2.7x code.
Setting up the double planets Set cursor location to (0, 0, 0), add a sphere and an orbit circle. Scale to suit. Add a follow path constraint to the sphere, as shown below. The target is the orbit circle object.
The driver can be typed directly into the field, using a
# (hash) as first character, eg
#(frame / 50) % 1 or via the drivers panel, without the hash. The driver expression
(frame / 50) % 1
is basically making the planet travel the path every 50 frames.
Select both the planet and path and duplicate. And now the sneaky tricky bit, scale the orbit dupe by -1 s - 1 This will ensure the dupe planet is always in opposite phase, or diametrically opposed to original planet.
You can now scale the orbits and planets to suit. Add both planets and orbits to a group, as a group instance is going to be used when orbiting the double planet.
Python code setup
In case that's a bit daunting, here is the code to do same, with the default settings set up something like 90 Antiope in the Gallery
Copy the code block below paste into blender text and run script.
import bpy from math import sqrt name = "90 Antiope" planet_size = 0.5 orbit_time = 50 # full orbit frames orbit_size = (5, 5) # elipse if not same planet2_scale = 1 # times bigger than planet orbit2_scale = 1 context = bpy.context scene = context.scene vl = context.view_layer # cursor to zero scene.cursor.location = (0, 0, 0) # make a group for the doubleplants group = bpy.data.collections.new(name) scene.collection.children.link(group) vl.active_layer_collection = vl.layer_collection.children[group.name] # create 2 planets bpy.ops.mesh.primitive_uv_sphere_add(radius=planet_size) planet = context.object bpy.ops.curve.primitive_nurbs_circle_add(radius=1) orbit = context.object x, y = orbit_size orbit.scale.x, orbit.scale.y = x, y bpy.ops.object.transform_apply(scale=True) if x != y: # get focus of eliptical path axis = 0 if x > y else 1 scene.cursor.location[axis] = sqrt(abs(x * x - y * y)) bpy.ops.object.origin_set(type='ORIGIN_CURSOR') orbit.location = (0, 0, 0) # follow path fp = planet.constraints.new('FOLLOW_PATH') fp.target = orbit fp.use_fixed_location = True fp.use_curve_follow = True # drive the offset fcurve = fp.driver_add("offset_factor") fcurve.driver.expression = "(frame / %d) %% 1" % orbit_time planet2 = planet.copy() orbit2 = orbit.copy() # fix target planet2.constraints.target = orbit2 planet2.scale *= planet2_scale # give orbit2 a negative scale (diametric) orbit2.scale *= -1 * orbit2_scale # link them to group for o in [planet2, orbit2]: group.objects.link(o)
Eccentric elliptic orbits (from gallery)
name = "Eccentric Elliptic" planet_size = 0.5 orbit_time = 50 # full orbit frames orbit_size = (3, 5) # ellipse if not same planet2_scale = 1 # times bigger than planet orbit2_scale = 1