summaryrefslogtreecommitdiffstats
path: root/source/ct-Bot/map.c
blob: 753941db3ea757066b3f0e35c42ed8fbffc7ca28 (plain)
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
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
/*
 * c't-Bot - Robotersimulator fuer den c't-Bot
 * 
 * This program is free software; you can redistribute it
 * and/or modify it under the terms of the GNU General
 * Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your
 * option) any later version. 
 * This program is distributed in the hope that it will be 
 * useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 * PURPOSE. See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public 
 * License along with this program; if not, write to the Free 
 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307, USA.
 * 
 */

/*! @file 	map.c  
 * @brief 	Karte 
 * @author 	Benjamin Benz (bbe@heise.de)
 * @date 	19.09.06
*/
#include <stdio.h>
#include "ct-Bot.h"
#include "bot-local.h"
#include "sensor_correction.h"
#include "map.h"
#include "mmc.h"
#include "mini-fat.h"
#include "mmc-vm.h"

#ifdef MAP_AVAILABLE
#include <math.h>
#include <stdlib.h>

/*
 * Eine Karte ist wie folgt organisiert:
 * Es gibt Sektionen zu je MAP_SECTION_POINTS * MAP_SECTION_POINTS. 
 * Diese Sektionen enthalten direkt die Pixel-Daten
 * Auf dem PC haelt (noch) ein uebergeordnetes Array haelt die einzelnen Sections 
 * So laesst sich leicht eine Karte aufbauen, 
 * ohne dass viel Platz fuer unbenutzte Felder draufgeht
 * 
 * Auf dem MCU passt eine Sektion in einen Flashblock, bzw immer 2 Sektionen in einen Block
 * Es stehen immer 2 Sections also 1 Flash-Block im SRAM und werden bei Bedarf gewechselt
 * 
 * Felder sind vom Typ int8 und haben einen Wertebereich von -128 bis 127
 * 0 bedeutet: wir wissen nichts über das Feld
 * negative Werte bedeuten: Hinderniss
 * postivie Werte bedeuten: freier Weg
 * je größer der Betrag ist, desto sicherer die Aussage über das Feld
 * Der Wert -128 ist Löchern vorbehalten und wird dann auch nicht durch die Abstandssensoren verändert
 * (Achtung, die Locherkennung ist derzeit noch nicht fertig impelementiert)
 *
 * Felder werden wie folgt aktualisiert:
 * Wird ein Punkt als frei betrachtet, erhoehen wir den Wert des Feldes um MAP_STEP_FREE
 * Wird ein Punkt als belegt erkannt, ziehen wir um ihn einen Streukreis mit dem Radius MAP_RADIUS. 
 * Das Zentrum des Kreises wird um MAP_STEP_OCCUPIED dekrementiert, nach aussen hin immer weniger
 * Wird ein Feld als Loch erkannt, setzen wir den Wert fest auf -128 (Achtung, derzeit noch nicht fertig impelementiert)
 */

#define MAP_SECTIONS ((( MAP_SIZE*MAP_RESOLUTION)/MAP_SECTION_POINTS))

#define MAP_STEP_FREE		2	/*!< Um diesen Wert wird ein Feld inkrementiert, wenn es als frei erkannt wird */
#define MAP_STEP_OCCUPIED	10	/*!< Um diesen Wert wird ein Feld dekrementiert, wenn es als belegt erkannt wird */

#define MAP_RADIUS			10	/*!< Umkreis einen Messpunkt, der als Besetzt aktualisiert wird (Streukreis) [mm]*/
#define MAP_RADIUS_FIELDS	(MAP_RESOLUTION*MAP_RADIUS/1000)	/*!< Umkreis einen Messpunkt, der als Besetzt aktualisiert wird (Streukreis) [Felder]*/

#define MAP_PRINT_SCALE				/*!< Soll das PGM eine Skala erhalten */
#define MAP_SCALE	(MAP_RESOLUTION/2)	/*!< Alle wieviel Punkte kommt wein Skalen-Strich */

#ifdef SHRINK_MAP_ONLINE
	uint16 map_min_x=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: kleinste X-Koordinate */
	uint16 map_max_x=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: groesste X-Koordinate */
	uint16 map_min_y=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: kleinste Y-Koordinate */
	uint16 map_max_y=MAP_SIZE*MAP_RESOLUTION/2; /*!< belegter Bereich der Karte [Kartenindex]: groesste Y-Koordinate  */
#endif

typedef struct {
	int8 section[MAP_SECTION_POINTS][MAP_SECTION_POINTS]; /*!< Einzelne Punkte */
} map_section_t;   /*!< Datentyp fuer die elementarfelder einer Gruppe */


#ifdef MMC_VM_AVAILABLE
	map_section_t * map[2][1];	/*! Array mit den Zeigern auf die Elemente */
	uint32 map_start_block; 	/*! Block, bei dem die Karte auf der MMC-Karte beginnt. Derzeit nur bis 32MByte adressierbar*/
	uint32 map_current_block; 	/*! Block, der aktuell im Puffer steht. Derzeit nur bis 32MByte adressierbar*/
	uint8* map_buffer;			/*! dynamischer Puffer */
#else
	#ifdef MCU
		#ifdef MMC_AVAILABLE
			// Wenn wir die MMC-Karte haben, passen immer 2 Sektionen in den SRAM
			map_section_t * map[2][1];	/*! Array mit den Zeigern auf die Elemente */
			uint32 map_start_block; /*! Block, bei dem die Karte auf der MMC-Karte beginnt. Derzeit nur bis 32MByte adressierbar*/
			uint32 map_current_block; /*! Block, der aktuell im Puffer steht. Derzeit nur bis 32MByte adressierbar*/
			uint8 map_buffer[sizeof(map_section_t)*2]; /*! statischer Puffer */
			uint8 map_current_block_updated; /*! markiert, ob der aktuelle Block gegenueber der MMC-Karte veraendert wurde */
		#else
			// Ohne MMC-Karte nehmen wir nur 1 Sektionen in den SRAM und das wars dann
			map_section_t * map[1][1];	/*! Array mit den Zeigern auf die Elemente */
		#endif
	#else
		map_section_t * map[MAP_SECTIONS][MAP_SECTIONS];	/*! Array mit den Zeigern auf die Elemente */
	#endif
#endif	// MMC_VM_AVAILABLE

/*!
 *  initialisiere die Karte
 * @return 0 wenn alles ok ist
 */
int8 map_init(void){
	#ifndef MMC_VM_AVAILABLE
		#ifdef MMC_AVAILABLE 
			map_start_block=0xFFFFFFFF;
			map_current_block_updated = 0xFF;	// Die MMC-Karte ist erstmal nicht verfuegbar

			if (mmc_get_init_state() != 0) return 1;
			map_start_block= mini_fat_find_block("MAP",map_buffer);
		
			// Die Karte auf den Puffer biegen
			map[0][0]=(map_section_t*)map_buffer;
			map[1][0]=(map_section_t*)(map_buffer+sizeof(map_section_t));		
		
			if (map_start_block != 0xFFFFFFFF){
				map_current_block_updated = False;	// kein Block geladen und daher auch nicht veraendert
				return 1;
			}	
		#endif
	#else
		map_start_block = mmc_fopen("MAP")>>9;	// TODO: Mit Bytes arbeiten und Shiften sparen
		printf("Startaddress of map: 0x%lx \n\r", map_start_block<<9);
		if (map_start_block == 0) return 1;
		map_buffer = mmc_get_data(map_start_block<<9);
		if (map_buffer == NULL) return 1;
		
		// Die Karte auf den Puffer biegen
		map[0][0]=(map_section_t*)map_buffer;
		map[1][0]=(map_section_t*)(map_buffer+sizeof(map_section_t));		
	#endif	// MMC_VM_AVAILABLE	
		
	return 0;
}

/*!
 * liefert einen Zeiger auf die Section zurueck, in der der Punkt liegt.
 * Auf dem MCU kuemmert sie sich darum, die entsprechende Karte aus der MMC-Karte zu laden
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 * @param create Soll das Segment erzeugt werden, falls es noch nicht existiert?
 * @return einen zeiger auf die Karte
 */
map_section_t * map_get_section(uint16 x, uint16 y, uint8 create){
	uint16 section_x, section_y;
		
	// Berechne in welcher Sektion sich der Punkt befindet
	section_x=x/ MAP_SECTION_POINTS;
	section_y=y/ MAP_SECTION_POINTS;
		
	if ((section_x>= MAP_SECTIONS) || (section_y >= MAP_SECTIONS) ||
		(section_x < 0) || (section_y <0)){
		#ifdef PC
			printf("Versuch auf in Feld ausserhalb der Karte zu zugreifen!! x=%d y=%d\n",x,y);
		#endif
		return NULL;
	}

// cut	
	
	#ifndef MMC_VM_AVAILABLE	
		#ifdef MMC_AVAILABLE // Mit MMC-Karte geht hier einiges anders
			// wenn die Karte nicht sauber initialisiert ist, mache nix!
			if (map_current_block_updated == 0xFF)
				return map[0][0];
				
			// Berechne den gesuchten Block
			uint32 block = section_x + section_y*MAP_SECTIONS;
			block = block >>1;	// es passen immer 2 Sections in einen Block
			block += map_start_block;	// Offset drauf
			
			// Ist der Block noch nicht geladen
			if (map_current_block != block){
				// Wurde der Block im RAM veraendert?
				if (map_current_block_updated == True)
					mmc_write_sector(map_current_block,map_buffer,0);
				
				//Lade den neuen Block
				mmc_read_sector(block,map_buffer);
				map_current_block=block;
				map_current_block_updated = False;
			}
			
			// richtige der beiden sections raussuchen
			uint8 index= section_x & 0x01;
			return map[index][0];	
		#else // ohne MMC-Karte einfach direkt mit dem SRAM arbeiten
			if ((map[section_x][section_y] == NULL) && (create==True)){
				uint16 index_x, index_y;
				map[section_x][section_y]= malloc(sizeof(map_section_t));
				for (index_x=0; index_x<MAP_SECTION_POINTS; index_x++)
					for (index_y=0; index_y<MAP_SECTION_POINTS; index_y++)
						map[section_x][section_y]->section[index_x][index_y]=0;
				
			}
			return map[section_x][section_y];
		#endif	// MMC_AVAILABLE
	#else
		// Berechne den gesuchten Block
		uint32 block = section_x + section_y*MAP_SECTIONS;
		block = block >>1;	// es passen immer 2 Sections in einen Block
		block += map_start_block;	// Offset drauf
		map_buffer = mmc_get_data(block<<9);
		if (map_buffer != NULL){
			map[0][0]=(map_section_t*)map_buffer;
			map[1][0]=(map_section_t*)(map_buffer+sizeof(map_section_t));
			// richtige der beiden sections raussuchen
			uint8 index= section_x & 0x01;
			return map[index][0];
		} else return map[0][0];	
	#endif	// MMC_VM_AVAILABLE
}

/*!
 * liefert den Wert eines Feldes 
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 * @return Wert des Feldes (>0 heisst frei, <0 heisst belegt
 */
int8 map_get_field (uint16 x, uint16 y) {
	uint16 index_x, index_y;
	
	// Suche die Section heraus
	map_section_t * section = map_get_section(x,y,False);

	// Eventuell existiert die Section noch nicht
	if (section == NULL)
		return 0;

	// Berechne den Index innerhalb der Section
	index_x = x % MAP_SECTION_POINTS;
	index_y = y % MAP_SECTION_POINTS;

	return section->section[index_x][index_y];	
}

/*!
 * Setzt den Wert eines Feldes auf den angegebenen Wert
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 * @param value neuer wert des Feldes (> 0 heisst frei, <0 heisst belegt
 */
void map_set_field(uint16 x, uint16 y, int8 value) {
	uint16 index_x, index_y;
			
	// Suche die Section heraus
	map_section_t * section = map_get_section(x,y,True);		

	// Wenn wir keine section zurueck kriegen, stimmt was nicht
	if (section == NULL)
		return;

	// Berechne den Index innerhalb der Section
	index_x = x % MAP_SECTION_POINTS;
	index_y =  y % MAP_SECTION_POINTS;
	
	section->section[index_x][index_y]=value;
	
	#ifdef SHRINK_MAP_ONLINE
		// Belegte Kartengroesse anpassen
		if (x < map_min_x)
			map_min_x=x;
		if (x > map_max_x)
			map_max_x= x;
		if (y < map_min_y)
			map_min_y=y;
		if (y > map_max_y)
			map_max_y= y;
	#endif

	#ifdef MMC_AVAILABLE
		#ifndef MMC_VM_AVAILABLE
			if (map_current_block_updated != 0xFF)
				map_current_block_updated = True;
		#endif
	#endif
	
}

/*!
 * liefert den Wert eines Feldes 
 * @param x x-Ordinate der Welt 
 * @param y y-Ordinate der Welt
 * @return Wert des Feldes (>0 heisst frei, <0 heisst belegt
 */
int8 map_get_point (float x, float y){
	//Ort in Kartenkoordinaten
	uint16 X = world_to_map(x);
	uint16 Y = world_to_map(y);
	
	return map_get_field(X,Y);
}

/*!
 * aendert den Wert eines Feldes um den angegebenen Betrag 
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 * @param value Betrag um den das Feld veraendert wird (>= heisst freier, <0 heisst belegter
 */
void map_update_field (uint16 x, uint16 y, int8 value) {

	int16 tmp= map_get_field(x,y);
	if (tmp == -128)	// Nicht aktualiseren, wenn es sich um ein Loch handelt
		return;
			
	tmp+=value;
	
	// pruefen, ob kein ueberlauf stattgefunden hat und das Feld nicht schon als Loch (-128) markiert ist
	if ((tmp < 128) && (tmp > -128))
		map_set_field(x,y,(int8)tmp);
}

/*!
 * markiert ein Feld als frei -- drueckt den Feldwert etwas mehr in Richtung "frei"
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 */
void map_update_free (uint16 x, uint16 y) {
  map_update_field(x,y,MAP_STEP_FREE);
}

/*!
 * aendert den Wert eines Feldes um den angegebenen Betrag 
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 * @param value Betrag um den das Feld veraendert wird (>= heisst freier, <0 heisst belegter
 */
#if MAP_RADIUS_FIELDS > 0
	void map_update_field_circle(uint16 x, uint16 y, int8 radius, int8 value) {
		int16 dX,dY;
	    uint16 h=radius*radius;
		for(dX = -radius; dX <= radius; dX++){
	      for(dY = -radius; dY <= radius; dY++) {
	           if(dX*dX + dY*dY <= h)	 
	           	 map_update_field (x + dX, y + dY,value);
	      }
		}
	}
#endif

/*!
 * markiert ein Feld als belegt -- drueckt den Feldwert etwas mehr in Richtung "belegt"
 * @param x x-Ordinate der Karte (nicht der Welt!!!)
 * @param y y-Ordinate der Karte (nicht der Welt!!!)
 */
void map_update_occupied (uint16 x, uint16 y) {
  // Nur wenn ein Umkreis gewuenscht ist, auch einen malen
  #if MAP_RADIUS_FIELDS > 0
	  uint8 r;
	  for (r=1; r<=MAP_RADIUS_FIELDS; r++){
	  	map_update_field_circle(x,y,r,-MAP_STEP_OCCUPIED/MAP_RADIUS_FIELDS);
	  }
  #else 
  	map_update_field(x,y,-MAP_STEP_OCCUPIED);
  #endif
}

/*!
 * Konvertiert eine Weltkoordinate in eine Kartenkoordinate
 * @param koord Weltkordiante
 * @return kartenkoordinate
 */
uint16 world_to_map(float koord){
	uint16 tmp = koord * MAP_RESOLUTION / 1000  + (MAP_SIZE*MAP_RESOLUTION/2);
		
	return tmp;
}

/*!
 * Konvertiert eine Kartenkoordinate in eine Weltkoordinate
 * @param map_koord kartenkoordinate
 * @return Weltkordiante
 */
float map_to_world(uint16 map_koord){
	float tmp = (map_koord - (MAP_SIZE*MAP_RESOLUTION/2)) / MAP_RESOLUTION * 1000;
			
	return tmp;
}

/*! 
 * Aktualisiert die Karte mit den Daten eines Sensors
 * @param x X-Achse der Position des Sensors
 * @param y Y-Achse der Position des Sensors
 * @param head Blickrichtung im Bogenmaß
 * @param dist Sensorwert 
 */ 
void update_map_sensor(float x, float y, float h, int16 dist){
	//Ort des Sensors in Kartenkoordinaten
	uint16 X = world_to_map(x);
	uint16 Y = world_to_map(y);
	
	uint16 d;
	if (dist==SENS_IR_INFINITE)
		d=SENS_IR_MAX_DIST;
	else 
		d=dist;
		
		
	
	// Hinderniss, dass der Sensor sieht in Weltkoordinaten
	float PH_x = x + (DISTSENSOR_POS_FW + d) * cos(h);
	float PH_y = y + (DISTSENSOR_POS_FW + d) * sin(h);
	// Hinderniss, dass der linke Sensor sieht in Kartenkoordinaten
	uint16 PH_X = world_to_map(PH_x);
	uint16 PH_Y = world_to_map(PH_y);
	
	if ((dist > 80 ) && (dist <SENS_IR_INFINITE))
			map_update_occupied(PH_X,PH_Y);
	


	// Nun markiere alle Felder vor dem Hinderniss als frei
	uint16 i;

	uint16 lX = X; 	//	Beginne mit dem Feld, in dem der Sensor steht
	uint16 lY = Y; 
	
	int8 sX = (PH_X < X ? -1 : 1);  
	uint16 dX=abs(PH_X - X);		// Laenge der Linie in X-Richtung
	
	int8 sY = (PH_Y < Y ? -1 : 1); 
	uint16 dY =abs(PH_Y - Y);	// Laenge der Linie in Y-Richtung

	if (dX >= dY) {			// Hangle Dich an der laengeren Achse entlang
	  dY--;	// stoppe ein Feld vor dem Hinderniss
	  uint16 lh = dX / 2;
	  for (i=0; i<dX; ++i) {
	    map_update_free (lX+i*sX, lY);
	    lh += dY;
	    if (lh >= dX) {
	      lh -= dX;
	      lY += sY;
	    }
	  }
	} else {
	  dX--; // stoppe ein Feld vor dem Hinderniss
	  uint16 lh = dY / 2;
	  for (i=0; i<dY; ++i) {
	    map_update_free (lX, lY+i*sY);
	    lh += dX;
	    if (lh >= dY) {
	      lh -= dY;
	      lX += sX;
	    }
	  }
	}	
}

/*!
 * Aktualisiert den Standkreis der internen Karte
 * @param x X-Achse der Position
 * @param y Y-Achse der Position
 */
void update_map_location(float x, float y){
	int16 x_map = world_to_map(x);
	int16 y_map = world_to_map(y);
	
	// Aktualisiere zuerst die vom Bot selbst belegte Flaeche
	#define dim BOT_DIAMETER/2*MAP_RESOLUTION/100
	int16 dX,dY;
	for(dX = -dim; dX <= dim; dX++)
      for(dY = -dim; dY <= dim; dY++) {
           if(dX*dX + dY*dY <= dim*dim)	 
           	 map_update_free (x_map + dX, y_map + dY);
     }
}

/*!
 * Aktualisiert die interne Karte anhand der Sensordaten
 * @param x X-Achse der Position
 * @param y Y-Achse der Position
 * @param head Blickrichtung in Grad
 * @param distL Sensorwert links
 * @param distR Sensorwert rechts
 */
void update_map(float x, float y, float head, int16 distL, int16 distR){
//	printf("update_map: x=%f, y=%f, head=%f, distL=%d, distR=%d\n",x,y,head,distL,distR);
	
    float h= head * M_PI /180;
	        
    //Ort des rechten Sensors in Weltkoordinaten
    float Pr_x = x + (DISTSENSOR_POS_SW * sin(h));
	float Pr_y = y - (DISTSENSOR_POS_SW * cos(h));

    //Ort des linken Sensors in Weltkoordinaten
    float Pl_x = x - (DISTSENSOR_POS_SW * sin(h));
	float Pl_y = y + (DISTSENSOR_POS_SW * cos(h));

	update_map_sensor(Pl_x,Pl_y,h,distL);
	update_map_sensor(Pr_x,Pr_y,h,distR);
}



#ifdef PC
	/*!
	 * Schreibt einbe Karte in eine PGM-Datei
	 * @param filename Zieldatei
	 */
	void map_to_pgm(char * filename){
		printf("Speichere Karte nach %s\n",filename);
		FILE *fp = fopen(filename, "w");
		
		uint16 x,y;

		// lokale Variablen mit den defaults befuellen
		uint16 min_x=map_min_x;
		uint16 max_x=map_max_x;
		uint16 min_y=map_min_y;
		uint16 max_y=map_max_y;
		
		#ifdef 	SHRINK_MAP_OFFLINE	// nun muessen wir die Grenezn ermitteln
			// Kartengroesse reduzieren
			int8 free=1;
			while ((min_y < max_y) && (free ==1)){
				for (x=min_x; x<max_x; x++){
					if (map_get_field(x,min_y) != 0){
						free=0;
						break;
					}					
				}
				min_y++;
			}
			free=1;
			while ((min_y < max_y) && (free ==1)){
				for (x=min_x; x<max_x; x++){
					if (map_get_field(x,max_y-1) != 0){
						free=0;
						break;
					}					
				}
				max_y--;
			}
			
			free=1;
			while ((min_x < max_x) && (free ==1)){
				for (y=min_y; y<max_y; y++){
					if (map_get_field(min_x,y) != 0){
						free=0;
						break;
					}					
				}
				min_x++;
			}
			free=1;
			while ((min_x < max_x) && (free ==1)){
				for (y=min_y; y<max_y; y++){
					if (map_get_field(max_x-1,y) != 0){
						free=0;
						break;
					}					
				}
				max_x--;
			}
		
		#endif
			
		uint16 map_size_x=max_x-min_x;
		uint16 map_size_y=max_y-min_y;
		#ifdef MAP_PRINT_SCALE
			fprintf(fp,"P5\n%d %d\n255\n",map_size_x+10,map_size_y+10);
		#else
			fprintf(fp,"P5\n%d %d\n255\n",map_size_x,map_size_y);
		#endif
		printf("Karte beginnt bei X=%d,Y=%d und geht bis X=%d,Y=%d (%d * %d Punkte)\n",min_x,min_y,max_x,max_y,map_size_x,map_size_y);
		
		uint8 tmp;
		for (y=max_y; y> min_y; y--){
			for (x=min_x; x<max_x; x++){
				
				tmp=map_get_field(x,y-1)+128;
				fwrite(&tmp,1,1,fp);
			}

			#ifdef MAP_PRINT_SCALE
				// und noch schnell ne Skala basteln
				for (x=0; x<10; x++){
					if (y % MAP_SCALE == 0)
						tmp=0;
					else tmp=255;
					
					fwrite(&tmp,1,1,fp);
				}
			#endif

		}

		#ifdef MAP_PRINT_SCALE
			for (y=0; y< 10; y++){
				for (x=min_x; x<max_x+10; x++){
					if (x % MAP_SCALE == 0)
						tmp=0;
					else tmp=255;
					
					fwrite(&tmp,1,1,fp);
				}
			}
		#endif
		fclose(fp);
		
	}


	/*! Liest eine Map wieder ein 
	 * @param filename Quelldatei
	 */
	void read_map(char * filename){
		printf("Lese Karte (%s) von MMC/SD (Bot-Format)\n",filename);
		FILE *fp = fopen(filename, "r");
		
		uint8 buffer[512];
		fread(buffer,512,1,fp);
		
		if (buffer[0] != 'M' || buffer[1] != 'A' || buffer[2] != 'P'){
			printf("Datei %s enthaelt keine Karte\n",filename);
			return;
		}
		
		uint16 x,y;	
		uint8 * ptr;

		for (y=0; y< MAP_SECTIONS; y++)
			for (x=0; x< MAP_SECTIONS; x++){
				ptr= (uint8*)map_get_section(x*MAP_SECTION_POINTS, y*MAP_SECTION_POINTS, True);
				fread(ptr,MAP_SECTION_POINTS*MAP_SECTION_POINTS,1,fp);
			}
			
		fclose(fp);
		
	}
#endif



/*!
 * Zeigt die Karte an
 */
void print_map(void){
	#ifdef PC
		map_to_pgm("map.pgm");
	#else
		// Todo: Wie soll der Bot eine Karte ausgeben ....
	#endif
}



#endif