-
Notifications
You must be signed in to change notification settings - Fork 1
/
controller.groovy
228 lines (188 loc) · 8.63 KB
/
controller.groovy
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
import com.neuronrobotics.bowlerstudio.creature.MobileBaseCadManager
import com.neuronrobotics.bowlerstudio.creature.MobileBaseLoader
import com.neuronrobotics.sdk.addons.kinematics.AbstractLink
import com.neuronrobotics.sdk.addons.kinematics.DHParameterKinematics
import com.neuronrobotics.sdk.addons.kinematics.ILinkListener
import com.neuronrobotics.sdk.addons.kinematics.MobileBase
import com.neuronrobotics.sdk.addons.kinematics.math.RotationNR
import com.neuronrobotics.sdk.addons.kinematics.math.TransformNR
import com.neuronrobotics.sdk.common.DeviceManager
import com.neuronrobotics.sdk.pid.PIDLimitEvent
import javafx.beans.value.ChangeListener
import javafx.beans.value.ObservableValue
import javafx.event.ActionEvent
import javafx.fxml.FXML
import javafx.scene.control.ComboBox
import javafx.scene.control.Slider
import javafx.scene.control.TableColumn
import javafx.scene.control.TextField
import javafx.scene.input.MouseEvent
public class HortonsController {
MobileBase system;
@FXML
private TableColumn<?, ?> l1AngleColumn;
@FXML
private TableColumn<?, ?> l2AngleColumn;
@FXML
private TableColumn<?, ?> l3AngleColumn;
@FXML
private TableColumn<?, ?> l4AngleColumn;
@FXML
private TableColumn<?, ?> transAngleColumn;
@FXML // ResourceBundle that was given to the FXMLLoader
private ResourceBundle resources;
@FXML // URL location of the FXML file that was given to the FXMLLoader
private URL location;
@FXML // fx:id="typeSelector"
private ComboBox<?> typeSelector; // Value injected by FXMLLoader
@FXML // fx:id="numOfLinks"
private TextField numOfLinks; // Value injected by FXMLLoader
@FXML // fx:id="lenLin2"
private TextField lenLin2; // Value injected by FXMLLoader
@FXML // fx:id="lenLin3"
private TextField lenLin3; // Value injected by FXMLLoader
@FXML // fx:id="lenLin4"
private TextField lenLin4; // Value injected by FXMLLoader
@FXML // fx:id="lenLin1"
private TextField lenLin1; // Value injected by FXMLLoader
@FXML // fx:id="angleLin1"
private TextField angleLin1; // Value injected by FXMLLoader
@FXML // fx:id="distToCoupler"
private TextField distToCoupler; // Value injected by FXMLLoader
@FXML // fx:id="angleToCoupler"
private TextField angleToCoupler; // Value injected by FXMLLoader
@FXML // fx:id="startAngle"
private TextField startAngle; // Value injected by FXMLLoader
@FXML // fx:id="endAngle"
private TextField endAngle; // Value injected by FXMLLoader
@FXML // fx:id="deltaAngle"
private TextField deltaAngle; // Value injected by FXMLLoader
@FXML // fx:id="velocityOfCrank"
private TextField velocityOfCrank; // Value injected by FXMLLoader
@FXML // fx:id="positionSlider"
private Slider positionSlider; // Value injected by FXMLLoader
private boolean running =false;
@FXML
void liveMove(MouseEvent event) {
double lower = Double.parseDouble(startAngle.getText())
double upper = Double.parseDouble(endAngle.getText())
double range =lower+( (upper-lower)*positionSlider.getValue()/100.0);
println "Live move "+range
setLinkAngle(range)
}
void setLinkAngle(double angle) {
if(angle.isNaN())
return;
new Thread() {
void run() {
try {
DHParameterKinematics limb =system.getAllDHChains().get(0)
DHParameterKinematics follower = system.getAllDHChains().get(1)
def crank =limb.getAbstractLink(0)
crank.setTargetEngineeringUnits(angle)
crank.flush(0);
//def tipOfCrank= limb.getCurrentTaskSpaceTransform()
def angles = limb.getCurrentJointSpaceVector()
angles[0]=angle;
def tipOfCrank= limb.forwardOffset(limb.forwardKinematics(angles))
if(follower.checkTaskSpaceTransform(tipOfCrank))
follower.setDesiredTaskSpaceTransform(tipOfCrank, 0)
}catch(Throwable t) {
t.printStackTrace();
}
}
}.start();
}
@FXML
void setType(ActionEvent event) {
println "Set Type of Linkage"
}
@FXML
void update(ActionEvent event) {
if(running)
return;
running =true;
new Thread() {
void run() {
println "Update Hortons"
double lower = Double.parseDouble(startAngle.getText())
double upper = Double.parseDouble(endAngle.getText())
double increment= Double.parseDouble(deltaAngle.getText())
double speed = Double.parseDouble(velocityOfCrank.getText())
double range = (upper-lower)
double secondsPerRange = range/speed
double numIncrements = range/increment
println "Seconds per range "+secondsPerRange
system.getAllDHChains().get(0).setDH_R(0, Double.parseDouble(lenLin2.getText()))
system.getAllDHChains().get(1).setDH_R(2, Double.parseDouble(lenLin3.getText()))
system.getAllDHChains().get(1).setDH_R(1, Double.parseDouble(lenLin4.getText()))
TransformNR tf = system.getAllDHChains().get(1).getRobotToFiducialTransform();
tf.setY(Double.parseDouble(lenLin1.getText()))
system.getAllDHChains().get(1).setRobotToFiducialTransform(tf)
for(double i=lower;i<=upper;i+=increment) {
setLinkAngle(i)
Thread.sleep((long)(secondsPerRange*1000.0/numIncrements))
}
setLinkAngle(0)
if(event !=null)
MobileBaseCadManager.get(system).generateCad();
running =false;
}
}.start();
}
@FXML // This method is called by the FXMLLoader when initialization is complete
void initialize() {
assert typeSelector != null : "fx:id=\"typeSelector\" was not injected: check your FXML file 'main.fxml'.";
assert numOfLinks != null : "fx:id=\"numOfLinks\" was not injected: check your FXML file 'main.fxml'.";
assert lenLin2 != null : "fx:id=\"lenLin2\" was not injected: check your FXML file 'main.fxml'.";
assert lenLin3 != null : "fx:id=\"lenLin3\" was not injected: check your FXML file 'main.fxml'.";
assert lenLin4 != null : "fx:id=\"lenLin4\" was not injected: check your FXML file 'main.fxml'.";
assert lenLin1 != null : "fx:id=\"lenLin1\" was not injected: check your FXML file 'main.fxml'.";
assert angleLin1 != null : "fx:id=\"angleLin1\" was not injected: check your FXML file 'main.fxml'.";
assert distToCoupler != null : "fx:id=\"distToCoupler\" was not injected: check your FXML file 'main.fxml'.";
assert angleToCoupler != null : "fx:id=\"angleToCoupler\" was not injected: check your FXML file 'main.fxml'.";
assert startAngle != null : "fx:id=\"startAngle\" was not injected: check your FXML file 'main.fxml'.";
assert endAngle != null : "fx:id=\"endAngle\" was not injected: check your FXML file 'main.fxml'.";
assert deltaAngle != null : "fx:id=\"deltaAngle\" was not injected: check your FXML file 'main.fxml'.";
assert velocityOfCrank != null : "fx:id=\"velocityOfCrank\" was not injected: check your FXML file 'main.fxml'.";
assert positionSlider != null : "fx:id=\"positionSlider\" was not injected: check your FXML file 'main.fxml'.";
println "Creating the controller for Hortons!"
def cl = new ChangeListener<Boolean>(){
@Override
public void changed(ObservableValue<? extends Boolean> arg0, Boolean oldPropertyValue, Boolean newPropertyValue)
{
if (!newPropertyValue)
{
update(null);
}
}
}
velocityOfCrank.focusedProperty().addListener(cl)
numOfLinks.focusedProperty().addListener(cl); // Value injected by FXMLLoader
lenLin2.focusedProperty().addListener(cl); // Value injected by FXMLLoader
lenLin3.focusedProperty().addListener(cl); // Value injected by FXMLLoader
lenLin4.focusedProperty().addListener(cl); // Value injected by FXMLLoader
lenLin1.focusedProperty().addListener(cl); // Value injected by FXMLLoader
angleLin1.focusedProperty().addListener(cl); // Value injected by FXMLLoader
distToCoupler.focusedProperty().addListener(cl); // Value injected by FXMLLoader
angleToCoupler.focusedProperty().addListener(cl); // Value injected by FXMLLoader
startAngle.focusedProperty().addListener(cl); // Value injected by FXMLLoader
endAngle.focusedProperty().addListener(cl); // Value injected by FXMLLoader
deltaAngle.focusedProperty().addListener(cl); // Value injected by FXMLLoader
velocityOfCrank.focusedProperty().addListener(cl); // Value injected by FXMLLoader
system = DeviceManager.getSpecificDevice( "FourBarGroup",{
MobileBase m = MobileBaseLoader.fromGit("https://github.com/WPIRoboticsEngineering/HortonsLinkages.git", "fourbar.xml")
return m
})
DHParameterKinematics limb =system.getAllDHChains().get(0)
DHParameterKinematics follower = system.getAllDHChains().get(1)
AbstractLink crank =limb.getAbstractLink(0)
lenLin2.setText(""+limb.getDH_R(0))
lenLin3.setText(""+follower.getDH_R(2))
lenLin4.setText(""+follower.getDH_R(1))
lenLin1.setText(""+(follower.getRobotToFiducialTransform().getY()))
velocityOfCrank.setText("360")
update(null)
}
}
return new HortonsController()