前提・実現したいこと
Windows10(以降PC)で DUALSHOCK 4 の入力をpygameを使って読み取り、socket通信にてLANケーブルを介して Raspberry Pi 4 Model B(以降ラズパイ) へ DUALSHOCK 4 のデータを送信、そのデータをもとにGPIOへ出力するというのが今回したいことです。
発生している問題
socket通信のUDPにてつい数日前まで通信できていたのですが、これまで作業していた部屋とは違う場所へ行ったところ、ラズパイ側で受信が出来ずに「recv()」関数でプログラムが止まってしまいます。
「recv()」関数でプログラムが止まっていたことはどうやって確認したかと言うと、「print("1")」を「recv()」の直前に書いた場合には表示出来ており、「recv()」の直後に書いた場合では表示されなかったため、「recv()」関数でプログラムが止まっていたと判断しました。
これまでの作業部屋には無線ルーターがあり、無線ネットワークがギリギリ届かない程度離れたら「recv()」関数でプログラムが止まってしまったので、LANケーブルではなく無線ルーターを介してこれまでsocket通信をしていたのではないかと現状では疑っております。
ラズパイ側が受信できない状態でプログラムが止まっているだけなので、エラーメッセージ等はありません。
PC側(socket通信的にクライアント)のソースコード
python3
1import pygame 2from pygame.locals import * 3import socket 4import time 5 6host = "192.168.10.21" 7port = 55555 8sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) 9 10def Constrain( val, min_val, max_val ): 11 if val > max_val: 12 return max_val 13 elif val < min_val: 14 return min_val 15 else: 16 return val 17 18def Map( val, in_min, in_max, out_min, out_max ): 19 temp = ( val - in_min ) * ( out_max - out_min ) / ( in_max - in_min ) + out_min 20 return ( Constrain( temp, out_min, out_max ) ) 21 22def main(): 23 # [LX, LY, RX, RY, L2, R2] 24 stick = [ 0, 0, 0, 0, 0, 0 ] # スティックは(-255 ~ 255), L2とR2は(0 ~ 255) 25 button = 0 # 2進数化してボタン情報を1つの変数にまとめる 26 27 pygame.joystick.init() 28 29 try: 30 j = pygame.joystick.Joystick( 0 ) 31 j.init() 32 print( "ジョイスティックの名前:", j.get_name(), end=" " ) 33 print( "ボタンの数:", j.get_numbuttons(), end=" " ) 34 print( "スティックの数:", j.get_numaxes() ) 35 except pygame.error: 36 print( "ジョイスティックが接続されていません" ) 37 38 pygame.init() 39 40 while True: 41 for e in pygame.event.get(): 42 if e.type == QUIT: 43 return 44 if( e.type == KEYDOWN and 45 e.key == K_ESCAPE ): 46 return 47 48 stick[0] = int( Map( j.get_axis(0), -1.0, 1.0, 0, 127 ) ) 49 stick[1] = int( Map( j.get_axis(1), 1.0, -1.0, 0, 127 ) ) 50 stick[2] = int( Map( j.get_axis(2), -1.0, 1.0, 0, 127 ) ) 51 52 button = 0 53 button |= j.get_button(0) 54 for i in range(1, 4): 55 button <<= 1 56 button |= j.get_button(i) 57 for i in range(9, 15): 58 button <<= 1 59 button |= j.get_button(i) 60 61 print( button, end=" " ) 62 print( stick[0], end=" " ) 63 print( stick[1], end=" " ) 64 print( stick[2], end=" " ) 65 66 message = "%d,%d,%d,%d" % ( button, stick[0], stick[1], stick[2] ) 67 sock.sendto( message.encode( 'utf-8' ), ( host, port ) ) 68 69 time.sleep(0.05) 70 71if __name__ == '__main__': 72 main() 73
ラズパイ側(socket通信的にサーバー)のソースコード
python3
1# -*- coding: utf-8 -*- 2 3import socket 4import time 5 6host = "192.168.10.21" 7port = 55555 8sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) 9sock.bind( ( host, port ) ) 10 11import pigpio 12FREQ = 10000 13dout_pin = [ 24, 25, 8, 7, 13, 5, 6, 11, 9, 10 ] 14dire_pin = [ 4, 17, 14, 15 ] 15pwm_pin = [ 27, 22, 2, 3 ] 16pi = pigpio.pi() 17 18for i in range(0, 10): 19 pi.set_mode( dout_pin[i], pigpio.OUTPUT ) 20 21for i in range(0, 4): 22 pi.set_mode( dire_pin[i], pigpio.OUTPUT ) 23 pi.set_mode( pwm_pin[i], pigpio.OUTPUT ) 24 pi.set_PWM_frequency( pwm_pin[i], FREQ ) 25 26class Static: 27 data = False 28 return_val = False 29 30def Constrain( val, min_val, max_val ): 31 if val > max_val: 32 return max_val 33 elif val < min_val: 34 return min_val 35 else: 36 return val 37 38def Map( val, in_min, in_max, out_min, out_max ): 39 temp = ( val - in_min ) * ( out_max - out_min ) / ( in_max - in_min ) + out_min 40 return ( Constrain( temp, out_min, out_max ) ) 41 42def PushButton(button): 43 if( button == 0 and Static.data == False ): 44 Static.data = False 45 Static.return_val = False 46 elif( button != 0 and Static.data == False ): 47 Static.data = True 48 Static.return_val = True 49 elif( button != 0 and Static.data == True ): 50 Static.data = True 51 Static.return_val = False 52 elif( button == 0 or Static.data == True ): 53 Static.data = False 54 Static.return_val = False 55 return Static.return_val 56 57while True: 58 try: 59 rcv = sock.recv( 31 ) # ここでプログラムが止まる! 60 rcvmsg = rcv.decode( 'utf-8' ) 61 ps4_data = rcvmsg.split( "," ) 62 63 # ボタンのデータに再変換 64 cross = ( int(ps4_data[0]) >> 9 ) & 1 65 circle = ( int(ps4_data[0]) >> 8 ) & 1 66 square = ( int(ps4_data[0]) >> 7 ) & 1 67 triangle = ( int(ps4_data[0]) >> 6 ) & 1 68 L1 = ( int(ps4_data[0]) >> 5 ) & 1 69 R1 = ( int(ps4_data[0]) >> 4 ) & 1 70 up = ( int(ps4_data[0]) >> 3 ) & 1 71 down = ( int(ps4_data[0]) >> 2 ) & 1 72 left = ( int(ps4_data[0]) >> 1 ) & 1 73 right = int(ps4_data[0]) & 1 74 75 delta_dire = False 76 if ( up > 0 or right > 0 ): 77 delta_dire = True 78 else: 79 delta_dire = False 80 81 _right = False 82 _left = False 83 if ( right > 0 ): 84 _right = True 85 if ( left > 0 ): 86 _left = True 87 88 _up = False 89 _down = False 90 if ( up > 0 ): 91 _up = True 92 if ( down > 0 ): 93 _down = True 94 95 pi.write( dout_pin[0], triangle ) 96 pi.write( dout_pin[1], cross ) 97 pi.write( dout_pin[2], R1 ) 98 pi.write( dout_pin[3], _up ) 99 pi.write( dout_pin[4], _down ) 100 pi.write( dout_pin[5], circle ) 101 pi.write( dout_pin[6], square ) 102 pi.write( dout_pin[7], _right ) 103 pi.write( dout_pin[8], _left ) 104 pi.write( dout_pin[9], delta_dire ) 105 106 jacobian = [ [ 1, -1, 1 ], [ 1, 1, 1 ], [ -1, 1, 1 ], [ -1, -1, 1 ] ] 107 robot_vel = [ 0, 0, 0 ] 108 for i in range( 0, 3 ): 109 robot_vel[i] = int( Map( int(ps4_data[i+1]), 0, 127, -255, 255 ) ) 110 111 dead_zone = 0.15 112 for i in range( 0, 3 ): 113 if abs( robot_vel[i] ) < 255 * dead_zone: 114 robot_vel[i] = 0 115 116 wheel_vel = [ 0, 0, 0, 0 ] 117 for i in range( 0, 4 ): 118 wheel_vel[i] += jacobian[i][0] * robot_vel[0] 119 wheel_vel[i] += jacobian[i][1] * robot_vel[1] 120 wheel_vel[i] += jacobian[i][2] * robot_vel[2] 121 122 max_vel = 0 123 for i in range( 0, 4 ): 124 if ( abs( wheel_vel[i] ) > max_vel ): 125 max_vel = abs( wheel_vel[i] ) 126 127 if max_vel > 255: 128 for i in range( 0, 4 ): 129 wheel_vel[i] *= 255 / max_vel 130 Constrain( wheel_vel[i], -255, 255 ) 131 132 dead_zone = 0.05 133 for i in range( 0, 4 ): 134 if abs( wheel_vel[i] ) < 255 * dead_zone: 135 wheel_vel[i] = 0 136 137 for i in range( 0, 4 ): 138 if wheel_vel[i] > 255 * 0.01: 139 pi.write( dire_pin[i], 0 ) 140 pi.set_PWM_dutycycle( pwm_pin[i], abs( wheel_vel[i] * 0.5 ) ) 141 elif wheel_vel[i] < -255 * 0.01: 142 pi.write( dire_pin[i], 1 ) 143 pi.set_PWM_dutycycle( pwm_pin[i], abs( wheel_vel[i] * 0.5 ) ) 144 else: 145 pi.write( dire_pin[i], 0 ) 146 pi.set_PWM_dutycycle( pwm_pin[i], 0 ) 147 148 print( left, end=" " ) 149 print( down, end=" " ) 150 print( up, end=" " ) 151 print( right, end=" " ) 152 print( L1, end=" " ) 153 print( R1, end=" " ) 154 print( square, end=" " ) 155 print( cross, end=" " ) 156 print( triangle, end=" " ) 157 print( circle, end=" " ) 158 print() 159 160 time.sleep(0.01) # Delay 1 ms 161 162 163 except KeyboardInterrupt: 164 sock.close() 165 for i in range(0, 14): 166 pi.set_mode( dout_pin[i], pigpio.INPUT ) 167 for i in range(0, 4): 168 pi.set_mode( pwm_pin[i], pigpio.INPUT ) 169 pi.stop() 170 break 171
「sock.recv( 31 )」でプログラムが止まっていると目星はつけていますが、そこ以外にもsocket通信に悪影響が出ている箇所がある可能性も否定できないので、長いかもしれませんが使用しているソースコードを全て提示させていただきました。
試したこと
ラズパイの「Wireless & Wired NetWork Setting」とPCの「インターネット プロトコル バージョン 4(TCP/IPv4)のプロパティ」にて、イーサネットのIPアドレス(192.168.10.21)を固定しましたが、上手くいきませんでした。偶発的な問題ではないことを確認するため、数回作業場所と作業場所外を往復し、両ソースコードを実行してみましたが、再現性高く作業場所ではsocket通信でき、作業場所外では全くsocket通信できませんでした。作業場所のルーターを介して出来ていたのだと考えると、他の無線ネットワークを介してやれば(根本的な解決にはならないが)通信できるのでは? と思って、私物のポケットWi-FiをPCへ接続し、コマンドプロンプトの「ipconfig」でIPアドレスを取得し、ラズパイの「Wireless & Wired NetWork Setting」とPCの「インターネット プロトコル バージョン 4(TCP/IPv4)のプロパティ」にてIPアドレス固定したのち、両ソースコードを実行しましたが、変わらず「recv()」関数でプログラムが止まってしまいます。
補足情報
LANケーブルはもちろんクロスではなくストレートを使用しています。
普段の作業場所にて通信をし、正常にsocket通信できる際は、ラズパイ側で「ifconfig」をするとIPアドレスは「192.168.10.21」、PC側で「ipconfig」をすると「169.254.36.224」と表示されます。
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。