-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDriveTrain.cpp
More file actions
233 lines (199 loc) · 6.28 KB
/
DriveTrain.cpp
File metadata and controls
233 lines (199 loc) · 6.28 KB
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
#include "DriveTrain.h"
#include "Config.h"
using namespace std;
DriveTrain::DriveTrain(int fl, int fr, int rl, int rr)
{
FLMotor = new CANJaguar(fl);
FRMotor = new CANJaguar(fr);
RLMotor = new CANJaguar(rl);
RRMotor = new CANJaguar(rr);
Odometer = new Encoder(9,10,false,Encoder::k4X);
ResetCANJaguars();
Odometer->Start();
double WheelCircumference = Config::GetSetting("drive_WheelCircumference",18.85);
double GearRatio = Config:: GetSetting("drive_GearRatio",30.2934);
int EncoderLines = (int)Config::GetSetting("drive_encoderlines",360);
double DistancePerPulse = WheelCircumference / EncoderLines / GearRatio ;
Odometer->SetDistancePerPulse(DistancePerPulse);
cout << "DistancePerPulse =" << DistancePerPulse << endl;
Sol1 = new DoubleSolenoid(1,2);
}
void DriveTrain::ResetCANJaguars()
{
InitCANJags(FLMotor);
InitCANJags(FRMotor);
InitCANJags(RLMotor);
InitCANJags(RRMotor);
}
void DriveTrain::InitCANJags(CANJaguar* motor)
{
for(int x=0;x<5;x++)
{
if(motor->GetControlMode() != CANJaguar::kSpeed) //Checks whether the motor is in speed control mode
{
motor->ChangeControlMode(CANJaguar::kSpeed); //Changes to speed control
motor->SetSpeedReference(CANJaguar::kSpeedRef_QuadEncoder); //Tells the program that a quad encoder is being used
motor->ConfigEncoderCodesPerRev((int)Config::GetSetting("drive_encoderlines",360)); //Sets 360 as the lines per encoder revolution
motor->SetPID(DRIVE_KP,DRIVE_KI,DRIVE_KD); //Sets the proportional, integral, and derivative values for closed loop speed
motor->ConfigNeutralMode(CANJaguar::kNeutralMode_Coast);
motor->EnableControl(0.0);//Starts controlling output based on feedback
} else {
break;
}
}
}
double DriveTrain::GetDist()
{
return Odometer->GetDistance() * -1;
}
void DriveTrain::ResetOdometer()
{
Odometer->Reset();
}
void DriveTrain::StopOdometer()
{
Odometer->Stop();
}
void DriveTrain::LogHeaders(ofstream &fout)
{ //Creates the headers for the logging file
char * motor_names[4] = { "Front Left", "Front Right", "Rear Left", "Rear Right" };
for (int i = 0; i < 4; i++) {
char * name = motor_names[i];
fout << name << " RPM Target,";
fout << name << " RPM Actual,";
fout << name << " Voltage,";
fout << name << " Current,";
fout << name << " Faults,";
fout << name << " Reset,";
fout << name << " Mode,";
}
fout << "Odometer,";
fout << "Tank/Mecanum*,";
}
void DriveTrain::LogMotors(ofstream &fout)
{ //Stores different outputs from the motors in the logging file
CANJaguar * motors[4] = { FLMotor, FRMotor, RLMotor, RRMotor };
for (int i = 0; i < 4; i++)
{
CANJaguar * motor = motors[i];
fout << motor->Get() << ",";
fout << motor->GetSpeed() << ",";
fout << motor->GetOutputVoltage() << ",";
fout << motor->GetOutputCurrent() << ",";
fout << motor->GetFaults() << ",";
fout << motor->GetPowerCycled() << ",";
fout << motor->GetControlMode() << ",";
}
fout << GetDist() << ",";
fout << Tank << ",";
}
void DriveTrain::Drive(double LeftXAxis, double LeftYAxis, double RightXAxis, double RightYAxis, double Gyro, bool FieldOrientated)
{ //Basic driving function for joystick based inputs
if(Tank == true)
{
this->DeadZone(LeftXAxis,LeftYAxis,RightXAxis,RightYAxis); //Checks whether Joysticks are in a range near 0
this->TankDrive(LeftYAxis,RightYAxis);
}
else if (Tank == false)
{
this->DeadZone(LeftXAxis,LeftYAxis,RightXAxis,RightYAxis); //Checks whether Joysticks are in a range near 0
if(FieldOrientated)
{
this->MecanumDrive(LeftXAxis,LeftYAxis,RightXAxis,Gyro);
}
else
{
this->MecanumDrive(LeftXAxis,LeftYAxis,RightXAxis,0.0);
}
}
}
void DriveTrain::TankDrive(double left, double right)
{
FRMotor->Set(-1 * (right * MAX_SPEED));
RRMotor->Set(-1 * (right * MAX_SPEED));
FLMotor->Set( (left * MAX_SPEED));
RLMotor->Set( (left * MAX_SPEED));
}
void DriveTrain::SwitchDrive(bool tank,bool mech)
{ //Function that switches from tank drive to mecanum drive and vice versa
if(tank)
{
Sol1->Set(DoubleSolenoid::kReverse);
Tank = true;
}
else if(mech)
{
Sol1->Set(DoubleSolenoid::kForward);
Tank = false;
}
else
{
Sol1->Set(DoubleSolenoid::kOff);
}
}
void DriveTrain::Rotate(double r)
{ //Rotates at r speed
if(Tank == false)
this->MecanumDrive(0,0,-r,0);
if(Tank == true)
this->TankDrive(r,-r);
}
void DriveTrain::DeadZone(double &LeftXAxis,double &LeftYAxis,double &RightXAxis,double &RightYAxis)
{ //Function to see whether joystick values are in a range near 0
if((LeftXAxis < 0.05) && (LeftXAxis > -0.05))
LeftXAxis = 0;
if((LeftYAxis < 0.05) && (LeftYAxis > -0.05))
LeftYAxis = 0;
if((RightXAxis < 0.05) && (RightXAxis > -0.05))
RightXAxis = 0;
if((RightYAxis < 0.05) && (RightYAxis > -0.05))
RightYAxis = 0;
}
void DriveTrain::MecanumDrive(double x, double y, double r, double gyro)
{
double xIn = x; //reversed to make the electronics the front of the robot
double yIn = y;
double rotation = r;
yIn = -yIn;
this->RotateVector(xIn, yIn, gyro);
double wheelSpeeds[4];
wheelSpeeds[0] = -1 * ( xIn + yIn + rotation);
wheelSpeeds[1] = -xIn + yIn - rotation;
wheelSpeeds[2] = -1 * (-xIn + yIn + rotation);
wheelSpeeds[3] = xIn + yIn - rotation;
this->Normalize(wheelSpeeds);
FLMotor->Set(wheelSpeeds[0] * MAX_SPEED);
FRMotor->Set(wheelSpeeds[1] * MAX_SPEED);
RLMotor->Set(wheelSpeeds[2] * MAX_SPEED);
RRMotor->Set(wheelSpeeds[3] * MAX_SPEED);
}
bool DriveTrain::GetMechanum()
{
return !Tank;
}
void DriveTrain::RotateVector(double &x, double &y, double angle)
{
double cosA = cos(angle * (3.14159 / 180.0));
double sinA = sin(angle * (3.14159 / 180.0));
double xOut = x * cosA - y * sinA;
double yOut = x * sinA + y * cosA;
x = xOut;
y = yOut;
}
void DriveTrain::Normalize(double *wheelSpeeds)
{ //Changes the wheel speeds to be in a scale from -1 to 1
double maxMagnitude = fabs(wheelSpeeds[0]);
INT32 i;
for (i=1; i<4; i++)
{
double temp = fabs(wheelSpeeds[i]);
if (maxMagnitude < temp) maxMagnitude = temp;
}
if (maxMagnitude > 1.0)
{
for (i=0; i<4; i++)
{
wheelSpeeds[i] = wheelSpeeds[i] / maxMagnitude;
}
}
}