コード例 #1
0
        /// <summary>
        /// Creates the recording timepoint from a single line of a CSV file.
        /// </summary>
        /// <param name="line">The CSV file line</param>
        internal RecordingTimepoint(String line)
        {
            String[] param;

            angles                   = new RotationAngles();
            directionOfBalance       = new RotationAngles();
            movingDirectionOfBalance = new RotationAngles();

            param = line.Split(',');

            if (param.Length < 12)
            {
                throw new IOException("Incorrect number of values in recording timepoint string.");
            }

            try {
                Double.TryParse(param[0], out time);
                Int32.TryParse(param[1], out trialNumber);
                Int32.TryParse(param[2], out trialPhase);
                Double.TryParse(param[3], out directionOfBalance.roll);
                Double.TryParse(param[4], out directionOfBalance.pitch);
                Double.TryParse(param[5], out directionOfBalance.yaw);
                Double.TryParse(param[6], out movingDirectionOfBalance.roll);
                Double.TryParse(param[7], out movingDirectionOfBalance.pitch);
                Double.TryParse(param[8], out movingDirectionOfBalance.yaw);
                Double.TryParse(param[9], out angles.roll);
                Double.TryParse(param[10], out angles.pitch);
                Double.TryParse(param[11], out angles.yaw);
            } catch (Exception) {
                throw new IOException("Parsing failed for recording timepoint string.");
            }
        }
コード例 #2
0
        internal bool SetNoiseProfile()
        {
            RotationAngles angles;
            StreamReader   reader;

            String[] fragments;
            String   line;

            logger.Debug("Enter: SetNoiseProfile()");

            if ((noiseProfile == "") || (noiseProfile == null) || (noiseProfile.ToUpper() == "NULL") || (noiseProfile.ToUpper() == "NONE"))
            {
                return(true);
            }

            if (!Directory.Exists(ConfigurationManager.AppSettings["NoiseDirectory"]))
            {
                logger.Error("[Trial] Could not load noise profile '" + noiseProfile + "' because the noise directory does not exist: " + ConfigurationManager.AppSettings["NoiseDirectory"]);
                return(false);
            }

            try
            {
                reader = new StreamReader(ConfigurationManager.AppSettings["NoiseDirectory"] + "\\" + noiseProfile);

                noisePoints = new List <RotationAngles>();

                while ((line = reader.ReadLine()) != null)
                {
                    // Ignore comment lines
                    if (line.StartsWith(";"))
                    {
                        continue;
                    }

                    // Parse the line for a set of noise values

                    fragments = line.Split(',');

                    angles       = new RotationAngles();
                    angles.roll  = Double.Parse(fragments[0]) * noiseAmplitude;
                    angles.pitch = Double.Parse(fragments[1]) * noiseAmplitude;
                    angles.yaw   = Double.Parse(fragments[2]) * noiseAmplitude;

                    noisePoints.Add(angles);
                }
            }
            catch (Exception e)
            {
                logger.Error("[Trial] Could not load noise profile '" + ConfigurationManager.AppSettings["NoiseDirectory"] + "\\" + noiseProfile + "'. Reason: " + e.Message);
                return(false);
            }

            return(true);
        }
コード例 #3
0
ファイル: RealTime.xaml.cs プロジェクト: llenroc/NETConf2017
        public RealTime()
        {
            InitializeComponent();

            angles = new RotationAngles(-1, -1, -1);
            angles.gyroXNoiseCorrect = -4.84 * .02;
            angles.gyroYNoiseCorrect = 2.35 * .02;
            angles.gyroZNoiseCorrect = -1.03 * .02;

            listView.ItemsSource = output;

            StartAccelAndGyroSensors();

            Close.Clicked += Close_Clicked;
        }
コード例 #4
0
        /// <summary>
        /// Creates the function timepoint from a single line of a CSV file.
        /// </summary>
        /// <param name="line">The CSV file line</param>
        internal FunctionTimepoint(String line)
        {
            String[] param;

            input = new RotationAngles();

            param = line.Split(',');

            if (param.Length != 4)
            {
                throw new IOException("Incorrect number of values in function timepoint input string.");
            }

            try {
                Double.TryParse(param[0], out time);
                Double.TryParse(param[1], out input.yaw);
                Double.TryParse(param[2], out input.pitch);
                Double.TryParse(param[3], out input.roll);
            } catch (Exception) {
                throw new IOException("Parsing failed for function timepoint input string.");
            }
        }
コード例 #5
0
        /// <summary>
        /// Calculates the next motion, based on the current system state.
        /// </summary>
        /// <param name="trial">Trial parameters</param>
        /// <param name="currentState">Position, velocity, etc of the system</param>
        /// <param name="originalControlInput">Current joystick input</param>
        /// <param name="noise">Noise values to add to position before calculations</param>
        /// <param name="dt">Time elapsed since last calculation</param>
        /// <returns>The new position, velocity, etc of the system</returns>
        public static MotionCommand CalculateDynamics(Trial trial, MotionCommand currentState, ControlInput originalControlInput,
                                                      RotationAngles noise, double dt)
        {
            AxisMotionState axis1State;
            AxisMotionState axis2State;
            ControlInput    controlInput;
            MotionCommand   newMotionCommand;

            // Convert to structs used in dynamics code
            axis1State = new AxisMotionState(currentState.outerPosition, currentState.outerVelocity, 0);
            axis2State = new AxisMotionState(currentState.innerPosition, currentState.innerVelocity, 0);

            if (originalControlInput.blanked)
            {
                controlInput = new ControlInput(0, 0, false, false);
            }
            else
            {
                controlInput = new ControlInput(originalControlInput.x, originalControlInput.y, false, false);
            }

            // Handle joystick input + noise

            // figure out what the noise for each axis is
            double axis1Noise = noise.pitch;
            double axis2Noise = (Hulk.InnerAxis == Hulk.Axis.Roll) ? noise.roll : noise.yaw;

            // figure out how joystick input should affect each axis
            double axis1Delta = controlInput.y * trial.JoystickGain;
            double axis2Delta = controlInput.x * trial.JoystickGain;

            // uncomment for debugging purpose
            // System.Diagnostics.Debug.Write("Axis 1 noise: " + axis1Noise + ", joystick delta: " + axis1Delta + ", total delta: " + (axis1Delta + axis1Noise));
            // System.Diagnostics.Debug.WriteLine(", Axis 2 noise: " + axis2Noise + ", joystick delta: " + axis2Delta + ", total delta: " + (axis2Delta + axis2Noise));

            // Apply joystick input + noise
            switch (controlMode)
            {
            case ControlMode.Velocity:
                axis1State.velocity -= axis1Delta + axis1Noise;
                axis2State.velocity -= axis2Delta + axis2Noise;
                break;

            case ControlMode.Position:
                axis1State.position -= axis1Delta + axis1Noise;
                axis2State.position -= axis2Delta + axis2Noise;
                break;
            }

            // Integrate to obtain new motion
            Integrate(trial, axis1State, dt, ComputeAcceleration, controlInput);
            Integrate(trial, axis2State, dt, ComputeAcceleration, controlInput);

            // Upper limit on velocity for safety
            axis1State.velocity = Math.Min(axis1State.velocity, trial.MaxVelocity);
            axis1State.velocity = Math.Max(axis1State.velocity, -trial.MaxVelocity);
            axis2State.velocity = Math.Min(axis2State.velocity, trial.MaxVelocity);
            axis2State.velocity = Math.Max(axis2State.velocity, -trial.MaxVelocity);

            // Lower limit on velocity to match precision of motion controller
            int signInner = (Hulk.InnerAxis == Hulk.Axis.Roll) ? Math.Sign(axis1State.position - trial.MovingDirectionOfBalance.roll) : Math.Sign(axis1State.position - trial.MovingDirectionOfBalance.yaw);
            int signOuter = Math.Sign(axis2State.position - trial.MovingDirectionOfBalance.pitch);

            if (Math.Abs(axis1State.velocity) < 0.5)
            {
                axis1State.velocity = 0.5 * signInner;
            }
            if (Math.Abs(axis2State.velocity) < 0.5)
            {
                axis2State.velocity = 0.5 * signOuter;
            }

            // old code, in case we need to revert back
            //if (axis1State.velocity > 0.0) {
            //    axis1State.velocity = Math.Max(axis1State.velocity, 0.5);
            //} else {
            //    axis1State.velocity = Math.Min(axis1State.velocity, -0.5);
            //}
            //if (axis2State.velocity > 0.0) {
            //    axis2State.velocity = Math.Max(axis2State.velocity, 0.5);
            //} else {
            //    axis2State.velocity = Math.Min(axis2State.velocity, -0.5);
            //}

            // Convert back to structs used in rest of code
            newMotionCommand = new MotionCommand {
                innerPosition     = axis2State.position,
                innerVelocity     = axis2State.velocity,
                innerAcceleration = Math.Abs(axis2State.acceleration),
                outerPosition     = axis1State.position,
                outerVelocity     = axis1State.velocity,
                outerAcceleration = Math.Abs(axis1State.acceleration)
            };

            return(newMotionCommand);
        }
コード例 #6
0
    void LateUpdate()
    {
        // Early out if we don't have a target
        if (!target)
        {
            return;
        }

        var rigidbody = target.GetComponent <Rigidbody>();

        if (rigidbody)
        {
            distance = Mathf.Lerp(distance, Mathf.Lerp(minDistance, maxDistance, Mathf.Clamp01((rigidbody.velocity.magnitude - minSpeed) / (maxSpeed - minSpeed))), Time.deltaTime);
        }

        float currentRotationAngle = transform.eulerAngles.y;
        float currentHeight        = transform.position.y;

        // Calculate the current rotation angles
        float wantedHeight = target.position.y + height;

        RaycastHit hit;
        int        i = 0;
        float      wantedRotationAngle = RotationAngles.FirstOrDefault(
            angle =>
        {
            var pos       = PositionFromRotationAngle(angle, wantedHeight);
            var direction = (target.position - pos).normalized;
            pos          -= direction * 2;
            //Debug.DrawRay(pos - direction * 5, direction, Color.green);

            if (Physics.Raycast(pos, direction, out hit))
            {
                //Debug.LogFormat("{0} ({1})", hit.collider.name, i++);
                return(hit.collider.transform.IsChildOf(target));
            }
            return(false);
        }
            );

        if (wantedRotationAngle == default(float))
        {
            wantedRotationAngle = RotationAngles.First();
        }
        //Debug.Log(wantedRotationAngle);

        // Damp the rotation around the y-axis
        currentRotationAngle = Mathf.LerpAngle(currentRotationAngle,
                                               wantedRotationAngle,
                                               rotationDamping * Time.deltaTime);
        // Damp the height
        currentHeight = Mathf.Lerp(currentHeight,
                                   wantedHeight,
                                   heightDamping * Time.deltaTime);

        // Convert the angle into a rotation around the y-axis
        Quaternion currentRotation = Quaternion.Euler(0, currentRotationAngle, 0);

        // Set the position of the camera on the x-z plane to:
        // distance meters behind the target
        transform.position  = target.position;
        transform.position -= currentRotation * Vector3.forward * distance;

        // Set the height of the camera
        transform.position = new Vector3(transform.position.x,
                                         currentHeight,
                                         transform.position.z);
        // Always look at the target
        transform.LookAt(target);
    }
コード例 #7
0
        /// <summary>
        /// Logs the data from the round of calculations.
        /// </summary>
        /// <param name="time">Seconds since start of trial</param>
        /// <param name="trial">The trial being run</param>
        /// <param name="currentMotion">Current motion</param>
        /// <param name="calculatedMotion">New motion, calculated by dynamics</param>
        /// <param name="controlInput">Current joystick position</param>
        /// <param name="noise">Noise input to position</param>
        internal void LogData(double time, Trial trial, MotionCommand currentMotion, MotionCommand calculatedMotion,
                              ControlInput controlInput, RotationAngles noise)
        {
            StringBuilder  builder;
            RotationAngles position;
            RotationAngles calcPosition;
            int            phase;

            position     = new RotationAngles();
            calcPosition = new RotationAngles();

            builder = new StringBuilder();
            switch (trial.TrialStatus)
            {
            case Trial.Status.Initializing:
                phase = 0;
                break;

            case Trial.Status.Moving:
                phase = 1;
                if (Hulk.InnerAxis == Hulk.Axis.Roll)
                {
                    position.roll = currentMotion.innerPosition;
                }
                else
                {
                    position.yaw = currentMotion.innerPosition;
                }
                position.pitch = currentMotion.outerPosition;
                break;

            case Trial.Status.BalancingDOBChanging:
                phase = 2;
                if (Hulk.InnerAxis == Hulk.Axis.Roll)
                {
                    position.roll     = currentMotion.innerPosition + trial.MovingDirectionOfBalance.roll;
                    calcPosition.roll = calculatedMotion.innerPosition + trial.MovingDirectionOfBalance.roll;
                }
                else
                {
                    position.yaw     = currentMotion.innerPosition + trial.MovingDirectionOfBalance.yaw;
                    calcPosition.yaw = calculatedMotion.innerPosition + trial.MovingDirectionOfBalance.yaw;
                }
                position.pitch     = currentMotion.outerPosition + trial.MovingDirectionOfBalance.pitch;
                calcPosition.pitch = calculatedMotion.outerPosition + trial.MovingDirectionOfBalance.pitch;
                break;

            case Trial.Status.BalancingDOBStable:
                phase = 3;
                if (Hulk.InnerAxis == Hulk.Axis.Roll)
                {
                    position.roll     = currentMotion.innerPosition + trial.MovingDirectionOfBalance.roll;
                    calcPosition.roll = calculatedMotion.innerPosition + trial.MovingDirectionOfBalance.roll;
                }
                else
                {
                    position.yaw     = currentMotion.innerPosition + trial.MovingDirectionOfBalance.yaw;
                    calcPosition.yaw = calculatedMotion.innerPosition + trial.MovingDirectionOfBalance.yaw;
                }
                position.pitch     = currentMotion.outerPosition + trial.MovingDirectionOfBalance.pitch;
                calcPosition.pitch = calculatedMotion.outerPosition + trial.MovingDirectionOfBalance.pitch;
                break;

            case Trial.Status.Resetting:
                phase = 4;
                if (Hulk.InnerAxis == Hulk.Axis.Roll)
                {
                    position.roll = currentMotion.innerPosition;
                }
                else
                {
                    position.yaw = currentMotion.innerPosition;
                }
                position.pitch = currentMotion.outerPosition;
                break;

            case Trial.Status.Complete:
                phase = 5;
                break;

            default:
                phase = -1;
                break;
            }

            if (Hulk.InnerAxis == Hulk.Axis.Roll)
            {
                builder.AppendFormat("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18},{19},{20},{21},{22},{23},{24},{25},{26},{27},{28},{29},{30}\n",
                                     time,
                                     trial.TrialNumber,
                                     phase,
                                     trial.DirectionOfBalance.roll,
                                     trial.DirectionOfBalance.pitch,
                                     trial.DirectionOfBalance.yaw,
                                     trial.MovingDirectionOfBalance.roll,
                                     trial.MovingDirectionOfBalance.pitch,
                                     trial.MovingDirectionOfBalance.yaw,
                                     position.roll,
                                     position.pitch,
                                     0,
                                     currentMotion.innerVelocity.ToString("F6"),
                                     currentMotion.outerVelocity.ToString("F6"),
                                     0,
                                     ((calculatedMotion != null) ? calcPosition.roll.ToString("F6") : "0"),
                                     ((calculatedMotion != null) ? calcPosition.pitch.ToString("F6") : "0"),
                                     0,
                                     ((calculatedMotion != null) ? calculatedMotion.innerVelocity.ToString("F6") : "0"),
                                     ((calculatedMotion != null) ? calculatedMotion.outerVelocity.ToString("F6") : "0"),
                                     0,
                                     ((calculatedMotion != null) ? calculatedMotion.innerAcceleration.ToString("F6") : "0"),
                                     ((calculatedMotion != null) ? calculatedMotion.outerAcceleration.ToString("F6") : "0"),
                                     0,
                                     controlInput.x.ToString("F6"),
                                     controlInput.y.ToString("F6"),
                                     (controlInput.blanked ? "1" : "0"),
                                     (controlInput.trigger ? "1" : "0"),
                                     noise.roll,
                                     noise.pitch,
                                     noise.yaw
                                     );
            }
            else
            {
                builder.AppendFormat("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},{17},{18},{19},{20},{21},{22},{23},{24},{25},{26},{27},{28},{29},{30}\n",
                                     time,
                                     trial.TrialNumber,
                                     phase,
                                     trial.DirectionOfBalance.roll,
                                     trial.DirectionOfBalance.pitch,
                                     trial.DirectionOfBalance.yaw,
                                     trial.MovingDirectionOfBalance.roll,
                                     trial.MovingDirectionOfBalance.pitch,
                                     trial.MovingDirectionOfBalance.yaw,
                                     0,
                                     position.pitch,
                                     position.yaw,
                                     0,
                                     currentMotion.outerVelocity.ToString("F6"),
                                     currentMotion.innerVelocity.ToString("F6"),
                                     0,
                                     ((calculatedMotion != null) ? calcPosition.pitch.ToString("F6") : "0"),
                                     ((calculatedMotion != null) ? calcPosition.yaw.ToString("F6") : "0"),
                                     0,
                                     ((calculatedMotion != null) ? calculatedMotion.outerVelocity.ToString("F6") : "0"),
                                     ((calculatedMotion != null) ? calculatedMotion.innerVelocity.ToString("F6") : "0"),
                                     0,
                                     ((calculatedMotion != null) ? calculatedMotion.outerAcceleration.ToString("F6") : "0"),
                                     ((calculatedMotion != null) ? calculatedMotion.innerAcceleration.ToString("F6") : "0"),
                                     controlInput.x.ToString("F6"),
                                     controlInput.y.ToString("F6"),
                                     (controlInput.blanked ? "1" : "0"),
                                     (controlInput.trigger ? "1" : "0"),
                                     noise.roll,
                                     noise.pitch,
                                     noise.yaw
                                     );
            }


            DataLogger.AppendData(builder.ToString());
        }
コード例 #8
0
        /// <summary>
        /// Creates the trial from the row/column data contained in the csvreader
        /// </summary>
        /// <param name="csvReader">The csvreader containing the row and column data</param>
        /// <param name="row">The row number of the data to use for this trial</param>
        internal Trial(CsvReader csvReader, int row)
        {
            logger.Debug("Create: Trial(CsvReader, int)");

            status = Status.Initializing;

            directionOfBalance       = new RotationAngles();
            movingDirectionOfBalance = new RotationAngles();
            visualOrientationOffset  = new RotationAngles();

            beginAtPoint = new RotationAngles();

            reminderGiven = false;

            trialNumber              = csvReader.getValueAsInt("TrialNumber", row);
            condition                = csvReader.getValueAsString("Condition", row);
            directionOfBalance.roll  = csvReader.getValueAsDouble("DOBRoll", row);
            directionOfBalance.pitch = csvReader.getValueAsDouble("DOBPitch", row);
            directionOfBalance.yaw   = csvReader.getValueAsDouble("DOBYaw", row);
            accelerationConstant     = csvReader.getValueAsDouble("AccelConstant", row);
            maxAcceleration          = csvReader.getValueAsDouble("MaxAcceleration", row);
            maxVelocity              = csvReader.getValueAsDouble("MaxVelocity", row);
            maxAngle            = csvReader.getValueAsDouble("MaxAngle", row);
            maxAcceleration     = csvReader.getValueAsDouble("MaxAcceleration", row);
            restartWhenMaxAngle = csvReader.getValueAsBool("RestartWhenMaxAngle", row);
            timeLimit           = csvReader.getValueAsDouble("TimeLimit", row);
            joystickGain        = csvReader.getValueAsDouble("JoystickGain", row);

            restartDOBOffsetMaxYaw   = csvReader.getValueAsDouble("RestartDOBOffsetMaxYaw", row);
            restartDOBOffsetMinYaw   = csvReader.getValueAsDouble("RestartDOBOffsetMinYaw", row);
            restartDOBOffsetMaxPitch = csvReader.getValueAsDouble("RestartDOBOffsetMaxPitch", row);
            restartDOBOffsetMinPitch = csvReader.getValueAsDouble("RestartDOBOffsetMinPitch", row);
            restartDOBOffsetMaxRoll  = csvReader.getValueAsDouble("RestartDOBOffsetMaxRoll", row);
            restartDOBOffsetMinRoll  = csvReader.getValueAsDouble("RestartDOBOffsetMinRoll", row);

            string val = csvReader.getValueAsString("JoystickControl", row);

            if (val.ToUpper() == "MIRROR")
            {
                joystickControl = JoystickControl.Mirrored;
            }
            else if (val.ToUpper() == "CW")
            {
                joystickControl = JoystickControl.Clockwise;
            }
            else if (val.ToUpper() == "CCW")
            {
                joystickControl = JoystickControl.Counterclockwise;
            }
            else
            {
                joystickControl = JoystickControl.Normal;
            }

            noiseProfile   = csvReader.getValueAsString("NoiseProfile", row);
            noiseAmplitude = csvReader.getValueAsDouble("NoiseAmplitude", row);
            useRoll        = csvReader.getValueAsBool("UseRoll", row);
            usePitch       = csvReader.getValueAsBool("UsePitch", row);
            useYaw         = csvReader.getValueAsBool("UseYaw", row);

            joystickIndicationsMandatory = csvReader.getValueAsBool("JoystickIndicationsMandatory", row);

            bool useBeginPoint = false;

            if (csvReader.hasValueAsDouble("BeginAtPitch", row) &&
                csvReader.hasValueAsDouble("BeginAtYaw", row) &&
                csvReader.hasValueAsDouble("BeginAtRoll", row))
            {
                beginAtPoint.yaw   = csvReader.getValueAsDouble("BeginAtYaw", row);
                beginAtPoint.pitch = csvReader.getValueAsDouble("BeginAtPitch", row);
                beginAtPoint.roll  = csvReader.getValueAsDouble("BeginAtRoll", row);
                useBeginPoint      = true;
            }

            if (!useBeginPoint)
            {
                beginAtPoint = null;
            }

            visualOrientationOffset.yaw   = csvReader.getValueAsDouble("VisualYawOffset", row);
            visualOrientationOffset.pitch = csvReader.getValueAsDouble("VisualPitchOffset", row);
            visualOrientationOffset.roll  = csvReader.getValueAsDouble("VisualRollOffset", row);

            moveSound       = csvReader.getValueAsString("MoveSound", row);
            startSound      = csvReader.getValueAsString("TrialStartSound", row);
            endSound        = csvReader.getValueAsString("TrialEndSound", row);
            resetStartSound = csvReader.getValueAsString("ResetStartSound", row);
            resetEndSound   = csvReader.getValueAsString("ResetEndSound", row);
            reminderSound   = csvReader.getValueAsString("ReminderSound", row);

            // sanity check
            if (restartDOBOffsetMaxYaw > maxAngle)
            {
                throw new Exception("Error when reading row " + (row + 1) + " from file " + csvReader.FileName + "\r\n" + "Reason: the maximum DOB yaw offset when restarting (column: RestartDOBOffsetMaxYaw) is larger than the maximum angle (column: MaxAngle)");
            }
            if (restartDOBOffsetMaxPitch > maxAngle)
            {
                throw new Exception("Error when reading row " + (row + 1) + " from file " + csvReader.FileName + "\r\n" + "Reason: the maximum DOB pitch offset when restarting (column: RestartDOBOffsetMaxPitch) is larger than the maximum angle (column: MaxAngle)");
            }
            if (restartDOBOffsetMaxRoll > maxAngle)
            {
                throw new Exception("Error when reading row " + (row + 1) + " from file " + csvReader.FileName + "\r\n" + "Reason: the maximum DOB roll offset when restarting (column: RestartDOBOffsetMaxRoll) is larger than the maximum angle (column: MaxAngle)");
            }

//            SetNoiseProfile();
            SetSoundPlayers();
        }
コード例 #9
0
 /// <summary>
 /// Creates an empty recording timepoint.
 /// </summary>
 internal RecordingTimepoint()
 {
     angles                   = new RotationAngles();
     directionOfBalance       = new RotationAngles();
     movingDirectionOfBalance = new RotationAngles();
 }
コード例 #10
0
 /// <summary>
 /// Creates an empty function timepoint.
 /// </summary>
 internal FunctionTimepoint()
 {
     input = new RotationAngles();
 }