TransformInterpolator::TransformInterpolator(const MATRIX &start, const MATRIX &end, unsigned int totalSteps)
: d(new TransformInterpolatorPrivate)
{
	d->totalSteps = totalSteps;
	d->currentStep = 0;
	d->startTransform = start;
    MatrixToQuaternion(d->startRotation, start);	
	setEnd(end);
}
Exemplo n.º 2
0
bool DexMouseTracker::GetCurrentMarkerFrame( CodaFrame &frame ) {


	POINT mouse_position;
	GetCursorPos( &mouse_position );
	RECT rect;
	GetWindowRect( GetDesktopWindow(), &rect );

	Vector3		position, rotated;
	Vector3	x_dir, y_span, z_span;
	Vector3		x_displacement, y_displacement, z_displacement;

	double		x, y, z;

	Quaternion	Ry, Rz, Q, nominalQ, midQ;
	Matrix3x3	xform = {{-1.0, 0.0, 0.0},{0.0, 0.0, 1.0},{0.0, 1.0, 0.0}};

	int mrk, id;
	
	// Just set the target frame markers at their nominal fixed positions.
	for ( mrk = 0; mrk < nFrameMarkers; mrk++ ) {
		id = FrameMarkerID[mrk];
		CopyVector( frame.marker[id].position, TargetFrameBody[mrk] );
	}

	// Shift the vertical bar markers to simulate being in the left position.
	if ( IsDlgButtonChecked( dlg, IDC_LEFT ) ) {
		frame.marker[DEX_NEGATIVE_BAR_MARKER].position[X] += 300.0;
		frame.marker[DEX_POSITIVE_BAR_MARKER].position[X] += 300.0;
	}

	// Transform the marker positions of the target box and frame according 
	//  to whether the system was upright or supine when it was aligned and
	//  according to whether the system is currently installed in the upright
	//  or supine configuration.
	if ( ( IsDlgButtonChecked( dlg, IDC_SUPINE ) && TRACKER_ALIGNED_SUPINE  != SendDlgItemMessage( dlg, IDC_ALIGNMENT, CB_GETCURSEL, 0, 0 ) ) ||
		 ( IsDlgButtonChecked( dlg, IDC_SEATED ) && TRACKER_ALIGNED_UPRIGHT != SendDlgItemMessage( dlg, IDC_ALIGNMENT, CB_GETCURSEL, 0, 0 ) ) )	{	
		 for ( mrk = 0; mrk < nFrameMarkers; mrk++ ) {

			id = FrameMarkerID[mrk];
			position[X] = - frame.marker[id].position[X];
			position[Z] =   frame.marker[id].position[Y];
			position[Y] =   frame.marker[id].position[Z];

			CopyVector( frame.marker[id].position, position );
		}
		MatrixToQuaternion( nominalQ, xform );
	}
	else CopyQuaternion( nominalQ, nullQuaternion );

	// Now set the visibility flag as a funciton of the GUI.
	if ( IsDlgButtonChecked( dlg, IDC_BAR_OCCLUDED ) ) {
		frame.marker[DEX_NEGATIVE_BAR_MARKER].visibility = false;
		frame.marker[DEX_POSITIVE_BAR_MARKER].visibility = false;
	}
	else {
		frame.marker[DEX_NEGATIVE_BAR_MARKER].visibility = true;
		frame.marker[DEX_POSITIVE_BAR_MARKER].visibility = true;
	}
	if ( IsDlgButtonChecked( dlg, IDC_BOX_OCCLUDED ) ) {
		frame.marker[DEX_NEGATIVE_BOX_MARKER].visibility = false;
		frame.marker[DEX_POSITIVE_BOX_MARKER].visibility = false;
	}
	else {
		frame.marker[DEX_NEGATIVE_BOX_MARKER].visibility = true;
		frame.marker[DEX_POSITIVE_BOX_MARKER].visibility = true;
	}

	// Map mouse coordinates to world coordinates. The factors used here are empirical.
	
	y =  (double) ( mouse_position.y - rect.top ) / (double) ( rect.bottom - rect.top );
	z =  (double) (mouse_position.x - rect.right) / (double) ( rect.left - rect.right );
	x = 0.0;

	// By default, the orientation of the manipulandum is the nominal orientation.

	CopyQuaternion( Q, nominalQ );

	// Simulate wobbly movements of the manipulandum. This has not really been tested.

	if ( IsDlgButtonChecked( dlg, IDC_CODA_WOBBLY ) ) {
		// We will make the manipulandum rotate in a strange way as a function of the distance from 0.
		// This is just so that we can test the routines that compute the manipulandum position and orientation.
		double theta = y * 45.0;
		double gamma = - z * 45.0;
		SetQuaterniond( Ry, theta, iVector );
		SetQuaterniond( Rz, gamma, jVector );
		MultiplyQuaternions( midQ, Rz, nominalQ );
		MultiplyQuaternions( Q, Ry, midQ );
		// Make the movement a little bit in X as well so that we test the routines in 3D.
		x = 0.0 + 5.0 * sin( y / 80.0);
	}

	// Map screen position of the mouse pointer to 3D position of the wrist and manipulandum.
	// Top of the screen corresponds to the bottom of the bar and vice versa. It's inverted to protect the right hand rule.
	// Right of the screen correponds to the nearest horizontal target and left corresponds to the farthest.
	// The X position is set to be just to the right of the box.

	SubtractVectors( y_span, frame.marker[DEX_POSITIVE_BAR_MARKER].position, frame.marker[DEX_NEGATIVE_BAR_MARKER].position );
	SubtractVectors( x_dir, frame.marker[DEX_POSITIVE_BOX_MARKER].position, frame.marker[DEX_NEGATIVE_BOX_MARKER].position );
	NormalizeVector( x_dir );
	ComputeCrossProduct( z_span, x_dir, y_span );
	 
	ScaleVector( y_displacement, y_span, y );
	ScaleVector( z_displacement, z_span, z );
	ScaleVector( x_displacement, x_dir, x );

	// Reference position is the bottom target on the vertical target bar.
	CopyVector( position, frame.marker[DEX_NEGATIVE_BAR_MARKER].position );
	// Place the manipulandum to the right of the box, even if the target bar is in the left position.
	position[X] = frame.marker[DEX_NEGATIVE_BOX_MARKER].position[X];
	// Shift the position in X if the is any wobble to it.
	AddVectors( position, position, x_displacement );
	// Shift the position in Y and Z according to the displacements computed from the mouse position.
	AddVectors( position, position, y_displacement );
	AddVectors( position, position, z_displacement );

	frame.time = DexTimerElapsedTime( acquisitionTimer );

	// Displace the manipulandum with the mouse and make it rotate.
	for ( mrk = 0; mrk < nManipulandumMarkers; mrk++ ) {
		id = ManipulandumMarkerID[mrk];
		RotateVector( rotated, Q, ManipulandumBody[mrk] );
		AddVectors( frame.marker[id].position, position, rotated );
		frame.marker[id].visibility = true;
	}

	// Displace the wrist with the mouse, but don't rotate it.
	for ( mrk = 0; mrk < nWristMarkers; mrk++ ) {
		id = WristMarkerID[mrk];
		AddVectors( frame.marker[id].position, position, WristBody[mrk] );
		frame.marker[id].visibility = true;
	}

	// Output the position and orientation used to compute the simulated
	// marker positions. This is for testing only.
	fprintf( fp, "%f\t%f\t%f\t%f\t%f\t%f\t%f\t%f\n",
		frame.time, 
		position[X], position[Y], position[Z],
		Q[X], Q[Y], Q[Z], Q[M] );

	return( true );

}
void TransformInterpolator::setEnd(const MATRIX &end)
{
	d->endTransform = end;
    MatrixToQuaternion(d->endRotation, end);	
}