-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathControlServer.java
256 lines (217 loc) · 7.92 KB
/
ControlServer.java
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
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/**
* This program runs as a server and controls the force to be applied to balance the Inverted Pendulum system running on the clients.
*/
import java.io.*;
import java.net.*;
import java.util.*;
import java.lang.Math.*;
public class ControlServer {
private static ServerSocket serverSocket;
private static final int port = 25533;
/**
* Main method that creates new socket and PoleServer instance and runs it.
*/
public static void main(String[] args) throws IOException {
try {
serverSocket = new ServerSocket(port);
} catch (IOException ioe) {
System.out.println("Unable to set up port:" + ioe);
System.exit(1);
}
System.out.println("Waiting for connection");
do {
Socket client = serverSocket.accept();
System.out.println("\nnew client accepted.\n");
PoleServer_handler handler = new PoleServer_handler(client);
} while (true);
}
}
/**
* This class sends control messages to balance the pendulum on client side.
*/
class PoleServer_handler implements Runnable {
// Set the number of poles
private static final int NUM_POLES = 2;
static ServerSocket providerSocket;
Socket connection = null;
ObjectOutputStream out;
ObjectInputStream in;
String message = "abc";
static Socket clientSocket;
Thread t;
/**
* Class Constructor
*/
public PoleServer_handler(Socket socket) {
t = new Thread(this);
clientSocket = socket;
try {
out = new ObjectOutputStream(clientSocket.getOutputStream());
out.flush();
in = new ObjectInputStream(clientSocket.getInputStream());
} catch (IOException ioe) {
ioe.printStackTrace();
}
t.start();
}
double angle, angleDot, pos, posDot, action = 0, i = 0;
//Data used for part three
int current_pole = 0;
double last_angle = 0;
double last_angleDot = 0;
double last_pos = 0;
double last_posDot = 0;
/**
* This method receives the pole positions and calculates the updated value
* and sends them across to the client.
* It also sends the amount of force to be applied to balance the pendulum.
* @throws ioException
*/
void control_pendulum(ObjectOutputStream out, ObjectInputStream in) {
try {
while(true){
System.out.println("-----------------");
// read data from client
Object obj = in.readObject();
// Do not process string data unless it is "bye", in which case,
// we close the server
if(obj instanceof String){
System.out.println("STRING RECEIVED: "+(String) obj);
if(obj.equals("bye")){
break;
}
continue;
}
double[] data= (double[])(obj);
assert(data.length == NUM_POLES * 4);
double[] actions = new double[NUM_POLES];
// Get sensor data of each pole and calculate the action to be
// applied to each inverted pendulum
// TODO: Current implementation assumes that each pole is
// controlled independently. This part needs to be changed if
// the control of one pendulum needs sensing data from other
// pendulums.
for (int i = 0; i < NUM_POLES; i++) {
angle = data[i*4+0];
angleDot = data[i*4+1];
pos = data[i*4+2];
posDot = data[i*4+3];
System.out.println("server < pole["+i+"]: "+angle+" "
+angleDot+" "+pos+" "+posDot);
current_pole = i;
if(current_pole == 0){
last_angle = angle;
last_angleDot = angleDot;
last_pos = pos;
last_posDot = posDot;
}
actions[i] = calculate_action(angle, angleDot, pos, posDot);
}
sendMessage_doubleArray(actions);
}
} catch (Exception ex) {
ex.printStackTrace();
}
try {
if (clientSocket != null) {
System.out.println("closing down connection ...");
out.writeObject("bye");
out.flush();
in.close();
out.close();
clientSocket.close();
}
} catch (IOException ioe) {
System.out.println("unable to disconnect");
}
System.out.println("Session closed. Waiting for new connection...");
}
/**
* This method calls the controller method to balance the pendulum.
* @throws ioException
*/
public void run() {
try {
control_pendulum(out, in);
} catch (Exception ioException) {
ioException.printStackTrace();
} finally {
}
}
double output = 0;
double target_position = 0;
//THIS WAS TWO CHANGE IT
int p_gain = 10;
int d_gain = 2;
double p_gain_trans = .1;
double angle_p_gain = .2;
double angle_d_gain = .2;
// Calculate the actions to be applied to the inverted pendulum from the
// sensing data.
double calculate_action(double angle, double angleDot, double pos, double posDot) {
if(NUM_POLES > 1){
if(current_pole == 1){
//Set target position of follower pole, based on position of guide pole
if(pos < last_pos){
target_position = last_pos - 1;
if(last_posDot < 0){
target_position += last_posDot;
}
}else{
target_position = last_pos + 1;
if(last_posDot > 0){
target_position += last_posDot;
}
}
}else{
//Set target position of guide pole
target_position = 1;
}
}else{
//Set target position of the follower pole (part 1 & 2)
target_position = 0;
}
double separation = target_position - pos;
double target_angle = separation * angle_p_gain;
target_angle = target_angle - posDot * angle_d_gain;
//Bound the target angle to 1. This prevents tipping regardless of seperation
if(target_angle > 1){
target_angle = 1;
}else if(target_angle < -1){
target_angle = -1;
}
double angle_error = angle - target_angle;
output = angle_error * p_gain;
output = output + (angleDot* d_gain);
return output;
}
/**
* This method sends the Double message on the object output stream.
* @throws ioException
*/
void sendMessage_double(double msg) {
try {
out.writeDouble(msg);
out.flush();
System.out.println("server>" + msg);
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
/**
* This method sends the Double message on the object output stream.
*/
void sendMessage_doubleArray(double[] data) {
try {
out.writeObject(data);
out.flush();
System.out.print("server> ");
for(int i=0; i< data.length; i++){
System.out.print(data[i] + " ");
}
System.out.println();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}