this version 10/17

Dependencies:   mbed

Fork of linearMirrorMotion by Alvaro Cassinelli

Committer:
hiromasaoku
Date:
Fri Apr 05 08:21:46 2013 +0000
Revision:
14:314b86828ed2
Parent:
13:26263959903b
Child:
15:1d931a305464
better (but i understand it should be reverse the procedure of rotation and shearing ...

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbedalvaro 0:4e12dea53fbe 1 #include "mbed.h"
mbedalvaro 1:daf6b4939120 2 #include "laserProjectorHardware.h"
hiromasaoku 4:e00e709d7173 3 #include <vector>
hiromasaoku 7:64b313c58420 4 #define PI 3.141592
hiromasaoku 7:64b313c58420 5
hiromasaoku 11:8a0fecc86705 6 InterruptIn clockEncoderPin(p14);
hiromasaoku 11:8a0fecc86705 7 DigitalIn directionPin(p15);
mbedalvaro 0:4e12dea53fbe 8
mbedalvaro 0:4e12dea53fbe 9 void processSerial();
hiromasaoku 10:a3dd8ec4be60 10 Timer timer_v;
hiromasaoku 4:e00e709d7173 11 LocalFileSystem local("local");
hiromasaoku 5:e02cd57242c7 12 //Serial pc(USBTX, USBRX);
mbedalvaro 0:4e12dea53fbe 13
hiromasaoku 10:a3dd8ec4be60 14 unsigned int X, Y, T;
hiromasaoku 5:e02cd57242c7 15 unsigned int beforeX , beforeY;
hiromasaoku 4:e00e709d7173 16 int startX = CENTER_AD_MIRROR_X;
hiromasaoku 4:e00e709d7173 17 int startY = CENTER_AD_MIRROR_Y;
hiromasaoku 4:e00e709d7173 18
hiromasaoku 6:a82917b3b1aa 19 float sint=0, cost=1;
hiromasaoku 6:a82917b3b1aa 20
hiromasaoku 10:a3dd8ec4be60 21 float vx = 0, vy=0;
hiromasaoku 14:314b86828ed2 22 float theta=0, dt_betWords=50000, st=1800;
hiromasaoku 10:a3dd8ec4be60 23 unsigned int dt=500, ticktime=600;
hiromasaoku 4:e00e709d7173 24
mbedalvaro 0:4e12dea53fbe 25 bool newPositionReady=false;
mbedalvaro 0:4e12dea53fbe 26 unsigned int counter=0;
hiromasaoku 5:e02cd57242c7 27 vector<char> inputletters;
mbedalvaro 0:4e12dea53fbe 28
hiromasaoku 6:a82917b3b1aa 29 bool start=false;
hiromasaoku 6:a82917b3b1aa 30
hiromasaoku 12:d945fb6d4988 31 struct point2dl {
hiromasaoku 4:e00e709d7173 32 int x,y;
hiromasaoku 9:4db47b8eb750 33 int laserSwitch; // laser {1: on 0:off} until next step
hiromasaoku 4:e00e709d7173 34 };
hiromasaoku 12:d945fb6d4988 35
hiromasaoku 14:314b86828ed2 36 point2dl shearing(point2dl dataBefore, float velocity){
hiromasaoku 12:d945fb6d4988 37 point2dl dataAfter;
hiromasaoku 14:314b86828ed2 38 dataAfter.x = dataBefore.x + velocity*timer_v.read_us()/st/1000; //st is a parameter for ajustment
hiromasaoku 13:26263959903b 39 dataAfter.y = dataBefore.y;
hiromasaoku 12:d945fb6d4988 40 dataAfter.laserSwitch = dataBefore.laserSwitch;
hiromasaoku 12:d945fb6d4988 41
hiromasaoku 12:d945fb6d4988 42 return dataAfter;
hiromasaoku 12:d945fb6d4988 43 }
hiromasaoku 12:d945fb6d4988 44
hiromasaoku 12:d945fb6d4988 45 point2dl rotation(point2dl dataBefore, float theta){
hiromasaoku 12:d945fb6d4988 46 sint = sin(theta);
hiromasaoku 12:d945fb6d4988 47 cost = cos(theta);
hiromasaoku 12:d945fb6d4988 48 point2dl dataAfter;
hiromasaoku 12:d945fb6d4988 49 dataAfter.x = sint*dataBefore.x + cost*dataBefore.y;
hiromasaoku 12:d945fb6d4988 50 dataAfter.y = -cost*dataBefore.x + sint*dataBefore.y;
hiromasaoku 12:d945fb6d4988 51 dataAfter.laserSwitch = dataBefore.laserSwitch;
hiromasaoku 12:d945fb6d4988 52
hiromasaoku 12:d945fb6d4988 53 return dataAfter;
hiromasaoku 12:d945fb6d4988 54 }
hiromasaoku 12:d945fb6d4988 55
hiromasaoku 5:e02cd57242c7 56 struct letter {
hiromasaoku 4:e00e709d7173 57 int pointnum;
hiromasaoku 12:d945fb6d4988 58 vector<point2dl> letpoints;
hiromasaoku 4:e00e709d7173 59 };
hiromasaoku 4:e00e709d7173 60
hiromasaoku 5:e02cd57242c7 61 vector<letter> libletter; // letter library
hiromasaoku 5:e02cd57242c7 62
hiromasaoku 11:8a0fecc86705 63 ////for culculate rotary velocit800000000y --------------------------------------------------------
hiromasaoku 4:e00e709d7173 64
hiromasaoku 10:a3dd8ec4be60 65 volatile float angleIncrement = 2.0*PI / 128; // when in Sign/Magnitude mode
hiromasaoku 13:26263959903b 66 float radious = 700, attachSecond = 500;
hiromasaoku 4:e00e709d7173 67
hiromasaoku 10:a3dd8ec4be60 68 // a ticker function to compute the speed periodically:
hiromasaoku 10:a3dd8ec4be60 69 #define PERIODIC_COMPUTE 10000 // in us
hiromasaoku 10:a3dd8ec4be60 70 volatile float angularSpeed = 0;
hiromasaoku 10:a3dd8ec4be60 71 volatile float angle=0, oldAngle=0;
hiromasaoku 10:a3dd8ec4be60 72 Ticker speedTimerCompute;
hiromasaoku 11:8a0fecc86705 73 Ticker superEncoder;
hiromasaoku 5:e02cd57242c7 74
hiromasaoku 10:a3dd8ec4be60 75 // the external interrupt routine:
hiromasaoku 10:a3dd8ec4be60 76 void encoderClock() {
hiromasaoku 10:a3dd8ec4be60 77 if (directionPin) angle += angleIncrement ; else angle -= angleIncrement;
hiromasaoku 7:64b313c58420 78 }
hiromasaoku 7:64b313c58420 79
hiromasaoku 10:a3dd8ec4be60 80 void computeSpeed() {
hiromasaoku 10:a3dd8ec4be60 81 // We know exactly how much time passed since we last computed the speed, this is PERIODIC_COMPUTE in microseconds
hiromasaoku 14:314b86828ed2 82 angularSpeed = 1000000.0 * (float)(angle-oldAngle) / (float)(PERIODIC_COMPUTE); // in rad/sec
hiromasaoku 10:a3dd8ec4be60 83 oldAngle=angle;
hiromasaoku 10:a3dd8ec4be60 84 }
hiromasaoku 10:a3dd8ec4be60 85
hiromasaoku 10:a3dd8ec4be60 86 Timer timer;
hiromasaoku 10:a3dd8ec4be60 87
hiromasaoku 7:64b313c58420 88 int main(){
hiromasaoku 10:a3dd8ec4be60 89 //read from TextFileLibrary ------------------------------------------------------
hiromasaoku 9:4db47b8eb750 90 FILE *fp = fopen("/local/text.txt", "r");
hiromasaoku 5:e02cd57242c7 91 if(!fp) {
hiromasaoku 5:e02cd57242c7 92 IO.setGreenPower(1);
hiromasaoku 5:e02cd57242c7 93 exit(1);
hiromasaoku 9:4db47b8eb750 94 }
hiromasaoku 9:4db47b8eb750 95
hiromasaoku 4:e00e709d7173 96 int letternum;
hiromasaoku 4:e00e709d7173 97 fscanf(fp, "%d", &letternum);
hiromasaoku 5:e02cd57242c7 98 for(int i=0; i<letternum; i++) {
hiromasaoku 5:e02cd57242c7 99 letter bufl;
hiromasaoku 4:e00e709d7173 100 fscanf(fp, "%d", &bufl.pointnum);
hiromasaoku 5:e02cd57242c7 101 for(int j=0; j<bufl.pointnum; j++) {
hiromasaoku 12:d945fb6d4988 102 point2dl bufp;
hiromasaoku 4:e00e709d7173 103 fscanf(fp, "%d", &bufp.x);
hiromasaoku 4:e00e709d7173 104 fscanf(fp, "%d", &bufp.y);
hiromasaoku 9:4db47b8eb750 105 fscanf(fp, "%d", &bufp.laserSwitch);
hiromasaoku 4:e00e709d7173 106 bufl.letpoints.push_back(bufp);
hiromasaoku 4:e00e709d7173 107 }
hiromasaoku 5:e02cd57242c7 108 libletter.push_back(bufl);
hiromasaoku 4:e00e709d7173 109 }
hiromasaoku 5:e02cd57242c7 110
hiromasaoku 5:e02cd57242c7 111
mbedalvaro 0:4e12dea53fbe 112 // SETUP: --------------------------------------------------------------------------------------------
mbedalvaro 0:4e12dea53fbe 113 IO.init(); // note: serial speed can be changed by checking in the hardwareIO.cpp initialization
hiromasaoku 4:e00e709d7173 114
hiromasaoku 10:a3dd8ec4be60 115 // initialize the angle (arbitrary origin):
hiromasaoku 10:a3dd8ec4be60 116 oldAngle=angle=0;
hiromasaoku 10:a3dd8ec4be60 117
hiromasaoku 10:a3dd8ec4be60 118 // Attach the external interrupt routine:
hiromasaoku 11:8a0fecc86705 119 //clockEncoderPin.rise(&encoderClock);
hiromasaoku 11:8a0fecc86705 120 //clockEncoderPin.fall(&encoderClock);
hiromasaoku 13:26263959903b 121 superEncoder.attach_us(&encoderClock, attachSecond);
hiromasaoku 10:a3dd8ec4be60 122 timer.reset(); timer.start();
hiromasaoku 10:a3dd8ec4be60 123
hiromasaoku 10:a3dd8ec4be60 124 // Attach the periodic computing function:
hiromasaoku 10:a3dd8ec4be60 125 speedTimerCompute.attach_us(&computeSpeed, PERIODIC_COMPUTE);
hiromasaoku 10:a3dd8ec4be60 126
hiromasaoku 4:e00e709d7173 127 // Set displaying laser powers:
mbedalvaro 0:4e12dea53fbe 128 IO.setRedPower(0);
hiromasaoku 9:4db47b8eb750 129 IO.setGreenPower(0);
mbedalvaro 0:4e12dea53fbe 130 wait_ms(100);
mbedalvaro 0:4e12dea53fbe 131
hiromasaoku 5:e02cd57242c7 132 X = beforeX = CENTER_AD_MIRROR_X;
hiromasaoku 5:e02cd57242c7 133 Y = beforeY = CENTER_AD_MIRROR_Y;
hiromasaoku 10:a3dd8ec4be60 134 timer_v.start();
mbedalvaro 0:4e12dea53fbe 135 // MAIN LOOP: --------------------------------------------------------------------------------------------
mbedalvaro 0:4e12dea53fbe 136 while(1) {
hiromasaoku 6:a82917b3b1aa 137 if (pc.readable()>0) processSerial();
hiromasaoku 6:a82917b3b1aa 138
hiromasaoku 11:8a0fecc86705 139 if(1/*start*/) {
hiromasaoku 10:a3dd8ec4be60 140
hiromasaoku 10:a3dd8ec4be60 141 timer_v.reset();
hiromasaoku 6:a82917b3b1aa 142 wait_us(5000);
hiromasaoku 10:a3dd8ec4be60 143 // send the speed on the serial port every 30 ms:
hiromasaoku 11:8a0fecc86705 144 if (timer.read_ms()>30) {
hiromasaoku 10:a3dd8ec4be60 145 pc.printf("Angular Speed = %4.2f\t Cumulative Angle = %4.2f\n" , angularSpeed, angle);
hiromasaoku 10:a3dd8ec4be60 146 timer.reset();
hiromasaoku 11:8a0fecc86705 147 }
hiromasaoku 10:a3dd8ec4be60 148
hiromasaoku 10:a3dd8ec4be60 149
hiromasaoku 10:a3dd8ec4be60 150 // drawing ///-----------------------------------------------
hiromasaoku 5:e02cd57242c7 151 for(int i=0; i<inputletters.size(); i++) {
hiromasaoku 9:4db47b8eb750 152
hiromasaoku 9:4db47b8eb750 153 for(int j=0; j<libletter[inputletters[i]-'a'].letpoints.size(); j++) {
hiromasaoku 6:a82917b3b1aa 154
hiromasaoku 6:a82917b3b1aa 155 if (pc.readable()>0) processSerial();
hiromasaoku 6:a82917b3b1aa 156
hiromasaoku 14:314b86828ed2 157 point2dl sheared = shearing(libletter[inputletters[i]-'a'].letpoints[j] , radious*angularSpeed );
hiromasaoku 14:314b86828ed2 158 point2dl rotated = rotation(sheared, angle);
hiromasaoku 14:314b86828ed2 159 X = CENTER_AD_MIRROR_X + radious * cost;
hiromasaoku 14:314b86828ed2 160 Y = CENTER_AD_MIRROR_Y + radious * sint;
hiromasaoku 12:d945fb6d4988 161 IO.writeOutXY(X + rotated.x,Y + rotated.y );
hiromasaoku 12:d945fb6d4988 162
hiromasaoku 12:d945fb6d4988 163 /*
hiromasaoku 12:d945fb6d4988 164 int x = -0.8*((libletter[inputletters[i]-'a'].letpoints[j].x ) - radious*angularSpeed*timer_v.read_us()/st/1000); //this ZURE should be modifyed not by dt but Timer.
hiromasaoku 6:a82917b3b1aa 165 int y = (libletter[inputletters[i]-'a'].letpoints[j].y);
hiromasaoku 11:8a0fecc86705 166 IO.writeOutXY(X + radious*cost + sint*x + cost*y,Y + radious*sint - cost*x + sint*y);
hiromasaoku 12:d945fb6d4988 167 */
hiromasaoku 12:d945fb6d4988 168
hiromasaoku 5:e02cd57242c7 169 wait_us(dt);
hiromasaoku 9:4db47b8eb750 170 IO.setRedPower(libletter[inputletters[i]-'a'].letpoints[j].laserSwitch);//on
hiromasaoku 5:e02cd57242c7 171 }
hiromasaoku 12:d945fb6d4988 172 timer_v.reset();
hiromasaoku 9:4db47b8eb750 173 IO.setRedPower(0); //off
hiromasaoku 13:26263959903b 174 wait_us(dt_betWords);//sqrtf(vx*vx+vy*vy)*100000);
hiromasaoku 6:a82917b3b1aa 175
hiromasaoku 5:e02cd57242c7 176 }
hiromasaoku 10:a3dd8ec4be60 177 ////////////////
hiromasaoku 6:a82917b3b1aa 178 IO.setRGBPower(1); //off
hiromasaoku 6:a82917b3b1aa 179 wait_us(10000);
hiromasaoku 6:a82917b3b1aa 180 start=false;
hiromasaoku 11:8a0fecc86705 181 ////////////////////*/
hiromasaoku 6:a82917b3b1aa 182 }
hiromasaoku 6:a82917b3b1aa 183
hiromasaoku 10:a3dd8ec4be60 184
hiromasaoku 4:e00e709d7173 185
mbedalvaro 0:4e12dea53fbe 186 }
mbedalvaro 0:4e12dea53fbe 187 }
mbedalvaro 0:4e12dea53fbe 188
hiromasaoku 4:e00e709d7173 189
mbedalvaro 0:4e12dea53fbe 190 // --------------------------------------------------------------------------------------------
hiromasaoku 4:e00e709d7173 191 // String to store ALPHANUMERIC DATA (i.e., integers, floating point numbers, unsigned ints, etc represented as DEC) sent wirelessly:
mbedalvaro 0:4e12dea53fbe 192 char stringData[24]; // note: an integer is two bytes long, represented with a maximum of 5 digits, but we may send floats or unsigned int...
mbedalvaro 0:4e12dea53fbe 193 int indexStringData=0;//position of the byte in the string
mbedalvaro 0:4e12dea53fbe 194
hiromasaoku 4:e00e709d7173 195 void processSerial()
hiromasaoku 4:e00e709d7173 196 {
hiromasaoku 4:e00e709d7173 197
hiromasaoku 6:a82917b3b1aa 198 start=true;
hiromasaoku 4:e00e709d7173 199 while(pc.readable()>0) {
hiromasaoku 4:e00e709d7173 200
hiromasaoku 4:e00e709d7173 201 char val =pc.getc();
hiromasaoku 4:e00e709d7173 202
hiromasaoku 4:e00e709d7173 203 // Save ASCII numeric characters (ASCII 0 - 9) on stringData:
hiromasaoku 4:e00e709d7173 204 if ((val >= '0') && (val <= '9')) { // this is 45 to 57 (included)
hiromasaoku 4:e00e709d7173 205 stringData[indexStringData] = val;
hiromasaoku 4:e00e709d7173 206 indexStringData++;
hiromasaoku 5:e02cd57242c7 207 } else if ((val >= 'a') && (val <= 'z')) { // this is 45 to 57 (included)
hiromasaoku 5:e02cd57242c7 208 inputletters.push_back(val);
hiromasaoku 5:e02cd57242c7 209 }
hiromasaoku 5:e02cd57242c7 210
hiromasaoku 5:e02cd57242c7 211 /*else if (val == '/') {
hiromasaoku 5:e02cd57242c7 212 makeBuffer();
hiromasaoku 5:e02cd57242c7 213 }*/ else if (val == '.') {
hiromasaoku 5:e02cd57242c7 214 inputletters.clear();
hiromasaoku 4:e00e709d7173 215 }
mbedalvaro 0:4e12dea53fbe 216
hiromasaoku 4:e00e709d7173 217 else if (val == 'X') {
hiromasaoku 5:e02cd57242c7 218 beforeX = X;
hiromasaoku 4:e00e709d7173 219 stringData[indexStringData] = 0;
hiromasaoku 5:e02cd57242c7 220 X = atoi(stringData);
hiromasaoku 4:e00e709d7173 221 indexStringData=0;
hiromasaoku 10:a3dd8ec4be60 222 vx = ((float)X-(float)beforeX) / (float)timer_v.read_us() *1000;
hiromasaoku 4:e00e709d7173 223 }
hiromasaoku 4:e00e709d7173 224
hiromasaoku 4:e00e709d7173 225 else if (val == 'Y') {
hiromasaoku 5:e02cd57242c7 226 beforeY = Y;
hiromasaoku 4:e00e709d7173 227 stringData[indexStringData] = 0;
hiromasaoku 5:e02cd57242c7 228 Y = atoi(stringData);
hiromasaoku 4:e00e709d7173 229 indexStringData=0;
hiromasaoku 10:a3dd8ec4be60 230 //timer_v.stop();
hiromasaoku 4:e00e709d7173 231 //newSpeedReady = true;
hiromasaoku 6:a82917b3b1aa 232 //if( (Y-beforeY) > 5){
hiromasaoku 10:a3dd8ec4be60 233 vy = ((float)Y-(float)beforeY) / (float)timer_v.read_us() *1000;
hiromasaoku 10:a3dd8ec4be60 234 //theta=atan2(vy,vx);
hiromasaoku 10:a3dd8ec4be60 235 //sint = -sin(theta);//cos(theta);
hiromasaoku 10:a3dd8ec4be60 236 //cost = -cos(theta);//-sin(theta);
hiromasaoku 6:a82917b3b1aa 237 //}
hiromasaoku 6:a82917b3b1aa 238 //if (cost > 0){
hiromasaoku 6:a82917b3b1aa 239 //sint = -sint;//cos(thet
hiromasaoku 6:a82917b3b1aa 240 //cost = -cost;//-sin(theta);
hiromasaoku 6:a82917b3b1aa 241 //}
hiromasaoku 4:e00e709d7173 242 }
mbedalvaro 2:0548c7bf9fba 243
hiromasaoku 7:64b313c58420 244 else if (val == 'D') {
hiromasaoku 4:e00e709d7173 245 stringData[indexStringData] = 0;
hiromasaoku 4:e00e709d7173 246 dt = atoi(stringData);
hiromasaoku 4:e00e709d7173 247 indexStringData=0;
hiromasaoku 5:e02cd57242c7 248 //makeBuffer();
hiromasaoku 7:64b313c58420 249 } else if (val == 'B') {
hiromasaoku 7:64b313c58420 250 stringData[indexStringData] = 0;
hiromasaoku 13:26263959903b 251 dt_betWords = atoi(stringData);
hiromasaoku 7:64b313c58420 252 indexStringData=0;
hiromasaoku 7:64b313c58420 253 //makeBuffer();
hiromasaoku 5:e02cd57242c7 254 } else if (val == 'S') {
hiromasaoku 4:e00e709d7173 255 stringData[indexStringData] = 0;
hiromasaoku 7:64b313c58420 256 st = atoi(stringData);
hiromasaoku 7:64b313c58420 257 indexStringData=0;
hiromasaoku 7:64b313c58420 258 //makeBuffer();
hiromasaoku 7:64b313c58420 259 }else if (val == 'R') {
hiromasaoku 7:64b313c58420 260 stringData[indexStringData] = 0;
hiromasaoku 7:64b313c58420 261 radious = atoi(stringData);
hiromasaoku 7:64b313c58420 262 indexStringData=0;
hiromasaoku 7:64b313c58420 263 //makeBuffer();
hiromasaoku 11:8a0fecc86705 264 }else if (val == 'T') {
hiromasaoku 11:8a0fecc86705 265 stringData[indexStringData] = 0;
hiromasaoku 13:26263959903b 266 attachSecond = atoi(stringData);
hiromasaoku 11:8a0fecc86705 267 indexStringData=0;
hiromasaoku 11:8a0fecc86705 268 //makeBuffer();
hiromasaoku 10:a3dd8ec4be60 269 }
hiromasaoku 4:e00e709d7173 270 // X value?
hiromasaoku 5:e02cd57242c7 271 /*else if (val=='x') {
hiromasaoku 4:e00e709d7173 272 stringData[indexStringData] = 0 ;
hiromasaoku 4:e00e709d7173 273 omegaX=atoi(stringData);
hiromasaoku 4:e00e709d7173 274 indexStringData=0;
hiromasaoku 4:e00e709d7173 275 //newPositionReady=true;
hiromasaoku 4:e00e709d7173 276 }
hiromasaoku 4:e00e709d7173 277 // Y value?
hiromasaoku 4:e00e709d7173 278 else if (val=='y') {
hiromasaoku 4:e00e709d7173 279 stringData[indexStringData] = 0 ;
hiromasaoku 4:e00e709d7173 280 omegaY=atoi(stringData);
hiromasaoku 4:e00e709d7173 281 indexStringData=0;
hiromasaoku 5:e02cd57242c7 282 makeBuffer();
hiromasaoku 4:e00e709d7173 283 newPositionReady=true;
hiromasaoku 4:e00e709d7173 284 }
hiromasaoku 4:e00e709d7173 285
hiromasaoku 4:e00e709d7173 286 else if (val=='g') {
hiromasaoku 4:e00e709d7173 287 stringData[indexStringData] = 0 ;
hiromasaoku 4:e00e709d7173 288 int power=atoi(stringData);
hiromasaoku 4:e00e709d7173 289 indexStringData=0;
hiromasaoku 4:e00e709d7173 290 IO.setGreenPower(power);
hiromasaoku 4:e00e709d7173 291 } else if (val=='r') {
hiromasaoku 4:e00e709d7173 292 stringData[indexStringData] = 0 ;
hiromasaoku 4:e00e709d7173 293 int power=atoi(stringData);
hiromasaoku 4:e00e709d7173 294 indexStringData=0;
hiromasaoku 4:e00e709d7173 295 IO.setRedPower(power);
hiromasaoku 4:e00e709d7173 296 } else if (val=='c') {
hiromasaoku 4:e00e709d7173 297 stringData[indexStringData] = 0 ;
hiromasaoku 4:e00e709d7173 298 int power=atoi(stringData);
hiromasaoku 4:e00e709d7173 299 indexStringData=0;
hiromasaoku 4:e00e709d7173 300 IO.setRGBPower(power);
hiromasaoku 4:e00e709d7173 301 }
hiromasaoku 5:e02cd57242c7 302 */
hiromasaoku 4:e00e709d7173 303
hiromasaoku 6:a82917b3b1aa 304 }
mbedalvaro 0:4e12dea53fbe 305 }