Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84119b788e | ||
|
|
f79aaf86fa | ||
|
|
0af71f8c8e |
@@ -0,0 +1,448 @@
|
||||
# 基礎功能的 import
|
||||
import queue
|
||||
import time
|
||||
|
||||
# ROS2 的 import
|
||||
import rclpy
|
||||
|
||||
# mavlink 的 import
|
||||
from pymavlink import mavutil
|
||||
|
||||
# 自定義的 import
|
||||
import mavlinkObject as mo
|
||||
|
||||
# ====================== 分割線 =====================
|
||||
|
||||
test_item = 22
|
||||
print('test_item : ', test_item)
|
||||
|
||||
if test_item == 1:
|
||||
# 測試 updateMultiplexingList 的輸出
|
||||
print('===> Start of Program .Test ', test_item)
|
||||
mavlink_object_none = mo.mavlink_object(None)
|
||||
|
||||
print('=====================')
|
||||
print('正常範例')
|
||||
mavlink_object_none.multiplexingToAnalysis = []
|
||||
mavlink_object_none.multiplexingToReturn = []
|
||||
# mavlink_object_none.multiplexingToSwap = [[]]
|
||||
ret = mavlink_object_none.updateMultiplexingList()
|
||||
print('execute result : ', ret)
|
||||
print('multiplexingList : ', mavlink_object_none._multiplexingList)
|
||||
|
||||
print('=====================')
|
||||
print('錯誤範例 長度不一致')
|
||||
mavlink_object_none.multiplexingToSwap = [[-1], [11,12,13], [14,15,16],]
|
||||
ret = mavlink_object_none.updateMultiplexingList()
|
||||
print('execute result : ', ret)
|
||||
|
||||
print('=====================')
|
||||
print('正常範例')
|
||||
mo.swap_queues.append(queue.Queue())
|
||||
mo.swap_queues.append(queue.Queue())
|
||||
mavlink_object_none.multiplexingToAnalysis = [0, 1, 2, 3, 4, 5]
|
||||
mavlink_object_none.multiplexingToReturn = [6, 7, 8, 9, 10]
|
||||
mavlink_object_none.multiplexingToSwap = [[-1], [11,12,13], [14,15,16],]
|
||||
ret = mavlink_object_none.updateMultiplexingList()
|
||||
print('execute result : ', ret)
|
||||
print('multiplexingList : ', mavlink_object_none._multiplexingList)
|
||||
|
||||
print('=====================')
|
||||
print('錯誤範例 multiplexingToAnalysis 不可以有 -1')
|
||||
mavlink_object_none.multiplexingToAnalysis = [-1, 1, 2, 3, 4, 5]
|
||||
ret = mavlink_object_none.updateMultiplexingList()
|
||||
print('execute result : ', ret)
|
||||
|
||||
print('End of Program')
|
||||
|
||||
|
||||
elif test_item == 2:
|
||||
# 測試 updateMultiplexingList 的輸出
|
||||
print('===> Start of Program .Test ', test_item)
|
||||
mavlink_object_none1 = mo.mavlink_object(None)
|
||||
mavlink_object_none2 = mo.mavlink_object(None)
|
||||
mavlink_object_none3 = mo.mavlink_object(None)
|
||||
del mavlink_object_none2
|
||||
|
||||
print(len(mo.swap_queues))
|
||||
|
||||
mavlink_object_none2 = mo.mavlink_object(None)
|
||||
print(len(mo.swap_queues))
|
||||
|
||||
print(mavlink_object_none1._multiplexingList)
|
||||
|
||||
print('End of Program')
|
||||
|
||||
|
||||
elif test_item == 10:
|
||||
# 這邊是測試代碼 運行10秒 過程中把三個 queue 的資料印出來
|
||||
# 只啟用了 mavlink_object 的功能
|
||||
print('===> Start of Program .Test ', test_item)
|
||||
mavlink_object_none = mo.mavlink_object(None)
|
||||
|
||||
connection_string="udp:127.0.0.1:14550"
|
||||
mavlink_socket = mavutil.mavlink_connection(connection_string)
|
||||
|
||||
mavlink_object1 = mo.mavlink_object(mavlink_socket)
|
||||
|
||||
print(mavlink_object1.multiplexingToSwap)
|
||||
print(mo.swap_queues)
|
||||
mavlink_object1.multiplexingToAnalysis = [30] # only ATTITUDE
|
||||
mavlink_object1.multiplexingToReturn = [0] # only HEARTBEAT
|
||||
mavlink_object1.multiplexingToSwap[0] = [74, ] # only VFR_HUD
|
||||
# mavlink_object1.multiplexingToSwap[0] = [-1, ] # all
|
||||
|
||||
# 啟動連線的模組
|
||||
mavlink_object1.run()
|
||||
|
||||
print(mavlink_object1._multiplexingList)
|
||||
|
||||
# 運行幾秒並印出 queue 的資料
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < 3:
|
||||
while not mo.fixed_stream_bridge_queue.empty():
|
||||
print('fixed_stream_bridge_queue:')
|
||||
t = mo.fixed_stream_bridge_queue.get()
|
||||
print('from {} : {}'.format(t[0],t[2]))
|
||||
while not mo.return_packet_processor_queue.empty():
|
||||
print('return_packet_processor_queue:')
|
||||
t = mo.return_packet_processor_queue.get()
|
||||
print('from {} : {}'.format(t[0],t[2]))
|
||||
# print(t[2].get_msgbuf())
|
||||
# print(t[2].type)
|
||||
|
||||
for n in range(len(mo.swap_queues)):
|
||||
q = mo.swap_queues[n]
|
||||
while not q.empty():
|
||||
print('swap_queues:')
|
||||
t = q.get()
|
||||
print('{} gets : {}'.format(n,t))
|
||||
|
||||
|
||||
# 結束程式 退出所有 thread
|
||||
mavlink_object1.running = False
|
||||
mavlink_object1.thread.join()
|
||||
mavlink_socket.close()
|
||||
print('End of Program')
|
||||
|
||||
|
||||
elif test_item == 11:
|
||||
# 這邊是測試代碼 確認 analyzer 運行後對於 device object 的建立與封包統計狀況
|
||||
# 啟用 mavlink_object 與 mavlink_bridge的thread區塊 的功能
|
||||
print('===> Start of Program .Test ', test_item)
|
||||
connection_string="udp:127.0.0.1:14550"
|
||||
mavlink_socket = mavutil.mavlink_connection(connection_string)
|
||||
|
||||
mavlink_object2 = mo.mavlink_object(mavlink_socket)
|
||||
mavlink_object2.multiplexingToAnalysis = [0] # only HEARTBEAT
|
||||
mavlink_object2.multiplexingToReturn = []
|
||||
|
||||
# 啟動 mavlink_bridge
|
||||
analyzer = mo.mavlink_bridge()
|
||||
|
||||
# 啟動連線的模組
|
||||
mavlink_object2.run()
|
||||
|
||||
start_time = time.time()
|
||||
show_time = time.time()
|
||||
compid = 1
|
||||
while time.time() - start_time < 5:
|
||||
if (time.time() - show_time) >= 1:
|
||||
show_time = time.time()
|
||||
for sysid in analyzer.mavlink_systems:
|
||||
print("目前收到的訊息數量 : ",analyzer.mavlink_systems[sysid].components[compid].msg_count)
|
||||
print("目前遺失的訊息數量 : ",analyzer.mavlink_systems[sysid].components[compid].lost_packet_count)
|
||||
print("現在飛機的模式 : ",analyzer.mavlink_systems[sysid].components[compid].emitParams['flightMode_mode'])
|
||||
analyzer.mavlink_systems[sysid].resetComponentPacketCount(compid)
|
||||
print("===================")
|
||||
|
||||
# 印出目前所有 mavlink_systems 的內容
|
||||
print('目前所有的系統 : ')
|
||||
for sysid in analyzer.mavlink_systems:
|
||||
print(analyzer.mavlink_systems[sysid])
|
||||
|
||||
|
||||
|
||||
|
||||
# 結束程式 退出所有 thread
|
||||
mavlink_object2.stop()
|
||||
mavlink_object2.thread.join()
|
||||
analyzer.stop()
|
||||
|
||||
analyzer = mo.mavlink_bridge() # 這邊是測試是否只有一個 instance
|
||||
analyzer.thread.join()
|
||||
mavlink_socket.close()
|
||||
print('End of Program')
|
||||
|
||||
elif test_item == 12:
|
||||
# 我這邊會測試 mavlink object 作為交換器的功能
|
||||
print('===> Start of Program .Test ', test_item)
|
||||
|
||||
# 初始化兩個通道
|
||||
connection_string_in="udp:127.0.0.1:15551"
|
||||
mavlink_socket_in = mavutil.mavlink_connection(connection_string_in)
|
||||
|
||||
mavlink_object_in = mo.mavlink_object(mavlink_socket_in)
|
||||
mavlink_object_in.multiplexingToAnalysis = [0] # only HEARTBEAT
|
||||
|
||||
connection_string_out="udpout:127.0.0.1:14553"
|
||||
mavlink_socket_out = mavutil.mavlink_connection(connection_string_out, source_system=17, source_component=200)
|
||||
|
||||
mavlink_object_out = mo.mavlink_object(mavlink_socket_out)
|
||||
mavlink_object_out.multiplexingToAnalysis = [0]
|
||||
|
||||
|
||||
# 讓兩個通道互相傳輸
|
||||
mavlink_object_in.multiplexingToSwap[mavlink_object_out.socket_id] = [-1, ] # all
|
||||
mavlink_object_out.multiplexingToSwap[mavlink_object_in.socket_id] = [-1, ] # all
|
||||
|
||||
# 做一個空的通道驗證
|
||||
mavlink_object_none = mo.mavlink_object(None)
|
||||
# mavlink_object_out.multiplexingToSwap[mavlink_object_none.socket_id] = [-1, ] # all
|
||||
|
||||
# 啟動連線的模組
|
||||
analyzer = mo.mavlink_bridge()
|
||||
|
||||
# 啟動通道
|
||||
mavlink_object_in.run()
|
||||
mavlink_object_out.run()
|
||||
|
||||
start_time = time.time()
|
||||
show_time = time.time()
|
||||
print("connection established!")
|
||||
|
||||
print(type(mavlink_socket_out))
|
||||
print(type(mavlink_socket_out.mav))
|
||||
|
||||
while time.time() - start_time < 100:
|
||||
try:
|
||||
test = mo.swap_queues[mavlink_object_none.socket_id].get(block=False)
|
||||
print('none object : ', test)
|
||||
except queue.Empty:
|
||||
pass
|
||||
|
||||
if (time.time() - show_time) >= 2:
|
||||
show_time = time.time()
|
||||
for sysid in analyzer.mavlink_systems:
|
||||
for compid in analyzer.mavlink_systems[sysid].components:
|
||||
print("Sysid : {} ,目前收到的訊息數量 : {}".format(sysid, analyzer.mavlink_systems[sysid].components[compid].msg_count))
|
||||
|
||||
|
||||
analyzer.mavlink_systems[sysid].resetComponentPacketCount(compid)
|
||||
print("===================")
|
||||
|
||||
print('目前所有的系統 : ')
|
||||
for sysid in analyzer.mavlink_systems:
|
||||
print(analyzer.mavlink_systems[sysid])
|
||||
|
||||
|
||||
# 結束程式 退出所有 thread
|
||||
mavlink_object_in.stop()
|
||||
mavlink_object_in.thread.join()
|
||||
mavlink_object_out.stop()
|
||||
mavlink_object_out.thread.join()
|
||||
mavlink_socket_in.close()
|
||||
mavlink_socket_out.close()
|
||||
|
||||
analyzer.stop()
|
||||
print('End of Program')
|
||||
|
||||
elif test_item == 20:
|
||||
sysid = 1
|
||||
compid = 1
|
||||
|
||||
# 這邊測試 node 生成 topic 的功能
|
||||
rclpy.init() # 注意要初始化 rclpy 才能使用 node
|
||||
# mavlink_object_none = mo.mavlink_object(None)
|
||||
|
||||
# 啟動 mavlink_bridge
|
||||
analyzer = mo.mavlink_bridge()
|
||||
|
||||
from pymavlink.dialects.v20 import common as mavlink2
|
||||
|
||||
mav = mavlink2.MAVLink(None)
|
||||
mav.srcSystem = sysid
|
||||
mav.srcComponent = compid
|
||||
|
||||
# 這是一個 heartbeat 封包
|
||||
fake_heartbeat = mavlink2.MAVLink_heartbeat_message(
|
||||
type=mavlink2.MAV_TYPE_QUADROTOR,
|
||||
autopilot=mavlink2.MAV_AUTOPILOT_ARDUPILOTMEGA,
|
||||
base_mode=3,
|
||||
custom_mode=0,
|
||||
system_status=0,
|
||||
mavlink_version=3
|
||||
)
|
||||
mavlink_bytes = fake_heartbeat.pack(mav)
|
||||
fake_heartbeat_msg = mav.parse_char(mavlink_bytes)
|
||||
|
||||
print(analyzer.mavlink_systems)
|
||||
|
||||
mo.fixed_stream_bridge_queue.put((0, 0, fake_heartbeat_msg)) # socket id, timestamp, data
|
||||
time.sleep(0.1)
|
||||
print(analyzer.mavlink_systems)
|
||||
|
||||
analyzer._init_node()
|
||||
|
||||
analyzer.create_flightMode(sysid, analyzer.mavlink_systems[sysid].components[compid]) # sysid, compid
|
||||
print("topic created")
|
||||
time.sleep(5)
|
||||
|
||||
analyzer.emit_info()
|
||||
|
||||
# 結束程式
|
||||
analyzer.running = False
|
||||
analyzer.destroy_node()
|
||||
|
||||
rclpy.shutdown()
|
||||
analyzer.stop()
|
||||
analyzer.thread.join()
|
||||
print('End of Program')
|
||||
|
||||
|
||||
elif test_item == 21:
|
||||
# 這邊是測試代碼 引入 rclpy 來測試 node 的運行
|
||||
print('===> Start of Program .Test ', test_item)
|
||||
rclpy.init() # 注意要初始化 rclpy 才能使用 node
|
||||
|
||||
# 啟動 mavlink_bridge
|
||||
analyzer = mo.mavlink_bridge()
|
||||
# 關於 Node 的初始化
|
||||
show_time = time.time()
|
||||
analyzer._init_node() # 初始化 node
|
||||
print('初始化 node 完成 耗時 : ',time.time() - show_time)
|
||||
|
||||
# 創建通道
|
||||
connection_string="udp:127.0.0.1:15551"
|
||||
mavlink_socket = mavutil.mavlink_connection(connection_string)
|
||||
mavlink_object3 = mo.mavlink_object(mavlink_socket)
|
||||
|
||||
# 啟動通道
|
||||
mavlink_object3.run()
|
||||
|
||||
print('waiting for mavlink data ...')
|
||||
time.sleep(2) # 等待 2 秒鐘 讓 device object 收到足夠的 mavlink 訊息
|
||||
|
||||
print('目前所有的系統 : ')
|
||||
for sysid in analyzer.mavlink_systems:
|
||||
print(analyzer.mavlink_systems[sysid])
|
||||
|
||||
compid = 1
|
||||
sysid = 1
|
||||
start_time = time.time()
|
||||
analyzer.create_flightMode(sysid, analyzer.mavlink_systems[sysid].components[compid])
|
||||
end_time = time.time()
|
||||
print(f"Execution time for create_flightMode: {end_time - start_time} seconds")
|
||||
|
||||
print("start emit info")
|
||||
|
||||
start_time = time.time()
|
||||
show_time = time.time()
|
||||
while time.time() - start_time < 10:
|
||||
try:
|
||||
# rclpy.spin(analyzer)
|
||||
analyzer.emit_info() # 這邊是測試 node 的運行
|
||||
time.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
|
||||
analyzer.destroy_node()
|
||||
rclpy.shutdown()
|
||||
|
||||
|
||||
# 結束程式 退出所有 thread
|
||||
mavlink_object3.stop()
|
||||
mavlink_object3.thread.join()
|
||||
analyzer.stop()
|
||||
analyzer.thread.join()
|
||||
|
||||
mavlink_socket.close()
|
||||
print('End of Program')
|
||||
|
||||
|
||||
elif test_item == 22:
|
||||
# 這邊是測試代碼 引入 rclpy 來測試 node 的運行
|
||||
print('===> Start of Program .Test ', test_item)
|
||||
rclpy.init() # 注意要初始化 rclpy 才能使用 node
|
||||
|
||||
# 啟動 mavlink_bridge
|
||||
analyzer = mo.mavlink_bridge()
|
||||
# 關於 Node 的初始化
|
||||
show_time = time.time()
|
||||
analyzer._init_node() # 初始化 node
|
||||
print('初始化 node 完成 耗時 : ',time.time() - show_time)
|
||||
|
||||
# 初始化兩個通道
|
||||
connection_string_in="udp:127.0.0.1:15551"
|
||||
mavlink_socket_in = mavutil.mavlink_connection(connection_string_in)
|
||||
mavlink_object_in = mo.mavlink_object(mavlink_socket_in)
|
||||
|
||||
connection_string_out="udpout:127.0.0.1:14553"
|
||||
mavlink_socket_out = mavutil.mavlink_connection(connection_string_out)
|
||||
mavlink_object_out = mo.mavlink_object(mavlink_socket_out)
|
||||
|
||||
mavlink_object_none = mo.mavlink_object(None)
|
||||
|
||||
# 讓兩個通道互相傳輸
|
||||
mavlink_object_in.multiplexingToSwap[mavlink_object_out.socket_id] = [-1, ] # all
|
||||
mavlink_object_out.multiplexingToSwap[mavlink_object_in.socket_id] = [-1, ] # all
|
||||
mavlink_object_in.multiplexingToSwap[mavlink_object_none.socket_id] = [-1, ]
|
||||
|
||||
# 啟動通道
|
||||
mavlink_object_in.run()
|
||||
mavlink_object_out.run()
|
||||
|
||||
print('waiting for mavlink data ...')
|
||||
time.sleep(2) # 等待 2 秒鐘 讓 device object 收到足夠的 mavlink 訊息
|
||||
|
||||
print('目前所有的系統 : ')
|
||||
for sysid in analyzer.mavlink_systems:
|
||||
print(analyzer.mavlink_systems[sysid])
|
||||
|
||||
compid = 1
|
||||
sysid = 1
|
||||
show_time = time.time()
|
||||
analyzer.create_flightMode(sysid, analyzer.mavlink_systems[sysid].components[compid])
|
||||
print(f"Execution time for create_flightMode: {time.time() - show_time} seconds")
|
||||
|
||||
print("start emit info")
|
||||
|
||||
start_time = time.time()
|
||||
show_time = time.time()
|
||||
show_time2 = time.time()
|
||||
|
||||
while time.time() - start_time < 100:
|
||||
if (time.time() - show_time2) >= 1:
|
||||
analyzer.emit_info() # 這邊是測試 node 的運行
|
||||
# sss = analyzer.mavlink_systems[1].components[1].emitParams['flightMode_mode']
|
||||
fmsg = analyzer.mavlink_systems[1].components[1].emitParams['flightMode']
|
||||
sss = mavutil.mode_string_v10(fmsg)
|
||||
print("目前的飛行模式 : ", sss)
|
||||
show_time2 = time.time()
|
||||
|
||||
# if (time.time() - show_time) >= 2:
|
||||
# show_time = time.time()
|
||||
# for sysid in analyzer.mavlink_systems:
|
||||
# for compid in analyzer.mavlink_systems[sysid].components:
|
||||
# print("Sysid : {} ,目前收到的訊息數量 : {}".format(sysid, analyzer.mavlink_systems[sysid].components[compid].msg_count))
|
||||
# analyzer.mavlink_systems[sysid].resetComponentPacketCount(compid)
|
||||
# print("===================")
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
analyzer.destroy_node()
|
||||
rclpy.shutdown()
|
||||
|
||||
|
||||
# 結束程式 退出所有 thread
|
||||
mavlink_object_in.stop()
|
||||
mavlink_object_in.thread.join()
|
||||
mavlink_socket_in.close()
|
||||
mavlink_object_out.stop()
|
||||
mavlink_object_out.thread.join()
|
||||
mavlink_socket_out.close()
|
||||
analyzer.stop()
|
||||
analyzer.thread.join()
|
||||
|
||||
|
||||
print('End of Program')
|
||||
@@ -1,9 +1,17 @@
|
||||
|
||||
|
||||
# 自定義的 import
|
||||
from theLogger import setup_logger
|
||||
|
||||
# ====================== 分割線 =====================
|
||||
|
||||
logger = setup_logger("mavlinkDevice.py")
|
||||
|
||||
# 用來記錄每個 system 的資訊
|
||||
# 資料格式 { sysid : mavlink_device object }
|
||||
mavlink_systems = {}
|
||||
|
||||
# ====================== 分割線 =====================
|
||||
|
||||
# 這個 class 是用來記錄每個 system 的資訊 每個 system 可能會有多個 component
|
||||
class mavlink_device():
|
||||
def __init__(self):
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'''
|
||||
# 不同的匯流排只有單一種通訊協定
|
||||
# 匯流排接到訊息後透過 queue stack 傳送到分析器
|
||||
# 會有三種 Queue 分別作為 1. 固定串流分析器 2. 回傳封包處理器 3. 轉格式(例如 mavlink to FDM)的轉換器
|
||||
# 匯流排接到訊息後透過 queue stack 傳送到橋接器
|
||||
# 會有三種 Queue 分別作為 1. 固定串流橋接器 2. 回傳封包處理器 3. 轉拋串流
|
||||
# 第三種比較麻煩 會需要用 list 管理多個轉換器的 queue
|
||||
# 分析器會將解析得到的結論 再透過 ros2 的 publisher 發送出去
|
||||
# 橋接器會將解析得到的結論 再透過 ros2 的 publisher 發送出去
|
||||
|
||||
# 關於 mavlink 採用 pymavlink 這個套件 製作匯流排
|
||||
# pymavlink 的 socket 會由其他地方製作(例如 main) 再放到 mavlink_object 裡面
|
||||
@@ -21,40 +21,34 @@ from pymavlink import mavutil
|
||||
|
||||
# ROS2 的 import
|
||||
from rclpy.node import Node
|
||||
import std_msgs.msg
|
||||
|
||||
# 自定義的 import
|
||||
from mavlinkDevice import mavlink_device
|
||||
from mavlinkDevice import mavlink_device, mavlink_systems
|
||||
from mavlinkPublish import mavlink_publisher
|
||||
from theLogger import setup_logger
|
||||
|
||||
|
||||
# ====================== 分割線 =====================
|
||||
|
||||
logger = setup_logger("mavlinkObject.py")
|
||||
|
||||
fixed_stream_analyzer_queue = queue.Queue()
|
||||
fixed_stream_bridge_queue = queue.Queue()
|
||||
return_packet_processor_queue = queue.Queue()
|
||||
converte_format_queues = []
|
||||
|
||||
# 用來記錄每個 system 的資訊
|
||||
# 資料格式 { sysid : mavlink_device object }
|
||||
mavlink_systems = {}
|
||||
swap_queues = [] # 這個 list 用來存放轉拋串流的 queue # 這些 queue 同時也是各自 mavlink_object 的 output buffer
|
||||
|
||||
# ====================== 分割線 =====================
|
||||
|
||||
class mavlink_analyzer(Node, mavlink_publisher):
|
||||
class mavlink_bridge(Node, mavlink_publisher):
|
||||
'''
|
||||
這個 class 就是 固定串流分析器
|
||||
是用來接收 mavlink 訊息 並進行分析
|
||||
這個地方是針對 fixed_stream_analyzer_queue 的資料做處理的
|
||||
這個 class 就是 固定串流橋接器
|
||||
是用來接收 mavlink 訊息 並進行橋接
|
||||
這個地方是針對 fixed_stream_bridge_queue 的資料做處理的
|
||||
記錄有 mavlink bus 上有那些 system id 和 component id
|
||||
為了每個 system id 都有一個對應的 device object
|
||||
並且看是否有重複 system id
|
||||
|
||||
整段代碼包含兩大區塊 thread 和 node
|
||||
|
||||
thread 區塊內會對 fixed_stream_analyzer_queue 進行監聽 並且將收到的訊息進行處理
|
||||
thread 區塊內會對 fixed_stream_bridge_queue 進行監聽 並且將收到的訊息進行處理
|
||||
其中 HEARTBEAT 是一個特殊類別 用來初始化整個 device object
|
||||
|
||||
node 區塊則是處理 ros2 的 publisher 和 subscriber 訂閱相關
|
||||
@@ -69,7 +63,7 @@ class mavlink_analyzer(Node, mavlink_publisher):
|
||||
def __new__(cls, *args, **kwargs):
|
||||
with cls._lock: # 確保多線程環境下只有一個實例被創建
|
||||
if cls._instance is None:
|
||||
cls._instance = super(mavlink_analyzer, cls).__new__(cls)
|
||||
cls._instance = super(mavlink_bridge, cls).__new__(cls)
|
||||
return cls._instance
|
||||
|
||||
def __init__(self):
|
||||
@@ -85,7 +79,7 @@ class mavlink_analyzer(Node, mavlink_publisher):
|
||||
self.thread = threading.Thread(target=self._run_thread)
|
||||
self.thread.start()
|
||||
else:
|
||||
logger.error('mavlink_analyzer instance already exists. Do not create another one.')
|
||||
logger.error('mavlink_bridge instance already exists. Do not create another one.')
|
||||
|
||||
def stop(self):
|
||||
self.running = False
|
||||
@@ -93,12 +87,12 @@ class mavlink_analyzer(Node, mavlink_publisher):
|
||||
# === Thread 區塊 ===
|
||||
def _run_thread(self):
|
||||
# start_time = time.time() # debug
|
||||
logger.info('Start of mavlink_analyzer._run_thread')
|
||||
# 從 Queue fixed_stream_analyzer_queue 中取出 mavlink 資料 並呼叫相對應的 function 進行後處理
|
||||
logger.info('Start of mavlink_bridge._run_thread')
|
||||
# 從 Queue fixed_stream_bridge_queue 中取出 mavlink 資料 並呼叫相對應的 function 進行後處理
|
||||
while self.running:
|
||||
if fixed_stream_analyzer_queue.empty():
|
||||
if fixed_stream_bridge_queue.empty():
|
||||
continue
|
||||
msg_pack = fixed_stream_analyzer_queue.get()
|
||||
msg_pack = fixed_stream_bridge_queue.get()
|
||||
|
||||
msg = msg_pack[2]
|
||||
sysid = msg.get_srcSystem()
|
||||
@@ -121,6 +115,9 @@ class mavlink_analyzer(Node, mavlink_publisher):
|
||||
|
||||
this_component.emitParams['base_mode'] = msg.base_mode
|
||||
this_component.emitParams['flightMode_mode'] = mavutil.mode_string_v10(msg)
|
||||
# print("get mode :", mavutil.mode_string_v10(msg)) # debug
|
||||
# print("record mode :", this_component.emitParams['flightMode_mode']) # debug
|
||||
this_component.emitParams['flightMode'] = msg # debug
|
||||
|
||||
elif msg.get_msgId() == 147: # BATTERY_STATUS 處理
|
||||
this_component = self.mavlink_systems[sysid].components[msg.get_srcComponent()]
|
||||
@@ -132,12 +129,12 @@ class mavlink_analyzer(Node, mavlink_publisher):
|
||||
logger.warning('This Message Type Did not define process method : {} / {}'.format(msg.get_msgId(), msg.get_type()))
|
||||
continue
|
||||
|
||||
logger.info('End of mavlink_analyzer._run_thread')
|
||||
logger.info('End of mavlink_bridge._run_thread')
|
||||
|
||||
# === Node 區塊 ===
|
||||
def _init_node(self):
|
||||
logger.info('Start of mavlink_analyzer._init_node')
|
||||
super().__init__('mavlink_analyzer') # TODO 不知道為何 這句耗時超長 可以到 5~10 秒
|
||||
logger.info('Start of mavlink_bridge._init_node')
|
||||
super().__init__('mavlink_bridge') # TODO 不知道為何 這句耗時超長 可以到 5~10 秒
|
||||
|
||||
def emit_info(self):
|
||||
# 這邊將 mavlink_systems 內所有的 device object 內所有的 component 輪循過
|
||||
@@ -163,16 +160,41 @@ class mavlink_object():
|
||||
每個 mavlink bus 都會有一個 mavlink_object
|
||||
其中主要是 thread 做統計封包與分流
|
||||
分流表的控制在三個 list 分別為
|
||||
multiplexingToAnalysis : 這個 list 是用來分流到固定串流分析器的
|
||||
multiplexingToAnalysis : 這個 list 是用來分流到固定串流橋接器的
|
||||
multiplexingToReturn : 這個 list 是用來分流到回傳封包處理器的
|
||||
multiplexingToConvert : 這個 list 是用來分流到轉格式的
|
||||
multiplexingToSwap : 這個 list 是用來分流到轉拋串流的
|
||||
透過先更新上述三個 list 後再執行 updateMultiplexingList 可以變更分流行為
|
||||
'''
|
||||
def __init__(self, mavlink_socket, socket_id = None):
|
||||
self.socket_id = socket_id
|
||||
self.mavlink_socket = mavlink_socket
|
||||
self.msg_count = {}
|
||||
self.multiplexingList = []
|
||||
mavlinkObjects = {} # 用來記錄所有的 mavlink_object instance 資料格式 { socket_id(序號) : mavlink_object(物件實例) }
|
||||
socket_num = 0 # 用來記錄目前的 socket 數量
|
||||
def __new__(cls, *args, **kwargs):
|
||||
# 每創建一個實例 就將其添加到 mavlinkObjects 列表中
|
||||
# 創建時 會檢查 mavlinkObjects 列表中空缺的 socket_id 序號
|
||||
# 若序號無中斷 則 socket_id 往後加一 若序號有中斷 則填補最小的序號
|
||||
# socket_id 從 0 開始
|
||||
|
||||
instance = super().__new__(cls)
|
||||
socket_id = 0
|
||||
for k in cls.mavlinkObjects.keys():
|
||||
if k == socket_id:
|
||||
socket_id += 1
|
||||
else:
|
||||
break
|
||||
instance.socket_id = socket_id
|
||||
cls.socket_num += 1
|
||||
cls.mavlinkObjects[socket_id] = instance
|
||||
return instance
|
||||
|
||||
def __init__(self, socket):
|
||||
self.mavlink_socket = socket
|
||||
# 這邊變數是執行的時候被使用的 不要直接寫入它
|
||||
self._multiplexingList = []
|
||||
# 存放要發送的訊息的 queue 或稱 buffer
|
||||
self.output_buffer = queue.Queue()
|
||||
if self.socket_id >= len(swap_queues):
|
||||
swap_queues.append(self.output_buffer)
|
||||
else:
|
||||
swap_queues[self.socket_id] = self.output_buffer
|
||||
|
||||
# 關聯到全域變數
|
||||
global mavlink_systems
|
||||
@@ -180,28 +202,57 @@ class mavlink_object():
|
||||
|
||||
# 這三個 list 用來分配不同的訊息到不同的 queue
|
||||
self.multiplexingToAnalysis = [
|
||||
0, # HEARTBEAT
|
||||
24, # GPS_RAW_INT
|
||||
30, # ATTITUDE
|
||||
33, # GLOBAL_POSITION_INT
|
||||
74, # VFR_HUD
|
||||
147, # BATTERY_STATUS
|
||||
0, # HEARTBEAT # 挺必要的項目
|
||||
# 24, # GPS_RAW_INT
|
||||
# 30, # ATTITUDE
|
||||
# 33, # GLOBAL_POSITION_INT
|
||||
# 74, # VFR_HUD
|
||||
# 147, # BATTERY_STATUS
|
||||
]
|
||||
self.multiplexingToReturn = [
|
||||
0, # HEARTBEAT
|
||||
# 30, # ATTITUDE
|
||||
]
|
||||
self.multiplexingToConvert = [
|
||||
self.multiplexingToReturn = []
|
||||
self.multiplexingToSwap = [
|
||||
[] for _ in range(len(swap_queues))
|
||||
]
|
||||
|
||||
# 刷新其他 mavlink_object 的 multiplexingToSwap
|
||||
for k, object in self.mavlinkObjects.items():
|
||||
if (k != self.socket_id) and (len(object.multiplexingToSwap) <= self.socket_id):
|
||||
object.multiplexingToSwap.append([])
|
||||
object.updateMultiplexingList()
|
||||
|
||||
logger.info('mavlink_object instance {} created'.format(self.socket_id))
|
||||
|
||||
def __del__(self):
|
||||
self.mavlink_socket.close()
|
||||
self.stop()
|
||||
# 停下自己的 thread
|
||||
if self.mavlink_socket != None:
|
||||
self.mavlink_socket.close()
|
||||
self.stop()
|
||||
|
||||
# 移除其他 mavlink_object 的 multiplexingToSwap
|
||||
for k, object in self.mavlinkObjects.items():
|
||||
if (k != self.socket_id) and (len(object.multiplexingToSwap) > self.socket_id):
|
||||
object.multiplexingToSwap[self.socket_id] = []
|
||||
object.updateMultiplexingList()
|
||||
|
||||
# 移除自己的 swap_queues
|
||||
swap_queues[self.socket_id] = None
|
||||
|
||||
# 處理 class 的 instance 記錄
|
||||
self.socket_num -= 1
|
||||
self.mavlinkObjects.pop(self.socket_id) # 刪除這個 instance
|
||||
|
||||
# logger 模組在這邊會一直掛掉 找不到問題 先用 print 代替
|
||||
# print('mavlink_object instance {} deleted'.format(self.socket_id)) # debug
|
||||
# logger.info('mavlink_object instance {} deleted'.format(self.socket_id))
|
||||
# try:
|
||||
# logger.info('mavlink_object instance {} deleted'.format(self.socket_id))
|
||||
# except Exception as e:
|
||||
# print(f"Error logging in __del__: {e}")
|
||||
# if 'logger' in globals() and logger:
|
||||
# logger.info('mavlink_object instance {} deleted'.format(self.socket_id))
|
||||
|
||||
def run(self):
|
||||
if not self.socket_id:
|
||||
logger.error('Please set socket id before running')
|
||||
return
|
||||
# TODO 檢查 socket 是否有連線
|
||||
self.thread = threading.Thread(target=self._run_thread)
|
||||
self.running = self.updateMultiplexingList()
|
||||
self.thread.start()
|
||||
@@ -214,6 +265,8 @@ class mavlink_object():
|
||||
start_time = time.time()
|
||||
while self.running:
|
||||
timestamp = time.time() # 記錄接受到訊息的時間 # 這邊若是在大量訊息造成壅塞時 可能會有些微偏差
|
||||
|
||||
# 處理接收到的封包
|
||||
try:
|
||||
mavlinkMsg = self.mavlink_socket.recv_msg()
|
||||
except Exception as e:
|
||||
@@ -223,7 +276,7 @@ class mavlink_object():
|
||||
self.running = False
|
||||
break
|
||||
|
||||
if mavlinkMsg: # data type should be 'pymavlink.dialects.v20.ardupilotmega.MAVLink_attitude_message'
|
||||
if mavlinkMsg: # data type should be 'pymavlink.dialects.v20.ardupilotmega. etc...'
|
||||
# 統計收到的訊息 & 透過 mavlink 封包的序列號來檢查是否有遺失的封包 & 記錄最後收到的封包時間
|
||||
sysid = mavlinkMsg.get_srcSystem()
|
||||
compid = mavlinkMsg.get_srcComponent()
|
||||
@@ -231,19 +284,37 @@ class mavlink_object():
|
||||
# mavlinkMsg.get_type() # mavlinkMsg.get_msgId() # 前者是字串 後者是 int 都是代表 mavlink 類型
|
||||
mavlink_systems[sysid].updateComponentPacketCount(compid, mavlinkMsg.get_seq(), mavlinkMsg.get_msgId(), timestamp)
|
||||
|
||||
# print(mavlinkMsg) # debug
|
||||
# break # Debug
|
||||
# break # Debug function can put here you can see the input data from mavlink
|
||||
|
||||
# 將訊息依照 multiplexing list 分發到不同的 queue
|
||||
for i in range(len(self.multiplexingList)):
|
||||
if mavlinkMsg.get_msgId() in self.multiplexingList[i]:
|
||||
for i in range(len(self._multiplexingList)):
|
||||
if (self._multiplexingList[i] == []):
|
||||
continue
|
||||
elif (mavlinkMsg.get_msgId() in self._multiplexingList[i]) or (self._multiplexingList[i][0] == -1):
|
||||
if i == 0:
|
||||
fixed_stream_analyzer_queue.put((self.socket_id,timestamp,mavlinkMsg))
|
||||
fixed_stream_bridge_queue.put((self.socket_id,timestamp,mavlinkMsg))
|
||||
elif i == 1:
|
||||
return_packet_processor_queue.put((self.socket_id,timestamp,mavlinkMsg))
|
||||
else:
|
||||
convert_queue = converte_format_queues[i-2]
|
||||
convert_queue.put((self.socket_id,timestamp,mavlinkMsg))
|
||||
_queue = swap_queues[i-2]
|
||||
# _queue.put((self.socket_id,timestamp,mavlinkMsg)) # 測試看看 也許不需要別的資訊 只需要封包
|
||||
_queue.put(mavlinkMsg)
|
||||
|
||||
# 處理要送出的封包
|
||||
# 如果 有資料在 output_buffer 中則將其取出並發送
|
||||
# 沒有就略過發送
|
||||
|
||||
try:
|
||||
mavlinkMsg_send = self.output_buffer.get(block=False)
|
||||
except queue.Empty:
|
||||
mavlinkMsg_send = None
|
||||
# except Exception as e:
|
||||
# logger.error(f"Error getting data from output_buffer: {e}")
|
||||
# mavlinkMsg_send = None
|
||||
|
||||
if mavlinkMsg_send:
|
||||
# self.mavlink_socket.mav.send(mavlinkMsg_send)
|
||||
self.mavlink_socket.write(mavlinkMsg_send.get_msgbuf()) # 這邊會將封包寫入 socket 中
|
||||
|
||||
# thread 結束
|
||||
logger.info('End of mavlink_object._run_thread id : {}'.format(self.socket_id))
|
||||
@@ -252,20 +323,37 @@ class mavlink_object():
|
||||
'''
|
||||
更新 multiplexing list 並做簡單的檢查
|
||||
'''
|
||||
# 檢查 multiplexingToAnalysis 與 multiplexingToReturn 是否有 -1 值
|
||||
check = (-1 in self.multiplexingToAnalysis) or (-1 in self.multiplexingToReturn)
|
||||
if check:
|
||||
logger.error('MultiplexingToAnalysis or MultiplexingToReturn NOT all type spilt. socket id : {}'.format(self.socket_id))
|
||||
return False
|
||||
|
||||
# 更新 multiplexing list
|
||||
self.multiplexingList = [self.multiplexingToAnalysis, self.multiplexingToReturn] + self.multiplexingToConvert
|
||||
# 檢查 multiplexingToSwap 與 swap_queues 的長度是否一致 而且 swap_queues 的長度不能為 0
|
||||
check = len(self.multiplexingToSwap) != len(swap_queues) or len(swap_queues) == 0
|
||||
if check:
|
||||
logger.error('Multiplexing Queue not fit List , Please check the list. socket id : {}'.format(self.socket_id))
|
||||
return False
|
||||
|
||||
# 檢查 multiplexing list 格式是否有錯誤
|
||||
check = all(isinstance(i, list) and all(isinstance(j, int) for j in i) for i in self.multiplexingList)
|
||||
# 對應到自己的 multiplexingToSwap 必需為空 避免對自己迴圈轉拋
|
||||
try:
|
||||
self.multiplexingToSwap[self.socket_id] = []
|
||||
except IndexError:
|
||||
logger.error('Multiplexing List of self socket id should be void. socket id : {}'.format(self.socket_id))
|
||||
return False
|
||||
|
||||
# 組合 multiplexing list
|
||||
multiL_tmp = [self.multiplexingToAnalysis, self.multiplexingToReturn] + self.multiplexingToSwap
|
||||
|
||||
# 檢查 multiplexing list 格式是否有錯誤 # 全部都要是 list 每個 list 裡面都要是 int
|
||||
check = all(isinstance(i, list) and all(isinstance(j, int) for j in i) for i in multiL_tmp)
|
||||
if not check:
|
||||
logger.error('Multiplexing List Format Error, Please check the list')
|
||||
logger.error('Multiplexing List Format Error, Please check the list. socket id : {}'.format(self.socket_id))
|
||||
return False # 若有錯誤則回傳 False
|
||||
|
||||
check = len(self.multiplexingToConvert) != len(converte_format_queues)
|
||||
if check:
|
||||
logger.error('Multiplexing Queue not fit List , Please check the list')
|
||||
return False
|
||||
# 更新 multiplexing list
|
||||
self._multiplexingList = multiL_tmp
|
||||
|
||||
return True
|
||||
|
||||
# ====================== 分割線 =====================
|
||||
@@ -274,163 +362,6 @@ class mavlink_object():
|
||||
def main_node():
|
||||
pass
|
||||
|
||||
# ====================== 分割線 =====================
|
||||
# 測試時的程式進入點
|
||||
def main_develop(args=None):
|
||||
|
||||
test_item = 2
|
||||
print('test_item : ', test_item)
|
||||
|
||||
if test_item == 1:
|
||||
# 這邊是測試代碼 運行10秒 過程中把三個 queue 的資料印出來
|
||||
# 只啟用了 mavlink_object 的功能
|
||||
print('Start of Program .Test 1')
|
||||
connection_string="udp:127.0.0.1:14550"
|
||||
mavlink_socket = mavutil.mavlink_connection(connection_string)
|
||||
|
||||
mavlink_object1 = mavlink_object(mavlink_socket, 1)
|
||||
mavlink_object1.multiplexingToAnalysis = [30] # only ATTITUDE
|
||||
mavlink_object1.multiplexingToReturn = [0] # only HEARTBEAT
|
||||
mavlink_object1.multiplexingToConvert = [[74,]] # only VFR_HUD
|
||||
|
||||
# 做一個空的 queue list 驗證 multiplexingToConvert
|
||||
converte_format_queues.append(queue.Queue())
|
||||
# 啟動連線的模組
|
||||
mavlink_object1.run()
|
||||
|
||||
# 運行幾秒並印出 queue 的資料
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < 2:
|
||||
|
||||
while not fixed_stream_analyzer_queue.empty():
|
||||
print('fixed_stream_analyzer_queue:')
|
||||
t = fixed_stream_analyzer_queue.get()
|
||||
print('from {} : {}'.format(t[0],t[2]))
|
||||
while not return_packet_processor_queue.empty():
|
||||
print('return_packet_processor_queue:')
|
||||
t = return_packet_processor_queue.get()
|
||||
# print('from {} : {}'.format(t[0],t[2]))
|
||||
print(t[2].type)
|
||||
|
||||
for q in converte_format_queues:
|
||||
while not q.empty():
|
||||
print('converte_format_queues:')
|
||||
t = q.get()
|
||||
print('from {} : {}'.format(t[0],t[2]))
|
||||
|
||||
# 結束程式 退出所有 thread
|
||||
mavlink_object1.running = False
|
||||
mavlink_object1.thread.join()
|
||||
mavlink_socket.close()
|
||||
print('End of Program .Test 1')
|
||||
|
||||
elif test_item == 2:
|
||||
# 這邊是測試代碼 確認 analyzer 運行後對於 device object 的建立與封包統計狀況
|
||||
# 啟用 mavlink_object 與 mavlink_analyzer的thread區塊 的功能
|
||||
print('Start of Program .Test 2')
|
||||
connection_string="udp:127.0.0.1:14550"
|
||||
mavlink_socket = mavutil.mavlink_connection(connection_string)
|
||||
|
||||
mavlink_object2 = mavlink_object(mavlink_socket, 1)
|
||||
mavlink_object2.multiplexingToAnalysis = [0] # only HEARTBEAT
|
||||
mavlink_object2.multiplexingToReturn = [] # only HEARTBEAT
|
||||
mavlink_object2.multiplexingToConvert = [] #
|
||||
|
||||
# 啟動 mavlink_analyzer
|
||||
analyzer = mavlink_analyzer()
|
||||
|
||||
# 啟動連線的模組
|
||||
mavlink_object2.run()
|
||||
|
||||
start_time = time.time()
|
||||
show_time = time.time()
|
||||
compid = 1
|
||||
while time.time() - start_time < 5:
|
||||
if (time.time() - show_time) >= 1:
|
||||
show_time = time.time()
|
||||
for sysid in analyzer.mavlink_systems:
|
||||
print("目前收到的訊息數量 : ",analyzer.mavlink_systems[sysid].components[compid].msg_count)
|
||||
print("目前遺失的訊息數量 : ",analyzer.mavlink_systems[sysid].components[compid].lost_packet_count)
|
||||
print("現在飛機的模式 : ",analyzer.mavlink_systems[sysid].components[compid].emitParams['flightMode_mode'])
|
||||
analyzer.mavlink_systems[sysid].resetComponentPacketCount(compid)
|
||||
print("===================")
|
||||
|
||||
# 印出目前所有 mavlink_systems 的內容
|
||||
print('目前所有的系統 : ')
|
||||
for sysid in mavlink_systems:
|
||||
print(mavlink_systems[sysid])
|
||||
|
||||
|
||||
|
||||
|
||||
# 結束程式 退出所有 thread
|
||||
mavlink_object2.stop()
|
||||
mavlink_object2.thread.join()
|
||||
analyzer.stop()
|
||||
|
||||
analyzer = mavlink_analyzer() # 這邊是測試是否只有一個 instance
|
||||
analyzer.thread.join()
|
||||
mavlink_socket.close()
|
||||
print('End of Program .Test 2')
|
||||
|
||||
elif test_item == 3:
|
||||
# 這邊是測試代碼 引入 rclpy 來測試 node 的運行
|
||||
print('Start of Program .Test 3')
|
||||
rclpy.init() # 注意要初始化 rclpy 才能使用 node
|
||||
connection_string="udp:127.0.0.1:14550"
|
||||
mavlink_socket = mavutil.mavlink_connection(connection_string)
|
||||
|
||||
mavlink_object3 = mavlink_object(mavlink_socket, 1)
|
||||
mavlink_object3.multiplexingToAnalysis = [0] # only HEARTBEAT
|
||||
mavlink_object3.multiplexingToReturn = [] # only HEARTBEAT
|
||||
mavlink_object3.multiplexingToConvert = [] #
|
||||
|
||||
# 啟動 mavlink_analyzer
|
||||
analyzer = mavlink_analyzer()
|
||||
|
||||
# 關於 Node 的初始化
|
||||
show_time = time.time()
|
||||
analyzer._init_node() # 初始化 node
|
||||
print('初始化 node 完成 耗時 : ',time.time() - show_time)
|
||||
|
||||
# 啟動連線的模組
|
||||
mavlink_object3.run()
|
||||
|
||||
print('waiting for mavlink data ...')
|
||||
time.sleep(2) # 等待 2 秒鐘 讓 device object 收到足夠的 mavlink 訊息
|
||||
|
||||
compid = 1
|
||||
sysid = 1
|
||||
start_time = time.time()
|
||||
analyzer.create_flightMode(sysid, analyzer.mavlink_systems[sysid].components[compid])
|
||||
end_time = time.time()
|
||||
print(f"Execution time for create_flightMode: {end_time - start_time} seconds")
|
||||
|
||||
print("start emit info")
|
||||
|
||||
start_time = time.time()
|
||||
show_time = time.time()
|
||||
while time.time() - start_time < 20:
|
||||
try:
|
||||
# rclpy.spin(analyzer)
|
||||
analyzer.emit_info() # 這邊是測試 node 的運行
|
||||
time.sleep(0.5)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
|
||||
analyzer.destroy_node()
|
||||
rclpy.shutdown()
|
||||
|
||||
|
||||
# 結束程式 退出所有 thread
|
||||
mavlink_object3.stop()
|
||||
mavlink_object3.thread.join()
|
||||
analyzer.stop()
|
||||
analyzer.thread.join()
|
||||
|
||||
mavlink_socket.close()
|
||||
print('End of Program .Test 3')
|
||||
|
||||
if __name__ == '__main__':
|
||||
import rclpy # 這邊是為了測試而加的
|
||||
main_develop()
|
||||
pass
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import socket
|
||||
|
||||
SOCKET_PATH = "/tmp/unix_socket_example"
|
||||
|
||||
# 建立 socket
|
||||
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
client.connect(SOCKET_PATH)
|
||||
|
||||
# 傳送資料
|
||||
client.sendall(b"Hello from client!")
|
||||
data = client.recv(1024)
|
||||
print("📤 Server replied:", data.decode())
|
||||
|
||||
client.close()
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
|
||||
|
||||
import rclpy
|
||||
from rclpy.node import Node
|
||||
from std_msgs.msg import String
|
||||
import time
|
||||
|
||||
# import mavros_msgs.srv
|
||||
|
||||
class TalkerNode(Node):
|
||||
def __init__(self):
|
||||
start_time = time.time()
|
||||
super().__init__('talker_node')
|
||||
end_time = time.time()
|
||||
print(f"Node initialization took {end_time - start_time:.2f} seconds")
|
||||
|
||||
self.publisher_ = self.create_publisher(String, 'hahatest/_1', 10)
|
||||
self.timer = self.create_timer(1.0, self.timer_callback) # 每秒執行一次
|
||||
self.get_logger().info('TalkerNode has been started.')
|
||||
|
||||
def timer_callback(self):
|
||||
msg = String()
|
||||
msg.data = 'Hello, ROS 2!'
|
||||
self.publisher_.publish(msg)
|
||||
self.get_logger().info(f'Published: "{msg.data}"')
|
||||
|
||||
def main(args=None):
|
||||
rclpy.init(args=args)
|
||||
node = TalkerNode()
|
||||
|
||||
print("Before sleep")
|
||||
time.sleep(5) # 等待 5 秒鐘
|
||||
print("After sleep")
|
||||
try:
|
||||
start_time = time.time()
|
||||
while time.time() - start_time < 10: # 持續 10 秒鐘
|
||||
rclpy.spin_once(node)
|
||||
time.sleep(1) # 每秒執行一次
|
||||
finally:
|
||||
node.destroy_node()
|
||||
rclpy.shutdown()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,33 @@
|
||||
import socket
|
||||
import os
|
||||
|
||||
# socket file path
|
||||
SOCKET_PATH = "/tmp/unix_socket_example"
|
||||
|
||||
# 若檔案存在就先刪除
|
||||
if os.path.exists(SOCKET_PATH):
|
||||
os.remove(SOCKET_PATH)
|
||||
|
||||
# 建立 socket
|
||||
server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
|
||||
# 綁定 socket 到檔案
|
||||
server.bind(SOCKET_PATH)
|
||||
server.listen(1)
|
||||
|
||||
print("🔌 Server waiting for connection...")
|
||||
|
||||
# 等待 client 連線
|
||||
conn, _ = server.accept()
|
||||
print("✅ Client connected.")
|
||||
|
||||
while True:
|
||||
data = conn.recv(1024)
|
||||
if not data:
|
||||
break
|
||||
print("📥 Received:", data.decode())
|
||||
conn.sendall(b"Echo: " + data)
|
||||
|
||||
conn.close()
|
||||
server.close()
|
||||
os.remove(SOCKET_PATH)
|
||||
Reference in New Issue
Block a user