|
|
|
|
@ -0,0 +1,331 @@
|
|
|
|
|
import rclpy
|
|
|
|
|
from pymavlink import mavutil
|
|
|
|
|
from time import sleep
|
|
|
|
|
import time
|
|
|
|
|
|
|
|
|
|
import socket
|
|
|
|
|
import struct
|
|
|
|
|
|
|
|
|
|
# used at fdm_switch_example_two
|
|
|
|
|
import threading
|
|
|
|
|
import queue
|
|
|
|
|
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
def mavlink_analyzer_simple(count = 500):
|
|
|
|
|
# rclpy.init()
|
|
|
|
|
# node = rclpy.create_node('mavlink_analyzer_simple')
|
|
|
|
|
|
|
|
|
|
print('Inintializing connection')
|
|
|
|
|
|
|
|
|
|
connection_string="udp:127.0.0.1:14550"
|
|
|
|
|
connection = mavutil.mavlink_connection(connection_string)
|
|
|
|
|
|
|
|
|
|
print('Catch messages')
|
|
|
|
|
msg_count = {}
|
|
|
|
|
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
|
|
|
|
|
for _ in range(count):
|
|
|
|
|
msg = connection.recv_msg()
|
|
|
|
|
# msg = connection.recv_match(blocking=True)
|
|
|
|
|
if msg:
|
|
|
|
|
msg_type = msg.get_type()
|
|
|
|
|
if msg_type in msg_count:
|
|
|
|
|
msg_count[msg_type] += 1
|
|
|
|
|
else:
|
|
|
|
|
msg_count[msg_type] = 1
|
|
|
|
|
|
|
|
|
|
if msg.get_type() == 'SERVO_OUTPUT_RAW':
|
|
|
|
|
print(msg)
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
print('No message yet, 1 second for data to fill')
|
|
|
|
|
sleep(1)
|
|
|
|
|
|
|
|
|
|
print('Messages Type received:')
|
|
|
|
|
print(msg_count)
|
|
|
|
|
|
|
|
|
|
end_time = time.time()
|
|
|
|
|
print('Time elapsed: ', end_time - start_time)
|
|
|
|
|
|
|
|
|
|
print('Closing connection')
|
|
|
|
|
connection.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fdm_parser_example(data=None):
|
|
|
|
|
if data is None:
|
|
|
|
|
data = bytes.fromhex('1a48e903b1340500e803e803e803e803000000000000000000000000000000000000000000000000')
|
|
|
|
|
# 1a48e903b1340500e803e803e803e803000000000000000000000000000000000000000000000000
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parse_format = 'HHI16H'
|
|
|
|
|
|
|
|
|
|
if len(data) != struct.calcsize(parse_format):
|
|
|
|
|
print("got packet of len %u, expected %u" % (len(data), struct.calcsize(parse_format)))
|
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
|
|
decoded = struct.unpack(parse_format,data)
|
|
|
|
|
|
|
|
|
|
magic = decoded[0]
|
|
|
|
|
frame_rate_hz = decoded[1]
|
|
|
|
|
frame_count = decoded[2]
|
|
|
|
|
pwm = decoded[3:]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print("magic: %u, frame_rate_hz: %u, frame_count: %u, pwm: %s" % (magic, frame_rate_hz, frame_count, pwm))
|
|
|
|
|
|
|
|
|
|
def fdm_switch_example_one():
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
這個範例在 SITL 與 Gazebo 之間 做一個簡單的UDP轉發器
|
|
|
|
|
沒有轉換數據格式
|
|
|
|
|
'''
|
|
|
|
|
# make a link get fdm from SITL, as a server
|
|
|
|
|
sock_s2g = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
|
|
sock_s2g.bind(('', 9002))
|
|
|
|
|
sock_s2g.settimeout(0.1)
|
|
|
|
|
|
|
|
|
|
# set a target link pass JSON to Gazebo, as a client
|
|
|
|
|
sock_g2s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
|
|
server_address = ('127.0.0.1', 19002)
|
|
|
|
|
|
|
|
|
|
packet_count = 0
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
try:
|
|
|
|
|
# 接到SITL的數據 並轉發給Gazebo
|
|
|
|
|
data_s2g, addr_s2g = sock_s2g.recvfrom(1024)
|
|
|
|
|
sock_g2s.sendto(data_s2g, server_address)
|
|
|
|
|
# 得到Gazebo的回應 並轉發給SITL
|
|
|
|
|
data_g2s, addr_g2s = sock_g2s.recvfrom(1024)
|
|
|
|
|
sock_s2g.sendto(data_g2s, addr_s2g)
|
|
|
|
|
|
|
|
|
|
# 解析並保存接收到的數據到 JSON 檔案 (SITL -> Gazebo)
|
|
|
|
|
try:
|
|
|
|
|
# 解析從 SITL 到 Gazebo 的數據
|
|
|
|
|
decoded = struct.unpack('HHI16H', data_s2g)
|
|
|
|
|
s2g_json = {
|
|
|
|
|
"magic": decoded[0],
|
|
|
|
|
"frame_rate_hz": decoded[1],
|
|
|
|
|
"frame_count": decoded[2],
|
|
|
|
|
"pwm": list(decoded[3:])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 解析從 Gazebo 到 SITL 的數據
|
|
|
|
|
# 注意:假設從 Gazebo 返回的數據是字串形式的 JSON
|
|
|
|
|
try:
|
|
|
|
|
g2s_data_str = data_g2s.decode('utf-8')
|
|
|
|
|
# 保存原始數據,適合後續分析
|
|
|
|
|
with open('gazebo_response_raw.txt', 'a') as f:
|
|
|
|
|
f.write(g2s_data_str + '\n')
|
|
|
|
|
except:
|
|
|
|
|
# 如果不是 UTF-8 格式,可能是二進制數據
|
|
|
|
|
g2s_data_str = str(data_g2s)
|
|
|
|
|
|
|
|
|
|
# 合併數據到一個 JSON 對象
|
|
|
|
|
combined_data = {
|
|
|
|
|
"sitl_to_gazebo": s2g_json,
|
|
|
|
|
"gazebo_to_sitl": g2s_data_str,
|
|
|
|
|
"timestamp": time.time()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 寫入 JSON 檔案
|
|
|
|
|
with open('fdm_one_data.json', 'w') as f:
|
|
|
|
|
json.dump(combined_data, f, indent=2)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"JSON 處理錯誤: {e}")
|
|
|
|
|
|
|
|
|
|
packet_count += 1
|
|
|
|
|
except socket.timeout:
|
|
|
|
|
print(f'no value')
|
|
|
|
|
#print(f'address:{addr_s2g}')
|
|
|
|
|
#pass
|
|
|
|
|
|
|
|
|
|
current_time = time.time()
|
|
|
|
|
elapsed_time = current_time - start_time
|
|
|
|
|
|
|
|
|
|
if elapsed_time >= 1.0:
|
|
|
|
|
#print(f"Packets received in the last second: {packet_count}")
|
|
|
|
|
print(f'JSON Pack:{data_g2s}')
|
|
|
|
|
packet_count = 0
|
|
|
|
|
start_time = current_time
|
|
|
|
|
fdm_parser_example(data_s2g)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fdm_switch_example_two():
|
|
|
|
|
'''
|
|
|
|
|
這個範例在 SITL 與 Gazebo 之間 做一個簡單的UDP轉發器
|
|
|
|
|
有轉換數據格式
|
|
|
|
|
|
|
|
|
|
time_usec
|
|
|
|
|
servo1_raw
|
|
|
|
|
servo16_raw
|
|
|
|
|
'''
|
|
|
|
|
# read info from SITL via MAVLink
|
|
|
|
|
connection_string="udp:127.0.0.1:14550" # uart mavlink # MATLAB
|
|
|
|
|
connection = mavutil.mavlink_connection(connection_string)
|
|
|
|
|
|
|
|
|
|
# set a target link pass JSON to Gazebo, as a client
|
|
|
|
|
sock_g2s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
|
|
server_address = ('127.0.0.1', 19002)
|
|
|
|
|
|
|
|
|
|
data_queue = queue.Queue()
|
|
|
|
|
servo_out = [0] * 16
|
|
|
|
|
data_queue.put(servo_out)
|
|
|
|
|
|
|
|
|
|
def send_data_from_queue(sock, server_address, q, frame_rate_fdm=600, frame_count_fdm=1):
|
|
|
|
|
interval = 1.0 / frame_rate_fdm
|
|
|
|
|
while True:
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
try:
|
|
|
|
|
data = q.get(timeout=0.1)
|
|
|
|
|
if data is None:
|
|
|
|
|
break
|
|
|
|
|
last_data = data
|
|
|
|
|
except queue.Empty:
|
|
|
|
|
data = last_data
|
|
|
|
|
data = struct.pack('HHI16H', 0x481a, frame_rate_fdm, frame_count_fdm, *servo_out)
|
|
|
|
|
sock.sendto(data, server_address)
|
|
|
|
|
|
|
|
|
|
# 新增:寫入 JSON 檔案
|
|
|
|
|
data_json = {
|
|
|
|
|
"magic": 0x481a,
|
|
|
|
|
"frame_rate_hz": frame_rate_fdm,
|
|
|
|
|
"frame_count": frame_count_fdm,
|
|
|
|
|
"pwm": list(servo_out)
|
|
|
|
|
}
|
|
|
|
|
with open('fdm_data.json', 'w') as f:
|
|
|
|
|
json.dump(data_json, f)
|
|
|
|
|
|
|
|
|
|
frame_count_fdm += 1
|
|
|
|
|
fdm_parser_example(data) # debug
|
|
|
|
|
|
|
|
|
|
elapsed_time = time.time() - start_time
|
|
|
|
|
sleep_time = interval - elapsed_time
|
|
|
|
|
if sleep_time > 0:
|
|
|
|
|
sleep(sleep_time)
|
|
|
|
|
|
|
|
|
|
Running = True
|
|
|
|
|
thread = threading.Thread(target=send_data_from_queue, args=(sock_g2s, server_address, data_queue))
|
|
|
|
|
thread.start()
|
|
|
|
|
|
|
|
|
|
while Running:
|
|
|
|
|
msgb1 = None
|
|
|
|
|
msg = connection.recv_msg()
|
|
|
|
|
while msg :
|
|
|
|
|
if msg.get_type() == 'SERVO_OUTPUT_RAW':
|
|
|
|
|
msgb1 = msg
|
|
|
|
|
# break # 這裡不需要break,因為我要最後一個 servo_output_raw 的值
|
|
|
|
|
msg = connection.recv_msg()
|
|
|
|
|
|
|
|
|
|
if msgb1:
|
|
|
|
|
for i in range(16):
|
|
|
|
|
servo_out[i] = getattr(msgb1, f'servo{i+1}_raw')
|
|
|
|
|
data_queue.put(servo_out)
|
|
|
|
|
msgb1 = None
|
|
|
|
|
# Running = False # debug
|
|
|
|
|
else:
|
|
|
|
|
# print('No message yet, 10 ms for data to fill')
|
|
|
|
|
sleep(0.01)
|
|
|
|
|
|
|
|
|
|
# Example of putting data into the queue
|
|
|
|
|
# data_queue.put(data)
|
|
|
|
|
# To stop the thread, you can put None into the queue
|
|
|
|
|
# data_queue.put(None)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def fdm_switch_example_one_with_remote_forwarding():
|
|
|
|
|
'''
|
|
|
|
|
這個範例在 SITL 與 Gazebo 之間 做一個簡單的UDP轉發器
|
|
|
|
|
並且將JSON數據轉發到指定的遠端IP
|
|
|
|
|
'''
|
|
|
|
|
# make a link get fdm from SITL, as a server
|
|
|
|
|
sock_s2g = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
|
|
sock_s2g.bind(('', 9002))
|
|
|
|
|
sock_s2g.settimeout(0.1)
|
|
|
|
|
|
|
|
|
|
# set a target link pass JSON to Gazebo, as a client
|
|
|
|
|
sock_g2s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
|
|
server_address = ('127.0.0.1', 19002)
|
|
|
|
|
|
|
|
|
|
# 建立與遠端IP的socket連接
|
|
|
|
|
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
|
|
remote_address = ('140.120.31.130', 9003) # 遠端IP與埠號,您可以根據需要更改埠號
|
|
|
|
|
print(f'Setting up forwarding to remote address: {remote_address}')
|
|
|
|
|
|
|
|
|
|
packet_count = 0
|
|
|
|
|
start_time = time.time()
|
|
|
|
|
|
|
|
|
|
while True:
|
|
|
|
|
try:
|
|
|
|
|
# 接到SITL的數據 並轉發給Gazebo
|
|
|
|
|
data_s2g, addr_s2g = sock_s2g.recvfrom(1024)
|
|
|
|
|
sock_g2s.sendto(data_s2g, server_address)
|
|
|
|
|
|
|
|
|
|
# 得到Gazebo的回應 並轉發給SITL
|
|
|
|
|
data_g2s, addr_g2s = sock_g2s.recvfrom(1024)
|
|
|
|
|
sock_s2g.sendto(data_g2s, addr_s2g)
|
|
|
|
|
|
|
|
|
|
# 解析並保存接收到的數據到 JSON 檔案 (SITL -> Gazebo)
|
|
|
|
|
try:
|
|
|
|
|
# 解析從 SITL 到 Gazebo 的數據
|
|
|
|
|
decoded = struct.unpack('HHI16H', data_s2g)
|
|
|
|
|
s2g_json = {
|
|
|
|
|
"magic": decoded[0],
|
|
|
|
|
"frame_rate_hz": decoded[1],
|
|
|
|
|
"frame_count": decoded[2],
|
|
|
|
|
"pwm": list(decoded[3:])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 解析從 Gazebo 到 SITL 的數據
|
|
|
|
|
try:
|
|
|
|
|
g2s_data_str = data_g2s.decode('utf-8')
|
|
|
|
|
# 保存原始數據,適合後續分析
|
|
|
|
|
with open('gazebo_response_raw.txt', 'a') as f:
|
|
|
|
|
f.write(g2s_data_str + '\n')
|
|
|
|
|
except:
|
|
|
|
|
# 如果不是 UTF-8 格式,可能是二進制數據
|
|
|
|
|
g2s_data_str = str(data_g2s)
|
|
|
|
|
|
|
|
|
|
# 合併數據到一個 JSON 對象
|
|
|
|
|
combined_data = {
|
|
|
|
|
"sitl_to_gazebo": s2g_json,
|
|
|
|
|
"gazebo_to_sitl": g2s_data_str,
|
|
|
|
|
"timestamp": time.time()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 寫入 JSON 檔案
|
|
|
|
|
with open('fdm_one_data.json', 'w') as f:
|
|
|
|
|
json.dump(combined_data, f, indent=2)
|
|
|
|
|
|
|
|
|
|
# 將JSON數據轉發到遠端IP
|
|
|
|
|
remote_socket.sendto(json.dumps(combined_data).encode(), remote_address)
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"JSON 處理錯誤: {e}")
|
|
|
|
|
|
|
|
|
|
packet_count += 1
|
|
|
|
|
except socket.timeout:
|
|
|
|
|
print(f'no value')
|
|
|
|
|
#pass
|
|
|
|
|
|
|
|
|
|
current_time = time.time()
|
|
|
|
|
elapsed_time = current_time - start_time
|
|
|
|
|
|
|
|
|
|
if elapsed_time >= 1.0:
|
|
|
|
|
print(f'JSON Pack:{data_g2s}')
|
|
|
|
|
print(f'Forwarded data to remote IP: 140.120.31.130')
|
|
|
|
|
packet_count = 0
|
|
|
|
|
start_time = current_time
|
|
|
|
|
fdm_parser_example(data_s2g)
|
|
|
|
|
|
|
|
|
|
print('Start')
|
|
|
|
|
#fdm_switch_example_two()
|
|
|
|
|
#mavlink_analyzer_simple()
|
|
|
|
|
#fdm_switch_example_one()
|
|
|
|
|
fdm_switch_example_one_with_remote_forwarding()
|
|
|
|
|
#fdm_parser_example()
|