Skip to content

Commit e8ffc14

Browse files
authored
Make QuaternionToTwist.RotationAxis configuration property (#12)
* Make QuaternionToTwist.RotationAxis configuration property - Mark its category as such - Rename some of the internal variables in QuaternionToTwist to reflect their true meaning * Forgot to rename one variable in QuaternionToTwist
1 parent bbc9f60 commit e8ffc14

File tree

3 files changed

+26
-18
lines changed

3 files changed

+26
-18
lines changed

OpenEphys.Commutator/Defintions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace OpenEphys.Commutator
2+
{
3+
static class Definitions
4+
{
5+
internal const string ConfigurationCategory = "Configuration";
6+
internal const string AcquisitionCategory = "Acquisition";
7+
}
8+
}

OpenEphys.Commutator/QuaternionToTwist.cs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public class QuaternionToTwist : Combinator<Quaternion, double>
2323
/// in the direction that the tether exits the headstage. Note that negating this vector will result in
2424
/// negating the direction of twisting.
2525
/// </remarks>
26+
[Category(Definitions.ConfigurationCategory)]
2627
[TypeConverter(typeof(NumericRecordConverter))]
2728
[Description("The direction vector specifying the axis around which to calculate the twist.")]
2829
public Vector3 RotationAxis { get; set; } = Vector3.UnitZ;
@@ -35,30 +36,31 @@ public class QuaternionToTwist : Combinator<Quaternion, double>
3536
/// <returns>The sequence of twist values, in units of turns.</returns>
3637
public override IObservable<double> Process(IObservable<Quaternion> source)
3738
{
39+
var rotationAxis = RotationAxis;
40+
3841
return Observable.Defer(() =>
3942
{
40-
double? previousTwist = default;
43+
double? previousAngleAboutAxis = default;
4144
return source.Select(rotation =>
4245
{
4346
// project rotation axis onto the direction axis
44-
var direction = RotationAxis;
45-
var rotationAxis = new Vector3(rotation.X, rotation.Y, rotation.Z);
46-
var dotProduct = Vector3.Dot(rotationAxis, direction);
47-
var projection = dotProduct / Vector3.Dot(direction, direction) * direction;
48-
var twist = new Quaternion(projection, rotation.W);
49-
twist = Quaternion.Normalize(twist);
47+
var vectorPart = new Vector3(rotation.X, rotation.Y, rotation.Z);
48+
var dotProduct = Vector3.Dot(vectorPart, rotationAxis);
49+
var projection = dotProduct / Vector3.Dot(rotationAxis, rotationAxis) * rotationAxis;
50+
var rotationAboutAxis = new Quaternion(projection, rotation.W);
51+
rotationAboutAxis = Quaternion.Normalize(rotationAboutAxis);
5052
if (dotProduct < 0) // account for angle-axis flipping
5153
{
52-
twist = -twist;
54+
rotationAboutAxis = -rotationAboutAxis;
5355
}
5456

5557
// normalize twist feedback in units of turns
56-
var twistAngle = 2 * Math.Acos(twist.W);
57-
var feedback = previousTwist.HasValue
58-
? (twistAngle - previousTwist.GetValueOrDefault() + 3 * Math.PI) % (2 * Math.PI) - Math.PI
58+
var angleAboutAxis = 2 * Math.Acos(rotationAboutAxis.W);
59+
var twist = previousAngleAboutAxis.HasValue
60+
? (angleAboutAxis - previousAngleAboutAxis.GetValueOrDefault() + 3 * Math.PI) % (2 * Math.PI) - Math.PI
5961
: 0;
60-
previousTwist = twistAngle;
61-
return -feedback / (2 * Math.PI);
62+
previousAngleAboutAxis = angleAboutAxis;
63+
return -twist / (2 * Math.PI);
6264
});
6365
});
6466
}

OpenEphys.Commutator/SerialCommutator.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,14 @@ namespace OpenEphys.Commutator
1414
[Description("Controls an Open Ephys commutator using a serial port.")]
1515
public class SerialCommutator : Combinator<double, string>
1616
{
17-
const string ConfigurationCategory = "Configuration";
18-
const string AcquisitionCategory = "Acquisition";
1917

2018
readonly BehaviorSubject<bool> enabled = new(true);
2119
readonly BehaviorSubject<bool> led = new(true);
2220

2321
/// <summary>
2422
/// Gets or sets the name of the serial port.
2523
/// </summary>
26-
[Category(ConfigurationCategory)]
24+
[Category(Definitions.ConfigurationCategory)]
2725
[TypeConverter(typeof(PortNameConverter))]
2826
[Description("The name of the serial port.")]
2927
public string PortName { get; set; }
@@ -35,7 +33,7 @@ public class SerialCommutator : Combinator<double, string>
3533
/// If true, the commutator will activate the motor and respond to turn commands. If false,
3634
/// the motor driver will be deactivated and motion commands will be ignored.
3735
/// </remarks>
38-
[Category(AcquisitionCategory)]
36+
[Category(Definitions.AcquisitionCategory)]
3937
[Description("If true, the commutator will be enabled. If false, it will disable the motor and ignore motion commands.")]
4038
public bool Enable
4139
{
@@ -50,7 +48,7 @@ public bool Enable
5048
/// If true, the commutator indication LED turn on. If false, the indication LED will turn
5149
/// off.
5250
/// </remarks>
53-
[Category(AcquisitionCategory)]
51+
[Category(Definitions.AcquisitionCategory)]
5452
[Description("If true, the commutator indication LED turn on. If false, the indication LED will turn off.")]
5553
public bool EnableLed
5654
{

0 commit comments

Comments
 (0)