private void testController() { Console.WriteLine("Testing constoller ..."); EV3Brick ev3 = new EV3Brick(); ev3.connect(); // current status: normalize int motorAdeg = (int)(ev3.getMotorADegree() / 50.0); int motorBdeg = (int)(ev3.getMotorBDegree() / 300.0); /* * training data = [ * [[0,0,0,1], [0,1]], // down1 * [[0,1,1,1], [1,0]], // pick * [[1,1,1,0], [0,-1]], // up1 * [[1,0,1,1], [0,1]], // down2 * [[1,1,0,1], [-1,0]], // drop * [[0,1,0,0], [0,-1]] // up2 * ] */ var argv = new List <int[]> (); // current (A, B), desired (A, B) // down1 argv.Add(new [] { motorAdeg, motorBdeg, 0, 1 }); // argv.Add (new []{0,0,0,1}); argv.Add(new [] { 0, 1 }); // targets A, B // up1 // argv.Add (new []{1,1,1,0}); // argv.Add (new []{motorAdeg,motorBdeg,1,0}); // argv.Add (new []{0,-1}); // targets A, B var engine = Python.CreateEngine(); var paths = engine.GetSearchPaths(); paths.Add(pythonPath); engine.SetSearchPaths(paths); engine.GetSysModule().SetVariable("argv", argv); var scriptRuntime = Python.CreateRuntime(); scriptRuntime.GetSysModule().SetVariable("argv", argv); try { dynamic result = engine.ExecuteFile("script.py"); Console.WriteLine(result.outputs); var outputs = result.outputs; foreach (double output in outputs) { Console.WriteLine(output); } motorAdeg = (int)(outputs[0] * 50); motorBdeg = (int)(outputs[1] * 300); Console.WriteLine(motorAdeg + ", " + motorBdeg); ev3.moveMotorA(motorAdeg); ev3.moveMotorB(motorBdeg); Thread.Sleep(5000); } catch (Exception ex) { Console.WriteLine( "Oops! We couldn't execute the script because of an exception: " + ex.Message); } ev3.disconnect(); Console.WriteLine("Complete."); // Console.ReadLine(); }
// verified void balance() { Console.WriteLine("refpos = " + refpos + ", dt = " + dt + ", Kp = " + Kp + ", Ki = " + Ki + ", Kd = " + Kd); Console.WriteLine("iter\tspeed\tang_vel\tang" + "\tsensor\tavg_pwr\toffset\trefpos" + "\tmspeed" + "\tspeedA\tspeedD\textra\tpwr_b\tpwr_c" // + "\tcurr_err\tacc_err\tdif_err\tprev_err" ); Stopwatch totalwatch = Stopwatch.StartNew(); Stopwatch functionwatch = Stopwatch.StartNew(); int iter = 0; stopwatch.Restart(); while (iter++ < max_iter) { // Position: verified refpos = refpos + (dt * speed * 0.002f); // ReadEncoders: verified //functionwatch.Restart(); float motor_speed = (radius * getMotorSpeed()) / radius_const; float motor_position = (radius * (ev3.getMotorADegree() + ev3.getMotorDDegree()) / 2.0f) / radius_const; //Console.Write(functionwatch.ElapsedMilliseconds + "ms "); // ReadGyro: verified //functionwatch.Restart(); float ang_vel = readGyro(); //Console.Write(functionwatch.ElapsedMilliseconds + "ms "); // CombineSensorValues: verified //functionwatch.Restart(); float sensor_values = combineSensorValues(ang_vel, motor_position, motor_speed); //Console.Write(functionwatch.ElapsedMilliseconds + "ms "); // PID: verified // input: sensor values // output: average power //functionwatch.Restart(); float avg_pwr = pid(sensor_values); // float avg_pwr = pid (sensor_values, curr_err, acc_err, dif_err, prev_err); //Console.Write(functionwatch.ElapsedMilliseconds + "ms "); // Errors: verified // input: PID output //functionwatch.Restart(); errors(avg_pwr); //Console.Write(functionwatch.ElapsedMilliseconds + "ms "); /* * Console.Write (iter + "\t" + speed + "\t" + ang_vel.ToString(FORMAT) + "\t" + ang.ToString(FORMAT) + "\t" + sensor_values.ToString(FORMAT) + "\t" + avg_pwr.ToString(FORMAT) + "\t" + (motor_position - refpos).ToString(FORMAT) + "\t" + refpos.ToString(FORMAT) + "\t" + motor_speed.ToString(FORMAT) + "\t" + ); */ // SetMotorPower: verified // input: pid output //functionwatch.Restart(); setMotorPower(avg_pwr); //Console.WriteLine(functionwatch.ElapsedMilliseconds + "ms"); // Wait: verified // Timer >= dt, elapsedTime long elapsedTime = stopwatch.ElapsedMilliseconds; Console.WriteLine(elapsedTime + " " + totalwatch.ElapsedMilliseconds); if (elapsedTime >= dt * 1000f) { stopwatch.Restart(); } } complete = true; }
private void balance() { Console.WriteLine("start balancing ..."); starting_balancing_task = true; /////////////////////////// //ADVANCED USER CONTROL /////////////////////////// /* * The following values can be modified for advanced control. Many users will not use these features, * which is why I do not require these to be set in the main program. You can just modify them here. * if you are unsure about what they do, just leave them at the default value. */ // Set gearing down ratio between motor and wheels (e.g. 5x slow down: 40z / 8z = 5) // The default is 1, no gearing down. gear_down_ratio = 1; // Set the time each loop cycle should last. You can set it up to 0.03 seconds or even higher, if you really // need to. If you add code to the control loop below (such as to read another sensor), make sure that // all code can run in under dt seconds. If it takes more time, set dt to a higher value. // Default is 0.010 seconds (10 miliseconds). dt = 0.010f; // Customize PID constants. These variables are global, so you can optionally dynamically change them in your main task. gn_dth_dt = 0.23f; gn_th = 25.00f; gn_y = 272.8f; gn_dy_dt = 24.6f; kp = 0.0336f; ki = 0.2688f; kd = 0.000504f; /////////////////////////// //END ADVANCED USER CONTROL /////////////////////////// //MOTOR SETUP int motorB = 1; int motorC = 2; int mtrNoReg = 0; int[] nMotorPIDSpeedCtrl = new int[4]; nMotorPIDSpeedCtrl[motorB] = mtrNoReg; nMotorPIDSpeedCtrl[motorC] = mtrNoReg; int[] nMotorEncoder = new int[4]; nMotorEncoder[motorC] = 0; nMotorEncoder[motorB] = 0; int[] motor = new int[4]; ev3.resetMotorATachoCount(); ev3.resetMotorDTachoCount(); // Sensor setup int Gyro = 2; int[] SensorType = new int[5]; // SensorType[Gyro] = ev3.getAngularVelocity(); int nSensorsDefined = 0; mean_reading = 0; /* #ifdef HiTechnic_Gyro * SensorType[Gyro] = sensorRawValue; * // The following sets the average HiTechnic sensor value. If you know the average, you can avoid the calibration * // next time like so: mean_reading = 593.82; (if that's your sensor average). * mean_reading = calibrate_hitechnic(); * nSensorsDefined++; #endif #ifdef MindSensors_IMU * int ux,uy,uz; // Mindsensors Sensor Measurement * mean_reading = 0; * SensorType[Gyro] = sensorI2CCustomFastSkipStates; * wait1Msec(500); * MSIMUsetGyroFilter(Gyro, 0x00); * wait1Msec(1000); * nSensorsDefined++; #endif * if(nSensorsDefined != 1){ * nxtDisplayTextLine(0,"Check Sensor"); * nxtDisplayTextLine(1,"definition!"); * wait1Msec(5000);StopAllTasks(); * } */ //MATH CONSTANTS const float radius = wheel_diameter / 1000; const float degtorad = (float)Math.PI / 180; //SETUP VARIABLES FOR CALCULATIONS float u = 0; // Sensor Measurement (raw) float th = 0, //Theta // Angle of robot (degree) dth_dt = 0; //dTheta/dt // Angular velocity of robot (degree/sec) float e = 0, //Error // Sum of four states to be kept zero: th, dth_dt, y, dy_dt. de_dt = 0, //dError/dt // Change of above error _edt = 0, //Integral Error // Accumulated error in time e_prev = 0; //Previous Error/ Error found in previous loop cycle float pid = 0; // SUM OF PID CALCULATION float y = 0, //y // Measured Motor position (degrees) dy_dt = 0, //dy/dt // Measured motor velocity (degrees/sec) v = 0, //velocity // Desired motor velocity (degrees/sec) y_ref = 0; //reference pos // Desired motor position (degrees) int motorpower = 0, // Power ultimately applied to motors last_steering = 0, // Steering value in previous cycle straight = 0, // Average motor position for synchronizing d_pwr = 0; // Change in power required for synchronizing const int n_max = 7; // Number of measurement used for floating motor speed average int n = 0, n_comp = 0; // Intermediate variables needed to compute measured motor speed int[] encoder = new int[n_max]; // Array containing last n_max motor positions // memset(&encoder[0],0,sizeof(encoder)); starting_balancing_task = false; // We're done configuring. Main task now resumes. // ClearTimer(T4); // This timer is used in the driver. Do not use it for other purposes! Console.WriteLine("iter\tu\tpid\tth\tmotorpower\td_pwr\tmotorB\tmotorC"); int iter = 0; // while(true) while (iter++ < max_iter) { //READ GYRO SENSOR u = ev3.getAngularVelocity(); Thread.Sleep(2); u = ev3.getAngularVelocity(); /* #ifdef HiTechnic_Gyro * u = SensorRaw[Gyro];wait1Msec(2); * u = u+SensorRaw[Gyro]; #endif #ifdef MindSensors_IMU * MSIMUreadGyroAxes(Gyro, ux, uy, uz); * u = uz*0.0210; #endif * //////////// */ //COMPUTE GYRO ANGULAR VELOCITY AND ESTIMATE ANGLE dth_dt = u / 2 - mean_reading; mean_reading = mean_reading * 0.999f + (0.001f * (dth_dt + mean_reading)); th = th + dth_dt * dt; //ADJUST REFERENCE POSITION ON SPEED AND ACCELERATION if (v < speed * 10) { v = v + acceleration * 10 * dt; } else if (v > speed * 10) { v = v - acceleration * 10 * dt; } y_ref = y_ref + v * dt; //COMPUTE MOTOR ENCODER POSITION AND SPEED nMotorEncoder [motorB] = ev3.getMotorADegree(); nMotorEncoder [motorC] = ev3.getMotorDDegree(); n++; if (n == n_max) { n = 0; } encoder[n] = nMotorEncoder[motorB] + nMotorEncoder[motorC] + (int)y_ref; n_comp = n + 1; if (n_comp == n_max) { n_comp = 0; } y = encoder[n] * degtorad * radius / gear_down_ratio; dy_dt = (encoder[n] - encoder[n_comp]) / (dt * (n_max - 1)) * degtorad * radius / gear_down_ratio; //COMPUTE COMBINED ERROR AND PID VALUES e = gn_th * th + gn_dth_dt * dth_dt + gn_y * y + gn_dy_dt * dy_dt; de_dt = (e - e_prev) / dt; _edt = _edt + e * dt; e_prev = e; pid = (kp * e + ki * _edt + kd * de_dt) / radius * gear_down_ratio; //ADJUST MOTOR SPEED TO STEERING AND SYNCHING if (steering == 0) { if (last_steering != 0) { straight = nMotorEncoder[motorC] - nMotorEncoder[motorB]; } d_pwr = (int)((nMotorEncoder[motorC] - nMotorEncoder[motorB] - straight) / (radius * 10 / gear_down_ratio)); } else { d_pwr = (int)(steering / (radius * 10 / gear_down_ratio)); } last_steering = steering; //CONTROL MOTOR POWER AND STEERING motorpower = (int)pid; motor[motorB] = motorpower + d_pwr; motor[motorC] = motorpower + d_pwr; // motor[motorC] = motorpower - d_pwr; //ERROR CHECKING OR SHUTDOWN Console.WriteLine(iter + "\t" + u + "\t" + pid + "\t" + th + "\t" + motorpower + "\t" + d_pwr + "\t" + motor[motorB] + "\t" + motor[motorC]); if (pid.Equals(float.NaN) || Math.Abs(th) > 60 || Math.Abs(motorpower) > 2000) { // StopAllTasks(); Console.WriteLine("error"); ev3.stopAll(); break; } ev3.onMotorA(motor [motorB]); ev3.onMotorD(motor [motorC]); // ev3.onMotorA (motor [motorB]/100); // ev3.onMotorD (motor [motorC]/100); // //WAIT THEN REPEAT // while(time1[T4] < dt*1000){ // wait1Msec(1); // } // ClearTimer(T4); Thread.Sleep((int)(dt * 1000)); } }
private void testController() { Console.WriteLine("Testing constoller ..."); EV3Brick ev3 = new EV3Brick (); ev3.connect (); // current status: normalize int motorAdeg = (int) (ev3.getMotorADegree()/50.0); int motorBdeg = (int) (ev3.getMotorBDegree()/300.0); /* training data = [ [[0,0,0,1], [0,1]], // down1 [[0,1,1,1], [1,0]], // pick [[1,1,1,0], [0,-1]], // up1 [[1,0,1,1], [0,1]], // down2 [[1,1,0,1], [-1,0]], // drop [[0,1,0,0], [0,-1]] // up2 ] */ var argv = new List<int[]> (); // current (A, B), desired (A, B) // down1 argv.Add (new []{motorAdeg,motorBdeg,0,1}); // argv.Add (new []{0,0,0,1}); argv.Add (new []{0,1}); // targets A, B // up1 // argv.Add (new []{1,1,1,0}); // argv.Add (new []{motorAdeg,motorBdeg,1,0}); // argv.Add (new []{0,-1}); // targets A, B var engine = Python.CreateEngine(); var paths = engine.GetSearchPaths(); paths.Add(pythonPath); engine.SetSearchPaths(paths); engine.GetSysModule ().SetVariable ("argv", argv); var scriptRuntime = Python.CreateRuntime(); scriptRuntime.GetSysModule().SetVariable("argv", argv); try { dynamic result = engine.ExecuteFile("script.py"); Console.WriteLine(result.outputs); var outputs = result.outputs; foreach (double output in outputs) { Console.WriteLine(output); } motorAdeg = (int) (outputs[0]*50); motorBdeg = (int) (outputs[1]*300); Console.WriteLine(motorAdeg + ", " + motorBdeg); ev3.moveMotorA(motorAdeg); ev3.moveMotorB(motorBdeg); Thread.Sleep(5000); } catch (Exception ex) { Console.WriteLine( "Oops! We couldn't execute the script because of an exception: " + ex.Message); } ev3.disconnect (); Console.WriteLine("Complete."); // Console.ReadLine(); }