예제 #1
0
 def __init__(self):
     # USBポートを使い、シリアル通信開始
     # 送信用と受信用で2つポートを使う
     self.ev3_recv_serial = serial.Serial('/dev/ttyUSB0', 115200, timeout=10)
     self.ev3_send_serial = serial.Serial('/dev/ttyUSB1', 115200, timeout=10)
     INFO(self.ev3_recv_serial.portstr)
     INFO(self.ev3_send_serial.portstr)
def message_received(client, server, message):
    DEBUG('Message has been received from ' + str(client['address'][0]) + ':' +
          str(client['address'][1]))
    try:
        message_dict = json.loads(message)
        if message_dict['type'] == 'guide_info':
            try:
                with open('./guide_info.json', mode='w') as f:
                    f.write(message)
            except AttributeError:
                INFO('faild to get color data')
    except json.JSONDecodeError:
        INFO('faild to decode message to json')
예제 #3
0
 def calcAndSendMotorPowers(self, shmem, serial):
     while 1:
         # ボール状態取得
         ballState = self.getBallStateByTouch(shmem.isTouched)
         DEBUG('ballState = ', ballState)
         # モータ値計算
         motorPowers = self.calcMotorPowers(ballState, shmem)
         # モーター値後処理(現在は首振り検知処理のみ)
         motorPowers = self.motorControlPostProcessor.escapeSwing(motorPowers)
         # 設定ファイルの内容を反映
         setting = self.getSetting()
         if setting != 'NONE':
             motorPowers = MotorController.DIC_SETTING_TO_MOTOR_VALUE.get(setting)
         # モータ値を正常値にまるめる
         motorPowers = self.roundOffMotorSpeeds(motorPowers)
         # 送信伝文生成
         sendText = str(int(motorPowers[0])) + "," + str(int(motorPowers[1])) + "\n"
         # モータ値送信
         serial.write(sendText)
         # 0.05sごとに実行
         # 本当は全力でぶん回したい
         # ラズパイ側はマルチプロセスを採用しているので問題ないと思うが
         # EV3側は計算資源を通信に占有される恐れがあるためとりあえず0.05sにしておく
         INFO('ball=' + str(ballState).rjust(15),
              'motor=' + str(motorPowers[0]).rjust(4) + ',' + str(motorPowers[1]).rjust(4),
              'IR=' + str(shmem.irAngle).rjust(4),
              'touch=' + str(shmem.isTouched).rjust(4),
              'enemy=' + str(shmem.enemyGoalAngle).rjust(4) + ',' + str(shmem.enemyGoalDis).rjust(4),
              'my=' + str(shmem.myGoalAngle).rjust(4) + ',' + str(shmem.myGoalDis).rjust(4),
              'center=' + str(shmem.fieldCenterAngle).rjust(4) + ',' + str(shmem.fieldCenterDis).rjust(4),
              )
         time.sleep(0.1)
예제 #4
0
    def getParameterSetting(self):
        # パラメータ値設定ファイルを読み込み
        config = ConfigParser.SafeConfigParser()
        config.read(MotorController.PARAMETER_INI_PATH)

        self.DEBUG_SHOOT_ALGORITHM = int(config.get(MotorController.PARAMETER_CUSTOM_SECTION, 'shoot_algo'))
        self.DEBUG_CHASE_ALGORITHM = int(config.get(MotorController.PARAMETER_CUSTOM_SECTION, 'chase_algo'))
        MotorController.SPEED_SHOOT = int(config.get(MotorController.PARAMETER_CUSTOM_SECTION, 'shoot_speed'))
        MotorController.K_SHOOT_ANGLE = float(config.get(MotorController.PARAMETER_CUSTOM_SECTION, 'k_shoot_angle'))
        MotorController.SPEED_CHASE = int(config.get(MotorController.PARAMETER_CUSTOM_SECTION, 'chase_speed'))
        MotorController.K_CHASE_ANGLE = float(config.get(MotorController.PARAMETER_CUSTOM_SECTION, 'k_chase_angle'))
        MotorController.SPEED_GO_CENTER = int(config.get(MotorController.PARAMETER_CUSTOM_SECTION, 'center_speed'))
        MotorController.K_GO_CENTER_ANGLE = float(config.get(MotorController.PARAMETER_CUSTOM_SECTION, 'k_center_angle'))
        INFO('------- motor control parameter read -------')
        INFO('shoot_algo=' + str(self.DEBUG_SHOOT_ALGORITHM).rjust(3) + ',',
                 'chase_algo=' + str(self.DEBUG_CHASE_ALGORITHM).rjust(3) + ',',
                 'shoot=' + str(MotorController.SPEED_SHOOT).rjust(4) + ',' + str(MotorController.K_SHOOT_ANGLE).rjust(4) + ',',
                 'chase=' + str(MotorController.K_CHASE_ANGLE).rjust(4) + ',' + str(MotorController.K_CHASE_ANGLE).rjust(4) + ',',
                 'center=' + str(MotorController.SPEED_GO_CENTER).rjust(4) + ',' + str(MotorController.K_GO_CENTER_ANGLE).rjust(4)
                 )
 def is_going_into_corner(self, wall_size):
     if wall_size == -1:
         self._is_near_wall = False
         return False
     else:
         if self._is_near_wall:
             if time.time() - self._near_wall_start_time > MotorController.TIME_WALL_STUCK:
                 INFO('### going into corner now')
                 return True
             return False
         else:
             DEBUG('### detect near wall start')
             self._near_wall_start_time = time.time()
             self._is_near_wall = True
     return False
 def escape_from_corner(self, shmem):
     shmem.soundPhase = SoundPhaseE.DETECT_PRESS_WALL
     INFO('### escape from corner')
     self.left_motor.drive(-MotorController.SPEED_BACK)
     self.right_motor.drive(-MotorController.SPEED_BACK)
     time.sleep(2)
     if shmem.wallX > 0:
         self.left_motor.drive(-100)
         self.right_motor.drive(100)
     else:
         self.left_motor.drive(100)
         self.right_motor.drive(-100)
     time.sleep(1)
     self.left_motor.drive(MotorController.SPEED_CHASE)
     self.right_motor.drive(MotorController.SPEED_CHASE)
     time.sleep(3)
예제 #7
0
 def update_loop(self, shmem):
     while 1:
         # どうやら10-20秒くらいで補正値を更新しないと、ドリフトの影響が無視出来なくなる
         # リスタート準備中フラグが立っていたら、他のモジュールが待っていてくれているので、補正値の調整をする
         # 補正が終わったらフラグをクリアして、他のモジュールに調整完了を知らせる
         if shmem.preparingRestart:
             INFO('calibrate IMU to prepare restart')
             self.calibrate()
             shmem.preparingRestart = False
         gyro = self._mpu9250.readGyro()
         self._degree += gyro["z"] - self._epsilon
         # 画像認識は右側正、左側負なので、そちらの挙動と合わせるために符号反転させる
         shmem.bodyAngle = -int(
             self.calc_shortcut_degree(self._degree, self.ONE_ROUND_VALUE))
         DEBUG('bodyAngle = ', shmem.bodyAngle)
         time.sleep(self._update_interval_sec)
예제 #8
0
 def setEnemyGoalColorFromFile(self):
     # ゴールモード設定ファイルを読み込み
     try:
         with open('/home/pi/Desktop/raspi_FcTronto/webiopi/goal_mode.txt'
                   ) as f:
             self.goal_mode = f.read()
     # ファイル読み込み失敗
     except:
         WARN('goal mode file read failure')
     # 前回読み込み時から変更があれば設定
     if self.goal_mode != self.pre_goal_mode:
         if self.goal_mode == 'yellow':
             self.enemy_goal_color = EnemyGoalColorE.YELLOW
         elif self.goal_mode == 'blue':
             self.enemy_goal_color = EnemyGoalColorE.BLUE
         else:
             WARN('invalid goal mode')
         INFO('goal_mode changed:', self.pre_goal_mode, '->',
              self.goal_mode)
     # ゴールモードを記憶
     self.pre_goal_mode = self.goal_mode
 def __escape_press_wall(self, motorPowers, bodyAngle):
     # すでにバック中の場合
     if self._pw_enable_force_back:
         if (time.time() - self._pw_start_back_time) > self._pw_back_time:
             DEBUG('### END back for escape press wall')
             self._pw_enable_force_back = False
             # 壁押し付け状態判定用変数初期化
             self._pw_error_count_now = 0
         TRACE('### CONTINUE back for escape press wall')
         return -self._pw_speed, -self._pw_speed
     # 旋回しようとしているかどうか
     # TODO: このパラメータも上位側で指定可能にする
     if abs(self._pw_pre_power[0] - self._pw_pre_power[1]) > 50 and abs(self._pw_pre_body_angle - bodyAngle) < self._pw_diff_angle:
         DEBUG('### pressing wall count +1')
         self._pw_error_count_now += 1
     else:
         self._pw_error_count_now = 0
     if self._pw_error_count_now >= self._pw_error_count_limit:
         INFO('### detect pressing wall count')
         self._pw_enable_force_back = True
         self._pw_start_back_time = time.time()
         # 別にこの時はバックしなくてもいいかもしれないが一応
         return -self._pw_speed, -self._pw_speed
     return motorPowers
 def calcAndSendMotorPowers(self, shmem):
     self.chaseBallMode.set_mode(ChaseMode.NORMAL)
     while 1:
         if self.motion_status == MotionStateE.CHASE_BALL:
             # ボール捕獲に移る
             if 100 < shmem.ballDis < 160 and -20 < shmem.ballAngle < 20:
                 INFO('capture ball')
                 self.left_motor.drive(0)
                 self.right_motor.drive(0)
                 self.servo.down()
                 time.sleep(1)
                 self.motion_status = MotionStateE.GO_TO_STATION
         elif self.motion_status == MotionStateE.GO_TO_STATION:
             distanceSensorValue = self.distanceSensor.read()
             DEBUG('distanceSensor = ' + str(distanceSensorValue))
             # ボール消失してる
             if distanceSensorValue > MotorController.DISTANCE_HAVE_BALL:
                 INFO('lost ball')
                 self.left_motor.drive(0)
                 self.right_motor.drive(0)
                 self.servo.up()
                 # ステーションが見えている場合はステーションにボールを渡せたと判断して再スタートする
                 if shmem.stationDis != -1:
                     shmem.soundPhase = SoundPhaseE.DONE
                     INFO('lost ball -> in station')
                     self.chaseBallMode.set_mode(ChaseMode.NORMAL)
                     self.motion_status = MotionStateE.PREPARE_RESTART
                 self.motion_status = MotionStateE.CHASE_BALL
             # TODO: ステーション到着後の動き
             if 200 < shmem.stationDis < 310:
                 INFO('reached station')
                 self.left_motor.drive(0)
                 self.right_motor.drive(0)
                 self.servo.up()
                 # ステーションに向かっている間に追跡モードがどうなっているか分からないので、通常にリセットしておく
                 shmem.soundPhase = SoundPhaseE.DONE
                 self.chaseBallMode.set_mode(ChaseMode.NORMAL)
                 self.motion_status = MotionStateE.PREPARE_RESTART
         elif self.motion_status == MotionStateE.PREPARE_RESTART:
             INFO('PREPARE RESTART start')
             self.left_motor.drive(0)
             self.right_motor.drive(0)
             shmem.preparingRestart = True
             shmem.soundPhase = SoundPhaseE.PREPARE_RESTART
             while(shmem.preparingRestart):
                 time.sleep(0.1)
             self.prepare_restart(shmem)
             self.chaseBallMode.set_mode(ChaseMode.NORMAL)
             INFO('PREPARE RESTART end -> CHASE BALL')
             self.motion_status = MotionStateE.CHASE_BALL
             continue
                 
         # モータ値計算
         motorPowers = self.calcMotorPowers(shmem, self.motion_status)
         # モーター値後処理(現在は首振り検知処理のみ)
         # motorPowers = self.motorControlPostProcessor.escapeSwing(motorPowers)
         # ステーションに戻るとき隅っこにハマる場合があるので、その時は中央に戻ることを試みる
         if self.motion_status == MotionStateE.GO_TO_STATION and self.is_going_into_corner(shmem.wallSize):
             self.escape_from_corner(shmem)
         motorPowers = self.motorControlPostProcessor.run(motorPowers, shmem.bodyAngle / 10)
         # ボール保持中じゃないのに前方近くに何かあったら後退して回避する
         if self.servo.is_lifting() and self.distanceSensor.read() < MotorController.DISTANCE_STUCK:
             INFO('### detect something barrier')
             motorPowers = (-MotorController.SPEED_BACK, -MotorController.SPEED_BACK)
         # モータ値を正常値にまるめる
         motorPowers = self.roundOffMotorSpeeds(motorPowers)
         # モータ値送信
         self.left_motor.drive(motorPowers[0])
         self.right_motor.drive(motorPowers[1])
         # とりあえず一定時間間隔で動かす
         INFO('motor r=' + str(motorPowers[0]).rjust(4) + ', l=' + str(motorPowers[1]).rjust(4),
              ',ball angle, distance=' + str(shmem.ballAngle).rjust(4) + ',' + str(shmem.ballDis).rjust(4),
              ',station angle, distance=' + str(shmem.stationAngle).rjust(4) + ',' + str(shmem.stationDis).rjust(4),
              ',body angle=' + str(shmem.bodyAngle / 10).rjust(4),
              )
         time.sleep(0.1)
예제 #11
0
def info(title):
    INFO(title)
    INFO('module name:', __name__)
    INFO('parent process:', os.getppid())
    INFO('process id:', os.getpid())
    def imageProcessingFrame(self, frame, shmem):
        # HSV色空間に変換
        hsv_img = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        cv2.line(frame, (self.CAMERA_CENTER_CX, 0),
                 (self.CAMERA_CENTER_CX, 480), (0, 0, 255),
                 thickness=1)
        cv2.line(frame, (0, self.CAMERA_CENTER_CY),
                 (480, self.CAMERA_CENTER_CY), (0, 0, 255),
                 thickness=1)

        # 赤色領域の検知
        red_cx, red_cy, red_area_size, red_convex = self.colorDetect2(
            hsv_img, 'RED')
        if red_cx > -1:
            self.draw_marker(frame, red_cx, red_cy, (255, 30, 30))

        # 黄色領域の検知
        yellow_cx, yellow_cy, yellow_area_size, yellow_convex = self.colorDetect2(
            hsv_img, 'YELLOW')
        if yellow_cx > -1:
            self.draw_marker(frame, yellow_cx, yellow_cy, (30, 255, 255))

        # 青色領域の検知
        blue_cx, blue_cy, blue_area_size, blue_convex = self.colorDetect2(
            hsv_img, 'BLUE')
        if blue_cx > -1:
            self.draw_marker(frame, blue_cx, blue_cy, (30, 30, 255))

        # 緑色領域の検知
        #green_cx, green_cy, green_area_size, green_convex = self.colorDetect2(hsv_img, 'GREEN')
        #if green_cx > -1:
        #    self.draw_marker(frame, green_cx, green_cy, (30, 255, 30))

        # 黒色領域の検知
        black_cx, black_cy, black_area_size, black_convex = self.colorDetect2(
            hsv_img, 'BLACK')
        if black_cx > -1:
            self.draw_marker(frame, black_cx, black_cy, (0, 0, 0))

        INFO('RedSize :' + str(red_area_size).rjust(8))
        INFO('YellowSize :' + str(yellow_area_size).rjust(8))
        INFO('BlueSize :' + str(blue_area_size).rjust(8))
        #INFO('GreenSize :' + str(green_area_size).rjust(8))
        INFO('BlackSize :' + str(black_area_size).rjust(8))

        # 認識できた部分の面積が小さい場合は結果を無視し、distanceに不正な値を入れる
        if red_area_size > blue_area_size and red_area_size > self.IGNORE_AREA_SIZE_BALL:
            DEBUG('use RED area')
            shmem.soundPhase = SoundPhaseE.DETECT_RED_BALL
            ball_angle, ball_distance = self.calcBallDirection(red_cx, red_cy)
        elif blue_area_size > self.IGNORE_AREA_SIZE_BALL:
            DEBUG('use BLUE area')
            shmem.soundPhase = SoundPhaseE.DETECT_BLUE_BALL
            ball_angle, ball_distance = self.calcBallDirection(
                blue_cx, blue_cy)
        #elif yellow_area_size > self.IGNORE_AREA_SIZE_BALL:
        #    DEBUG('use YELLOW area')
        #    shmem.soundPhase = SoundPhaseE.DETECT_YELLOW_BALL
        #    ball_angle, ball_distance = self.calcBallDirection(yellow_cx, yellow_cy)
        else:
            ball_angle = 0
            ball_distance = -1
        #if green_area_size > self.IGNORE_AREA_SIZE_GREEN:
        #    station_angle, station_distance = self.calcBallDirection(green_cx, green_cy)
        if yellow_area_size > self.IGNORE_AREA_SIZE_YELLOW:
            station_angle, station_distance = self.calcBallDirection(
                yellow_cx, yellow_cy)
        else:
            station_angle = 0
            station_distance = -1
        if black_area_size > self.IGNORE_AREA_SIZE_WALL:
            wall_x = black_cx - self.CAMERA_CENTER_CX
            wall_size = black_area_size
        else:
            wall_x = 0
            wall_size = -1

        return ball_angle, ball_distance, station_angle, station_distance, wall_x, wall_size
def new_client(client, server):
    INFO('New client ' + str(client['address'][0]) + ':' +
         str(client['address'][1]) + ' has joined.')
def client_left(client, server):
    INFO('Client ' + str(client['address'][0]) + ':' +
         str(client['address'][1]) + ' has left.')