Here's a script I came up with that does this (apologies if this has already been done). Given an axis, an angle, a duration, and an initial rotation, this script will smoothly transition back and forth between two rotations each time the object is touched. To see a demo, just put this script in a prim and poke at it a few times

CODE
// Lex Neva
//
// Smooth Rotation
// This script demonstrates how to use llTargetOmega() to smoothly transition between two
// rotations. Occasionally the object will under- or over-rotate, but generally, the effect
// is to rotate smoothly between a starting and ending rotation.
// how long to take to rotate
float ROT_TIME=1.0;
// axis to rotate around
vector ROT_AXIS=<0.0,0,1>;
// angle in radians to rotate
float ROT_ANGLE=PI_BY_TWO;
// initial rotation
rotation ROT_START=ZERO_ROTATION;
default
{
state_entry() {
// this needs to be a unit vector
ROT_AXIS = llVecNorm(ROT_AXIS);
// get the process started
llSetRot(ROT_START * llAxisAngle2Rot(ROT_AXIS, ROT_ANGLE));
state unflipped;
}
}
state unflipped {
state_entry()
{
llTargetOmega(ROT_AXIS,-ROT_ANGLE/ROT_TIME,1);
llSleep(ROT_TIME);
llTargetOmega(ROT_AXIS,0,1);
llSetRot(ROT_START);
}
touch_start(integer total_number)
{
state flipped;
}
}
state flipped {
state_entry()
{
llTargetOmega(ROT_AXIS,ROT_ANGLE/ROT_TIME,1);
llSleep(ROT_TIME);
llTargetOmega(ROT_AXIS,0,1);
llSetRot(ROT_START * llAxisAngle2Rot(ROT_AXIS, ROT_ANGLE));
}
touch_start(integer total_number)
{
state unflipped;
}
}