Project

General

Profile

Statistics
| Revision:

root / branches / simulator / projects / simulator / simulator / core / robot.c @ 1039

History | View | Annotate | Download (5.43 KB)

1
/**
2
 * @file robot.c
3
 * @author Colony Project
4
 * @brief Simulator Robot Management
5
 *
6
 * Contains implementations of functions managing robots
7
 * in the simulator, including process control and memory
8
 * management.
9
 **/
10

    
11
#include <stdlib.h>
12
#include <stdio.h>
13
#include <string.h>
14

    
15
#include <unistd.h>
16
#include <signal.h>
17
#include <sys/wait.h>
18
#include <robot_shared.h>
19
#include <sys/ipc.h>
20
#include <sys/types.h>
21
#include <sys/shm.h>
22
#include <errno.h>
23
#include <pthread.h>
24
#include <err.h>
25

    
26
#include "robot.h"
27
#include "motion.h"
28
#include "gtk_gui.h"
29

    
30
void sig_chld_handler(int sig);
31
void robot_update(int i);
32

    
33
// global variables
34
int first_available_id = 0;
35
// an expanding array of robots
36
Robot* robots = NULL;
37
int robots_size = 0;
38
int num_robots = 0;
39

    
40
int iterator_pos = 0;
41

    
42
// signalled when all robots have run for a bit
43
pthread_mutex_t all_finished_mutex;
44
pthread_cond_t all_finished_cond;
45
int finished = 0;
46

    
47
int robots_initialize(void)
48
{
49
        int i;
50
        if (signal(SIGCHLD, sig_chld_handler) == SIG_ERR)
51
                return -1;
52

    
53
        robots_size = 10;
54
        robots = (Robot*)malloc(sizeof(Robot) * robots_size);
55
        if (!robots)
56
                return -1;
57
        memset(robots, 0, sizeof(Robot) * robots_size);
58
        for (i = 0; i < robots_size; i++)
59
                robots[i].id = -1;
60
        
61
        finished = 0;
62
        pthread_mutex_init(&all_finished_mutex, NULL);
63
        pthread_cond_init(&all_finished_cond, NULL);
64

    
65
        return 0;
66
}
67

    
68
/**
69
 * Creates a new robot. Returns its id on
70
 * success, or a negative integer on failure.
71
 **/
72
int robot_create(char *execname)
73
{
74
  int pid,i;
75
        int id = first_available_id;
76
        Robot* r = &robots[id];
77
        printf("ID: %d\n", id);
78
        // do shared memory stuff here
79
        key_t key = IPC_PRIVATE;
80
        //Memory accessible only to children with r/w privileges
81
        r->sharedMemID = shmget(key, sizeof(RobotShared), IPC_CREAT | 0666);
82
        
83

    
84
        //hack!! TODO: remove!!
85
        r->pose.x=first_available_id*100;
86
        r->pose.y=first_available_id*50;
87

    
88

    
89
        if(r->sharedMemID < 0)
90
        {
91
                fprintf(stderr, "Failed to get shared memory.\n");
92
                return -1;
93
        }
94

    
95
        r->shared = (RobotShared*)shmat(r->sharedMemID, NULL, 0);
96
        
97
        if(!(r->shared))
98
        {        
99
                //Free shared memory region
100
                if (!shmctl(r->sharedMemID, IPC_RMID, NULL))
101
                        fprintf(stderr, "Failed to free shared memory.\n");
102
                       
103
                fprintf(stderr, "Error attaching memory to parent.\n");
104
                return -1;
105
        }
106
        
107
        // Initialize robot structure here
108
        r->shared->motor1 = 0;
109
        r->shared->motor2 = 0;
110
        r->id = id;
111

    
112
        if((pid = fork()) < 0)
113
        {
114
                //Free Shared Memory Region
115
                if (!shmdt(r->shared))
116
                        fprintf(stderr, "Failed to free shared memory.\n");
117
                
118
                if (!shmctl(r->sharedMemID, IPC_RMID, NULL))
119
                        fprintf(stderr, "Failed to free shared memory.\n");
120

    
121
                r->id = -1;
122
                fprintf(stderr, "Failed to fork robot process.\n");
123
                return -1;
124
        }
125
        
126

    
127
        if(!pid)
128
        {
129
          char var[21];
130
          /* restore default sigchld handler */
131
          signal(SIGCHLD, SIG_DFL);
132
          sprintf(var, "memory_id=%d", r->sharedMemID);
133
          putenv(var);
134
          //TODO: keep the other env. stuff around
135
          execv(execname, NULL);
136
          err(errno, "exec failed to run child process.\n");
137
        }
138
        else
139
        {
140
                r->pid = pid;
141
                do {
142
                        first_available_id++;
143
                } while (first_available_id < robots_size &&
144
                                robots[first_available_id].id != -1);
145
                // resize the array if necessary
146
                if (first_available_id >= robots_size)
147
                {
148
                        robots_size *= 2;
149
                        robots = realloc(robots, sizeof(Robot) * robots_size);
150
                        if (!robots)
151
                        {
152
                                fprintf(stderr, "Out of memory.\n");
153
                                return -1;
154
                        }
155
                        for (i = robots_size=first_available_id; i < robots_size; i++)
156
                          robots[i].id = -1;
157

    
158
                }
159
        }
160

    
161
        num_robots++;
162
        
163
        return id;
164
}
165

    
166
/**
167
 * Frees all resources associated with a robot, including
168
 * killing its process if necessary.
169
 *
170
 * @return zero on success, nonzero on failure
171
 **/
172
int robot_destroy(int id)
173
{
174
        Robot* r;
175

    
176
        if (id < 0 || id >= robots_size)
177
                return -1;
178
        r = &robots[id];
179
        if (r->id == 0)
180
                return -1;
181

    
182
    if (!shmdt(r->shared))
183
        {
184
                fprintf(stderr, "Failed to free shared memory.\n");
185
                return -1;
186
        }
187
        if (!shmctl(r->sharedMemID, IPC_RMID, NULL))
188
        {
189
                fprintf(stderr, "Failed to free shared memory.\n");
190
                return -1;
191
        }
192

    
193
        memset(r, 0, sizeof(Robot));
194
        r->id = -1;
195

    
196
        if (id < first_available_id)
197
                first_available_id = 0;
198
        
199
        return 0;
200
}
201

    
202
void robot_iterator_reset(void)
203
{
204
        iterator_pos = -1;
205
}
206

    
207
// note: addresses may change, replace with
208
// allocated memory
209
Robot* robot_iterator_next(void)
210
{
211
        if (iterator_pos >= robots_size)
212
                return NULL;
213
        do iterator_pos++;
214
        while (iterator_pos < robots_size && 
215
                        robots[iterator_pos].id == -1);
216
        
217
        if (iterator_pos >= robots_size)
218
                return NULL;
219
        
220
        return &(robots[iterator_pos]);
221
}
222

    
223
void sig_chld_handler(int sig)
224
{
225
  int ret,stat;
226

    
227
  pthread_mutex_lock(&all_finished_mutex);
228

    
229
  while((ret = waitpid(-1, &stat, WUNTRACED | WNOHANG)))
230
  {
231
    if(ret==-1)
232
      err(errno,"error waiting on robot");
233

    
234
    if(WIFSTOPPED(stat))
235
      finished++;
236
  }
237

    
238
  if (finished >= num_robots)
239
  {
240
    pthread_cond_signal(&all_finished_cond);
241
  }
242
  pthread_mutex_unlock(&all_finished_mutex);
243
}
244

    
245
void* robot_event_loop(void* arg)
246
{
247
        int i;
248
        //TODO: errors
249

    
250
        while (1)
251
        {
252
                pthread_mutex_lock(&all_finished_mutex);
253
                // TODO: race condition for adding robots?
254
                if (finished < num_robots)
255
                {
256
                        pthread_cond_wait(&all_finished_cond, &all_finished_mutex);
257
                }
258
                finished = 0;
259
                pthread_mutex_unlock(&all_finished_mutex);
260
                for (i = 0; i < robots_size; i++)
261
                        if (robots[i].id != -1)
262
                                robot_update(i);
263
                for (i = 0; i < robots_size; i++)
264
                {
265
                        if (robots[i].id == -1)
266
                                continue;
267
                        kill(robots[i].pid, SIGCONT);
268
                }
269

    
270
                gui_refresh();
271
        }
272
}
273

    
274
void robot_update(int i)
275
{
276
        Robot* r = &(robots[i]);
277
        if (r->id == -1)
278
                return;
279
        move_robot(r);
280
}
281