Revision 644
Changed move-to-point colonet behavior. Need to test.
trunk/code/projects/colonet/robot/robot_slave/robot_slave.c | ||
---|---|---|
12 | 12 |
#include <serial.h> |
13 | 13 |
#include <stdio.h> |
14 | 14 |
|
15 |
int behavior_status; |
|
16 |
|
|
15 | 17 |
int main(void) { |
16 | 18 |
dragonfly_init(ALL_ON); |
17 | 19 |
|
trunk/code/projects/colonet/robot/colonet_dragonfly/colonet_dragonfly.c | ||
---|---|---|
17 | 17 |
#include <string.h> |
18 | 18 |
#include <wireless.h> |
19 | 19 |
|
20 |
#define TARGET_POSITION_STOP_DISTANCE_THRESHOLD (40.0)
|
|
20 |
#define TARGET_POSITION_STOP_DISTANCE_THRESHOLD (40) |
|
21 | 21 |
|
22 | 22 |
typedef struct { |
23 | 23 |
unsigned char msgId; //is this necessary? |
... | ... | |
28 | 28 |
static UserHandler user_handlers[USER_DEFINED_MSG_TOTAL]; |
29 | 29 |
|
30 | 30 |
static unsigned robot_x, robot_y; |
31 |
static unsigned last_x, last_y; |
|
31 | 32 |
static volatile int updated_robot_pos_ready; |
32 | 33 |
static volatile int new_movement_command_received; |
33 | 34 |
#define ERROR_MAG_TO_MOTOR_DIFFENTIAL_CONST (1) |
... | ... | |
36 | 37 |
static unsigned two_bytes_to_int(unsigned char high, unsigned char low); |
37 | 38 |
static void colonet_handle_receive(char type, int source, unsigned char* packet, int length); |
38 | 39 |
static void move_to_position_routine(unsigned x, unsigned y); |
40 |
static int dist_squared(int x1, int y1, int x2, int y2); |
|
39 | 41 |
|
40 | 42 |
static PacketGroupHandler colonet_pgh; |
41 | 43 |
|
... | ... | |
57 | 59 |
// TODO this should return an error if wl_init has not been called yet. |
58 | 60 |
wl_register_packet_group(&colonet_pgh); |
59 | 61 |
|
60 |
robot_x = 0; |
|
61 |
robot_y = 0; |
|
62 |
robot_x = last_x = 0;
|
|
63 |
robot_y = last_y = 0;
|
|
62 | 64 |
updated_robot_pos_ready = 0; |
63 | 65 |
new_movement_command_received = 0; |
64 | 66 |
|
... | ... | |
87 | 89 |
|
88 | 90 |
void request_abs_position() { |
89 | 91 |
//usb_puts("requesting_abs_position\n"); |
90 |
|
|
91 | 92 |
ColonetRobotServerPacket pkt; |
92 | 93 |
pkt.client_id = -1; |
93 | 94 |
pkt.msg_code = ROBOT_REQUEST_POSITION_FROM_SERVER; |
94 | 95 |
wl_send_global_packet(colonet_pgh.groupCode, 0, (char*)&pkt, sizeof(ColonetRobotServerPacket), 0); |
95 | 96 |
} |
96 | 97 |
|
97 |
static float sqrt_approx(float x) { |
|
98 |
float x2 = x*x; |
|
99 |
float x3 = x*x2; |
|
100 |
|
|
101 |
return 0.00014*x3 - 0.0078*x2 + 0.29*x + 0.84; |
|
98 |
static int dist_squared(int x1, int y1, int x2, int y2) { |
|
99 |
int dx = x1 - x2; |
|
100 |
int dy = y1 - y2; |
|
101 |
return dx*dx + dy*dy; |
|
102 | 102 |
} |
103 | 103 |
|
104 |
static float dist(float x1, float y1, float x2, float y2) { |
|
105 |
return sqrt_approx((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)); |
|
106 |
} |
|
107 |
|
|
108 |
/* cubic approximation of arctan. */ |
|
109 |
/*static void arctan(float t) { |
|
110 |
float t3 = t*t*t; |
|
111 |
return -0.039 * t3 + 0.74 * t + 0.00011; |
|
112 |
}*/ |
|
113 |
|
|
114 | 104 |
/** Differential is the intended left motor speed - right motor speed. */ |
115 | 105 |
static void set_motors_with_differential(int differential) { |
116 | 106 |
int ml, mr; |
... | ... | |
149 | 139 |
} |
150 | 140 |
} |
151 | 141 |
|
152 |
// usb_puts("got past first loop.\n"); |
|
153 |
|
|
154 |
unsigned last_x = robot_x, last_y = robot_y; |
|
155 |
|
|
156 |
// char buf[40]; |
|
157 |
//sprintf(buf, "cur dist is %f\n", dist((float)robot_x, (float)robot_y, (float)target_x, (float)target_y)); |
|
158 |
//usb_puts(buf); |
|
159 |
//sprintf(buf, "radius squared is %f\n", TARGET_POSITION_STOP_DISTANCE_THRESHOLD); |
|
160 |
//usb_puts(buf); |
|
161 |
|
|
162 | 142 |
while (!new_movement_command_received && |
163 |
dist(robot_x, robot_y, target_x, target_y) > TARGET_POSITION_STOP_DISTANCE_THRESHOLD) { |
|
143 |
dist_squared(robot_x, robot_y, target_x, target_y) > TARGET_POSITION_STOP_DISTANCE_THRESHOLD) {
|
|
164 | 144 |
updated_robot_pos_ready = 0; |
165 |
request_abs_position(); // While we're doing this computation, server can be reporting next position. |
|
145 |
request_abs_position(); // While we're doing this computation, server can be reporting next position.
|
|
166 | 146 |
|
167 |
// usb_puts("after request_abs_position.\n"); |
|
147 |
// e is the error vector (where we want to go) |
|
148 |
int e_x = target_x - robot_x; |
|
149 |
int e_y = target_y - robot_y; |
|
168 | 150 |
|
169 |
int cur_robot_x = robot_x; |
|
170 |
int cur_robot_y = robot_y; |
|
151 |
// v is the velocity vector (wehere we just went) |
|
152 |
int v_x = robot_x - last_x; |
|
153 |
int v_y = robot_y - last_y; |
|
154 |
|
|
155 |
if (abs(v_x) < 2 && abs(v_x) < 2) { |
|
156 |
// if we didn't move since the last check, just go forward. |
|
157 |
motor1_set(0, 240); |
|
158 |
motor2_set(0, 240); |
|
159 |
} else { |
|
160 |
// move according to algortihm |
|
161 |
int e_mag = e_x*e_x + e_y*e_y; |
|
162 |
int motor_differential = e_mag >> 7; // 128; |
|
171 | 163 |
|
172 |
//usb_puts("after cur_robot_x/y = robot_x/y.\n"); |
|
164 |
// p is perpendicular to v, directed to the "left" of the robot. |
|
165 |
int p_x = v_y; |
|
166 |
int p_y = -v_x; |
|
167 |
int dot_product_pe = p_x * e_x + p_y * e_y; |
|
173 | 168 |
|
174 |
|
|
175 |
int e_x = target_x - cur_robot_x; |
|
176 |
int e_y = target_y - cur_robot_y; |
|
177 |
|
|
178 |
int v_x = cur_robot_x - last_x; |
|
179 |
int v_y = cur_robot_y - last_y; |
|
180 |
|
|
181 |
// sprintf(buf, "vx:%d vy:%d rx:%d ry:%d ex:%d ey:%d\n", v_x, v_y, e_x, e_y, e_x, e_y); |
|
182 |
// usb_puts(buf); |
|
183 |
|
|
184 |
int e_mag = e_x*e_x + e_y*e_y; |
|
185 |
|
|
186 |
int motor_differential = e_mag >> 7;// / 128; |
|
187 |
|
|
188 |
/* |
|
189 |
sprintf(buf, "Current position: %d %d\n", cur_robot_x, cur_robot_y); |
|
190 |
usb_puts(buf); |
|
191 |
|
|
192 |
sprintf(buf, "Target position: %d %d\n", target_x, target_y); |
|
193 |
usb_puts(buf); |
|
194 |
|
|
195 |
float r_x = (float)target_x - cur_robot_x; |
|
196 |
float r_y = (float)target_y - cur_robot_y; |
|
197 |
float r_mag = sqrt_approx(r_x * r_x + r_y * r_y); |
|
198 |
r_x /= r_mag; |
|
199 |
r_y /= r_mag; |
|
200 |
|
|
201 |
float v_x = (float)cur_robot_x - last_x; |
|
202 |
float v_y = robot_y - last_y; |
|
203 |
float v_mag = sqrt_approx(v_x*v_x + v_y*v_y); |
|
204 |
v_x /= v_mag; |
|
205 |
v_y /= v_mag; |
|
206 |
|
|
207 |
float e_x = r_x - v_x; |
|
208 |
float e_y = r_y - v_y; |
|
209 |
float e_mag = sqrt_approx(e_x * e_x + e_y * e_y); |
|
210 |
|
|
211 |
sprintf(buf, "Error: <%f,%f>; mag: %f\n", e_x, e_y, e_mag); |
|
212 |
usb_puts(buf); |
|
213 |
|
|
214 |
// Motor differential proportional to magnitude of directional error. |
|
215 |
// int motor_differential = (int)(e_mag * ERROR_MAG_TO_MOTOR_DIFFENTIAL_CONST); |
|
216 |
*/ |
|
217 |
|
|
218 |
|
|
219 |
int p_x = v_y; |
|
220 |
int p_y = -v_x; |
|
221 |
|
|
222 |
int e_trans_x = p_x * e_x + p_y * e_y; |
|
223 |
|
|
224 |
/* |
|
225 |
// Determine left or right by transforming error vector to robot axes |
|
226 |
// Perpendicular |
|
227 |
float p_x = v_y; |
|
228 |
float p_y = -v_x; |
|
229 |
|
|
230 |
// Inverse matrix |
|
231 |
float coeff = 1.0 / (p_x * v_y - v_x * p_y); |
|
232 |
float mat[2][2]; |
|
233 |
mat[0][0] = v_y * coeff; |
|
234 |
mat[0][1] = -v_x * coeff; |
|
235 |
//mat[1][0] = -p_y * coeff; //Not needed for our purposes. |
|
236 |
//mat[1][1] = p_x * coeff; |
|
237 |
|
|
238 |
float e_trans_x = mat[0][0] * e_x + mat[0][1] * e_y; |
|
239 |
//float e_trans_y = mat[1][0] * e_x + mat[1][1] * e_y; //Not needed for our purposes. |
|
240 |
*/ |
|
241 |
|
|
242 |
|
|
243 |
if (e_trans_x < 0) { |
|
244 |
motor_differential = -motor_differential; |
|
169 |
// if the dot product of p and e is negative, we should turn right. otherwise turn left. |
|
170 |
if (dot_product_pe < 0) { |
|
171 |
motor_differential = -motor_differential; |
|
172 |
} |
|
173 |
set_motors_with_differential(motor_differential); |
|
245 | 174 |
} |
246 | 175 |
|
247 |
// sprintf(buf, "motor_diff: %d\n", motor_differential); |
|
248 |
// usb_puts(buf); |
|
249 |
|
|
250 |
last_x = cur_robot_x; |
|
251 |
last_y = cur_robot_y; |
|
252 |
|
|
253 |
set_motors_with_differential(motor_differential); |
|
254 |
|
|
176 |
// once we move, ask for the position again. |
|
255 | 177 |
count = 0; |
256 |
while (!updated_robot_pos_ready) { // ghetto condition variable
|
|
178 |
while (!updated_robot_pos_ready) { |
|
257 | 179 |
wl_do(); |
258 | 180 |
if (count++ == 5000) { // in case the server missed it... |
259 | 181 |
request_abs_position(); |
... | ... | |
262 | 184 |
} |
263 | 185 |
} |
264 | 186 |
|
265 |
// usb_puts("reached destination!\n");
|
|
187 |
// Once this function terminates, the robot be at its destination.
|
|
266 | 188 |
} |
267 | 189 |
|
268 | 190 |
/* Private functions */ |
... | ... | |
332 | 254 |
|
333 | 255 |
case BATTERY: |
334 | 256 |
sprintf((char*)pkt->data, "%d", (int)battery8()); |
335 |
|
|
336 |
usb_puts("battery:"); |
|
337 |
usb_puts((char*)pkt->data); |
|
338 |
usb_puts("\n"); |
|
339 |
|
|
340 | 257 |
// NOTE: wl_send_robot_to_robot_global_packet does not work here! |
341 | 258 |
wl_send_global_packet(COLONET_PACKET_GROUP_ID, 0, (char*)pkt, sizeof(ColonetRobotServerPacket), 0); |
342 | 259 |
break; |
... | ... | |
369 | 286 |
/* break; */ |
370 | 287 |
|
371 | 288 |
case SERVER_REPORT_POSITION_TO_ROBOT: |
289 |
last_x = robot_x; |
|
290 |
last_y = robot_y; |
|
372 | 291 |
robot_x = (unsigned)int_args[0]; |
373 | 292 |
robot_y = (unsigned)int_args[1]; |
374 | 293 |
|
... | ... | |
447 | 366 |
case MOVE: |
448 | 367 |
new_movement_command_received = 1; |
449 | 368 |
/* format for move: left direction, left velocity, right direction, right velocity */ |
450 |
sprintf(buf, "calling motor1 set with: %d, %d\ncalling motor2 set with: %d %d\n", |
|
451 |
args[0], args[1], args[2], args[3]); |
|
369 |
sprintf(buf, "calling move\n"); |
|
452 | 370 |
usb_puts(buf); |
453 | 371 |
motor1_set(args[0], args[1]); |
454 | 372 |
motor2_set(args[2], args[3]); |
trunk/code/projects/colonet/client/Colonet.java | ||
---|---|---|
129 | 129 |
} |
130 | 130 |
|
131 | 131 |
private synchronized void createAndShowGUI () { |
132 |
paintThread = new Thread(this, "PaintThread"); |
|
133 |
paintThread.start(); |
|
132 |
//paintThread = new Thread(this, "PaintThread");
|
|
133 |
//paintThread.start();
|
|
134 | 134 |
|
135 | 135 |
// Webcam |
136 | 136 |
gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); |
Also available in: Unified diff