Revision 1006
Threading issues worked out better... Ready to add motion.
branches/simulator/projects/simulator/simulator/gui/gtk_gui.h | ||
---|---|---|
17 | 17 |
**/ |
18 | 18 |
int gtk_gui_run(int argc, char** argv); |
19 | 19 |
|
20 |
void gui_refresh(void); |
|
21 |
|
branches/simulator/projects/simulator/simulator/gui/gtk_environment_view.c | ||
---|---|---|
342 | 342 |
return FALSE; |
343 | 343 |
} |
344 | 344 |
|
345 |
/*gdk_threads_enter(); |
|
346 |
gtk_widget_queue_draw_area(widget, 0, row, view->width, 1); |
|
347 |
gdk_threads_leave();*/ |
|
345 |
void gtk_environment_view_refresh(GtkWidget* view) |
|
346 |
{ |
|
347 |
gdk_threads_enter(); |
|
348 |
gtk_widget_queue_draw(view); |
|
349 |
gdk_threads_leave(); |
|
350 |
} |
|
348 | 351 |
|
branches/simulator/projects/simulator/simulator/gui/gtk_environment_view.h | ||
---|---|---|
45 | 45 |
GtkWidget* gtk_environment_view_new(void); |
46 | 46 |
GtkType gtk_environment_view_get_type(void); |
47 | 47 |
|
48 |
void gtk_environment_view_refresh(GtkWidget* view); |
|
49 |
|
|
48 | 50 |
#endif |
49 | 51 |
|
branches/simulator/projects/simulator/simulator/gui/gtk_gui.c | ||
---|---|---|
5 | 5 |
#include "gtk_gui.h" |
6 | 6 |
#include "gtk_environment_view.h" |
7 | 7 |
|
8 |
GtkWidget* window; |
|
9 |
GtkWidget* view; |
|
10 |
|
|
8 | 11 |
void destroy_callback(int arg) |
9 | 12 |
{ |
10 | 13 |
gtk_main_quit(); |
... | ... | |
12 | 15 |
|
13 | 16 |
int gtk_gui_run(int argc, char** argv) |
14 | 17 |
{ |
15 |
GtkWidget* window; |
|
16 |
GtkWidget* view; |
|
17 |
|
|
18 |
g_thread_init(NULL); |
|
18 |
//g_thread_init(NULL); |
|
19 | 19 |
gdk_threads_init(); |
20 | 20 |
gdk_threads_enter(); |
21 | 21 |
gtk_init(&argc, &argv); |
... | ... | |
43 | 43 |
return 0; |
44 | 44 |
} |
45 | 45 |
|
46 |
void gui_refresh() |
|
47 |
{ |
|
48 |
gtk_environment_view_refresh(view); |
|
49 |
} |
|
50 |
|
branches/simulator/projects/simulator/simulator/core/main.c | ||
---|---|---|
9 | 9 |
|
10 | 10 |
#include <stdlib.h> |
11 | 11 |
#include <stdio.h> |
12 |
#include <gtk/gtk.h> |
|
13 |
#include <glib.h> |
|
14 |
#include <signal.h> |
|
12 | 15 |
|
13 | 16 |
#include "gtk_gui.h" |
14 | 17 |
#include "robot.h" |
... | ... | |
22 | 25 |
printf("Usage: simulator <robot execetuable>\n"); |
23 | 26 |
exit(-1); |
24 | 27 |
} |
28 |
|
|
25 | 29 |
robot_create(argv[1]); |
26 | 30 |
|
27 |
printf("returned to parent\n"); |
|
28 |
|
|
31 |
sigset_t set; |
|
32 |
//TODO: errors |
|
33 |
sigemptyset(&set); |
|
34 |
sigaddset(&set, SIGCHLD); |
|
35 |
pthread_sigmask(SIG_BLOCK, &set, NULL); |
|
36 |
g_thread_init(NULL); |
|
37 |
gdk_threads_init(); |
|
38 |
g_thread_create(robot_event_loop, NULL, TRUE, NULL); |
|
39 |
|
|
40 |
//TODO: better thread to put this in? |
|
41 |
sigemptyset(&set); |
|
42 |
sigaddset(&set, SIGCHLD); |
|
43 |
pthread_sigmask(SIG_UNBLOCK, &set, NULL); |
|
44 |
|
|
29 | 45 |
gtk_gui_run(argc, argv); |
30 | 46 |
|
31 | 47 |
return 0; |
branches/simulator/projects/simulator/simulator/core/robot.c | ||
---|---|---|
20 | 20 |
#include <sys/types.h> |
21 | 21 |
#include <sys/shm.h> |
22 | 22 |
#include <errno.h> |
23 |
#include <pthread.h> |
|
23 | 24 |
|
24 | 25 |
#include "robot.h" |
26 |
#include "gtk_gui.h" |
|
25 | 27 |
|
26 | 28 |
void sig_chld_handler(int sig); |
27 | 29 |
|
... | ... | |
30 | 32 |
// an expanding array of robots |
31 | 33 |
Robot* robots = NULL; |
32 | 34 |
int robots_size = 0; |
35 |
int num_robots = 0; |
|
33 | 36 |
|
34 | 37 |
int iterator_pos = 0; |
35 | 38 |
|
39 |
// signalled when all robots have run for a bit |
|
40 |
pthread_mutex_t all_finished_mutex; |
|
41 |
pthread_cond_t all_finished_cond; |
|
42 |
int finished = 0; |
|
43 |
|
|
36 | 44 |
int robots_initialize(void) |
37 | 45 |
{ |
38 | 46 |
int i; |
... | ... | |
46 | 54 |
memset(robots, 0, sizeof(Robot) * robots_size); |
47 | 55 |
for (i = 0; i < robots_size; i++) |
48 | 56 |
robots[i].id = -1; |
57 |
|
|
58 |
finished = 0; |
|
59 |
pthread_mutex_init(&all_finished_mutex, NULL); |
|
60 |
pthread_cond_init(&all_finished_cond, NULL); |
|
49 | 61 |
|
50 | 62 |
return 0; |
51 | 63 |
} |
... | ... | |
59 | 71 |
int pid; |
60 | 72 |
int id = first_available_id; |
61 | 73 |
Robot* r = &robots[id]; |
74 |
printf("ID: %d\n", id); |
|
62 | 75 |
// do shared memory stuff here |
63 | 76 |
key_t key = IPC_PRIVATE; |
64 | 77 |
//Memory accessible only to children with r/w privileges |
... | ... | |
120 | 133 |
do { |
121 | 134 |
first_available_id++; |
122 | 135 |
} while (first_available_id < robots_size && |
123 |
robots[first_available_id].id != 0);
|
|
136 |
robots[first_available_id].id != -1);
|
|
124 | 137 |
// resize the array if necessary |
125 | 138 |
if (first_available_id >= robots_size) |
126 | 139 |
{ |
... | ... | |
133 | 146 |
} |
134 | 147 |
} |
135 | 148 |
} |
149 |
|
|
150 |
num_robots++; |
|
136 | 151 |
|
137 | 152 |
return id; |
138 | 153 |
} |
... | ... | |
182 | 197 |
// allocated memory |
183 | 198 |
Robot* robot_iterator_next(void) |
184 | 199 |
{ |
200 |
if (iterator_pos >= robots_size) |
|
201 |
return NULL; |
|
202 |
do iterator_pos++; |
|
185 | 203 |
while (iterator_pos < robots_size && |
186 |
robots[iterator_pos].id == -1) |
|
187 |
iterator_pos++; |
|
204 |
robots[iterator_pos].id == -1); |
|
188 | 205 |
|
189 | 206 |
if (iterator_pos >= robots_size) |
190 | 207 |
return NULL; |
... | ... | |
194 | 211 |
|
195 | 212 |
void sig_chld_handler(int sig) |
196 | 213 |
{ |
197 |
pid_t pid; |
|
198 |
int cstat; |
|
214 |
pthread_mutex_lock(&all_finished_mutex); |
|
215 |
finished++; |
|
216 |
if (finished >= num_robots) |
|
217 |
{ |
|
218 |
pthread_cond_signal(&all_finished_cond); |
|
219 |
} |
|
220 |
pthread_mutex_unlock(&all_finished_mutex); |
|
221 |
} |
|
199 | 222 |
|
200 |
printf("SIGCHLD: parent waiting\n"); |
|
223 |
void* robot_event_loop(void* arg) |
|
224 |
{ |
|
225 |
int i; |
|
226 |
//TODO: errors |
|
201 | 227 |
|
202 |
pid = waitpid(0, &cstat, WUNTRACED); |
|
228 |
while (1) |
|
229 |
{ |
|
230 |
pthread_mutex_lock(&all_finished_mutex); |
|
231 |
// TODO: race condition for adding robots? |
|
232 |
if (finished < num_robots) |
|
233 |
{ |
|
234 |
pthread_cond_wait(&all_finished_cond, &all_finished_mutex); |
|
235 |
} |
|
236 |
finished = 0; |
|
237 |
pthread_mutex_unlock(&all_finished_mutex); |
|
238 |
for (i = 0; i < robots_size; i++) |
|
239 |
{ |
|
240 |
if (robots[i].id == -1) |
|
241 |
continue; |
|
242 |
kill(robots[i].pid, SIGCONT); |
|
243 |
} |
|
203 | 244 |
|
204 |
printf("got %d from %d\n", cstat, pid); |
|
205 |
|
|
206 |
kill(pid, SIGCONT); |
|
245 |
gui_refresh(); |
|
246 |
} |
|
207 | 247 |
} |
208 | 248 |
|
branches/simulator/projects/simulator/simulator/core/motion.c | ||
---|---|---|
1 |
#include <stdio.h> |
|
2 |
#include <math.h> |
|
3 |
|
|
4 |
#include "motion.h" |
|
5 |
|
|
6 |
#define CUTOFF 120 |
|
7 |
#define ABS(x) (x<0?-x:x) |
|
8 |
#define TIME 1 /*sec*/ |
|
9 |
#define ROBOT_WIDTH 131 /*mm*/ |
|
10 |
|
|
11 |
/** move will move a robot from its initial position, (x,y), and theta (in radians) to a new position given speed. |
|
12 |
* (x,y) and theta will be updated by the move function instead of returning a value |
|
13 |
* (x,y) is some kind of absolute position in the "world", let's make (0,0) the top left of the "world" |
|
14 |
* theta will an angle be between 0 - 2*Pi (0 being faces east) |
|
15 |
* speed is between 0 - 255, there is some magical cutoff point before the motors actually starts running |
|
16 |
* move will return 0 if successful |
|
17 |
**/ |
|
18 |
int move (int *x, int *y, double *theta, int speed1, int speed2) { |
|
19 |
if (*theta < 0 || *theta > 2*M_PI) return 1; |
|
20 |
if (speed1 < 0 || speed1 > 255) return 1; |
|
21 |
if (speed2 < 0 || speed2 > 255) return 1; |
|
22 |
|
|
23 |
/* if speed is lower than the cut off, don't move */ |
|
24 |
if (ABS(speed1) < CUTOFF) { |
|
25 |
speed1 = 0; |
|
26 |
} |
|
27 |
if (ABS(speed2) < CUTOFF) { |
|
28 |
speed2 = 0; |
|
29 |
} |
|
30 |
double radius; |
|
31 |
if (speed1 == speed2) { |
|
32 |
/* go straight */ |
|
33 |
*x += cos(*theta) * speed1; |
|
34 |
*y += sin(*theta) * speed1; |
|
35 |
return 0; |
|
36 |
} |
|
37 |
radius = ROBOT_WIDTH * speed1 / (speed1 - speed2); |
|
38 |
|
|
39 |
double t = speed1 / radius; |
|
40 |
|
|
41 |
double newx = radius * sin(t); |
|
42 |
double newy = radius - radius * cos(t); |
|
43 |
|
|
44 |
*x += newx * cos(*theta); |
|
45 |
*y += newx * sin(*theta); |
|
46 |
|
|
47 |
*x += newy * - sin(*theta); |
|
48 |
*y += newy * cos(*theta); |
|
49 |
|
|
50 |
*theta = fmod((t + *theta), (2 * M_PI)); |
|
51 |
if (*theta<0) *theta += 2 * M_PI; |
|
52 |
|
|
53 |
return 0; |
|
54 |
} |
|
55 |
|
branches/simulator/projects/simulator/simulator/core/robot.h | ||
---|---|---|
38 | 38 |
void robot_iterator_reset(void); |
39 | 39 |
Robot* robot_iterator_next(void); |
40 | 40 |
|
41 |
void* robot_event_loop(void* arg); |
|
42 |
|
|
41 | 43 |
#endif |
42 | 44 |
|
branches/simulator/projects/simulator/simulator/Makefile | ||
---|---|---|
16 | 16 |
|
17 | 17 |
INCLUDES = -I$(COMMON_DIR) -I$(CORE_DIR) -I$(GUI_DIR) |
18 | 18 |
|
19 |
CFLAGS = -Wall |
|
19 |
CFLAGS = -Wall -g
|
|
20 | 20 |
CFLAGS += $(INCLUDES) |
21 | 21 |
CFLAGS += `pkg-config --cflags gtk+-2.0 gthread-2.0` |
22 | 22 |
|
Also available in: Unified diff