Secondary/follow animation using expression

Can any point me down the road:

I want to apply and offset position information (translate) from previous frames of one object, to another.

Here's one that I came up with, basically I made it to transfer animation keys from one control to another, provided they have the same attributes, in the same order, and that their names are the same, except for one being left and one right. Example, the names be: "L_Foot_CNTRL" and "R_Foot_CNTRL", as there is a procedure to switch the names from right to left, or left to right. It doesn't offset them though, but that's easy to do with the dope sheet after running the script. Just highlight and offset what you want. So, this should be a decent starting point for you maybe:

// Procedure subName is used to virtually change the name of an OBJluence object effectively, from
// "left" to "right". A number of left/right labelling methods are taken into consideration.

proc string flipName(string $OBJ)
{
string $replacement = $OBJ;

if (gmatch $OBJ "L\_*")
$replacement = substitute "L\_" $OBJ "R\_";
else if (gmatch $OBJ "l\_*")
$replacement = substitute "l\_" $OBJ "r\_";
else if (gmatch $OBJ "left*")
$replacement = substitute "left" $OBJ "right";
else if (gmatch $OBJ "Left*")
$replacement = substitute "Left" $OBJ "Right";
else if (gmatch $OBJ "lt*")
$replacement = substitute "lt" $OBJ "lt";
else if (gmatch $OBJ "Lt*")
$replacement = substitute "Lt" $OBJ "Rt";

else if (gmatch $OBJ "R\_*")
$replacement = substitute "R\_" $OBJ "L\_";
else if (gmatch $OBJ "l\_*")
$replacement = substitute "l\_" $OBJ "r\_";
else if (gmatch $OBJ "right*")
$replacement = substitute "right" $OBJ "left";
else if (gmatch $OBJ "Right*")
$replacement = substitute "Right" $OBJ "Left";
else if (gmatch $OBJ "rt*")
$replacement = substitute "rt" $OBJ "lt";
else if (gmatch $OBJ "Rt*")
$replacement = substitute "Rt" $OBJ "Lt";

return($replacement);

}

// Procedure copyKeys copys the keyed attributes from one object to another, provided
// both objects follow the naming conventions set up by the flipName script.
proc copyKeys()
{

// Get selected and opposite of selected's name:
string $selected[] = ls -sl;
string $oppSelected = flipName($selected[0]);

string $selAttr[] = listAttr -k $selected[0];
int $selAttrSize = size $selAttr;
string $oppSelAttr[] = listAttr -k $oppSelected;
int $oppSelAttrSize = size $oppSelAttr;

// Check attributes of both objects for a match:
if($oppSelAttrSize != $selAttrSize)
error "Objects have a different number of attributes";
int $x;
for($x=0; $x < $oppSelAttrSize; $x++)
{
if($oppSelAttr[$x] != $selAttr[$x])
error "Incoming list of attributes don't match list of outgoing attributes.";
}

// Copy Keys:
int $currTime = currentTime -query;
int $j;
for($j=0; $j < $oppSelAttrSize; $j++)
{
float $keys[] = keyframe -q -tc ($selected[0] + "." + $selAttr[$j]);
int $keySize = size $keys;
int $k;
for($k=0; $k < $keySize; $k++)
{
currentTime -update false $keys[$k];
float $value[] = keyframe -query -eval ($selected[0] + "." + $selAttr[$j]);
setKeyframe -time $keys[$k] -value $value[0] ($oppSelected + "." + $oppSelAttr[$j]);
}
}
currentTime $currTime;

}

If you need to copy just position there is more flexible solution:
Write expression that will store your main objects's (pCube1 here) position per frame:

global vector $pos[];
float $x = pCube1.translateX;
float $y = pCube1.translateY;
float $z = pCube1.translateZ;
$pos[ (int) frame ] = <>;

Then, for object(s) that should follow (pCube2 here) issue the expression:

global vector $pos[];
int $frameDelay = 1;
vector $p = $pos[ (int) ( frame - $frameDelay ) ];
pCube2.translateX = $p.x;
pCube2.translateY = $p.y;
pCube2.translateZ = $p.z;

Ah yeah, good point. Mine was to copy keys from all attributes, instead of just the position. thumbs up

Or if you want to get wicked just copy the curve nodes, reconnect them to new object and feed them time from custom time node which offsets the default time thru expression. Like this:

// rough and dirty version
global proc copyKeysOffset( string $sourceObj, string $targetObj, int $timeOffset ){

string $curves[] = `listConnections -source true -type animCurve $sourceObj`;
string $time = `createNode time`;
addAttr -at long -ln "offset" $time;
setAttr ( $time + ".offset" ) $timeOffset;
expression -s ( $time + ".outTime = time1.outTime + " + $time + ".offset" );
string $c;
for( $c in $curves ){
	string $dest[] = `connectionInfo -destinationFromSource  ( $c + ".output" )`;
	string $newdest = substitute( $sourceObj, $dest[ 0 ], $targetObj );
	string $newcurve[] = `duplicate $c`;
	connectAttr ( $time + ".outTime" )( $newcurve[ 0 ] + ".input" );
	connectAttr ( $newcurve[ 0 ] + ".output" ) $newdest;
}

}

Note that offset is editable after you run the script thru "offset" attribute that is added to time node.