chiyu
ken910606 3 months ago
parent e54e42aad2
commit 44d63979b5

@ -11,7 +11,7 @@ import socket
from pymavlink import mavutil from pymavlink import mavutil
from geometry_msgs.msg import Point, Vector3 from geometry_msgs.msg import Point, Vector3
from sensor_msgs.msg import BatteryState, NavSatFix, Imu from sensor_msgs.msg import BatteryState, NavSatFix, Imu
from std_msgs.msg import Float64 from std_msgs.msg import Float64, String
from mavros_msgs.msg import State, VfrHud from mavros_msgs.msg import State, VfrHud
from mavros_msgs.srv import CommandBool, CommandTOL from mavros_msgs.srv import CommandBool, CommandTOL
@ -371,6 +371,7 @@ class WebSocketMavlinkReceiver(threading.Thread):
self.running = False self.running = False
class DroneMonitor(Node): class DroneMonitor(Node):
# Subscribe to drone ROS2 topics
def __init__(self): def __init__(self):
super().__init__('drone_monitor') super().__init__('drone_monitor')
self.signals = DroneSignals() self.signals = DroneSignals()
@ -403,12 +404,15 @@ class DroneMonitor(Node):
def scan_topics(self): def scan_topics(self):
topics = self.get_topic_names_and_types() topics = self.get_topic_names_and_types()
drone_pattern = re.compile(r'/MavLinkBus/(s\d+_\d+)/(\w+)') drone_pattern = re.compile(r'/fc_network/vehicle/(sys\d+)/(\w+)')
found_drones = set() found_drones = set()
for topic_name, _ in topics: for topic_name, _ in topics:
if match := drone_pattern.match(topic_name): if match := drone_pattern.match(topic_name):
drone_id, topic_type = match.groups() sys_id, topic_type = match.groups()
# 將 sys11 轉換為 s0_11 格式以保持兼容性
drone_num = sys_id.replace('sys', '')
drone_id = f's0_{drone_num}'
found_drones.add(drone_id) found_drones.add(drone_id)
with self.lock: with self.lock:
self.drone_topics.setdefault(drone_id, set()).add(topic_type) self.drone_topics.setdefault(drone_id, set()).add(topic_type)
@ -418,9 +422,11 @@ class DroneMonitor(Node):
self.setup_drone(drone_id) self.setup_drone(drone_id)
def setup_drone(self, drone_id): def setup_drone(self, drone_id):
base_topic = f'/MavLinkBus/{drone_id}' # 從 s0_11 轉換回 sys11 格式
sys_id = drone_id.replace('s0_', 'sys')
base_topic = f'/fc_network/vehicle/{sys_id}'
# Add service clients # Add service clients (保留但可能無法使用,因為新 topic 可能沒有這些服務)
self.arm_clients[drone_id] = self.create_client( self.arm_clients[drone_id] = self.create_client(
CommandBool, CommandBool,
f'{base_topic}/cmd/arming' f'{base_topic}/cmd/arming'
@ -438,58 +444,22 @@ class DroneMonitor(Node):
) )
subs = { subs = {
'attitude': self.create_subscription(
Imu,
f'{base_topic}/attitude',
lambda msg, did=drone_id: self.attitude_callback(did, msg),
10
),
'battery': self.create_subscription( 'battery': self.create_subscription(
BatteryState, BatteryState,
f'{base_topic}/battery', f'{base_topic}/battery',
lambda msg, did=drone_id: self.battery_callback(did, msg), lambda msg, did=drone_id: self.battery_callback(did, msg),
10 10
), ),
'global': self.create_subscription( 'position': self.create_subscription(
NavSatFix, NavSatFix,
f'{base_topic}/global_position/global', f'{base_topic}/position',
lambda msg, did=drone_id: self.gps_callback(did, msg), lambda msg, did=drone_id: self.gps_callback(did, msg),
10 10
), ),
'rel_alt': self.create_subscription( 'summary': self.create_subscription(
Float64, String,
f'{base_topic}/global_position/rel_alt', f'{base_topic}/summary',
lambda msg, did=drone_id: self.altitude_callback(did, msg), lambda msg, did=drone_id: self.summary_callback(did, msg),
10
),
'local_pose': self.create_subscription(
Point,
f'{base_topic}/local_position/pose',
lambda msg, did=drone_id: self.local_pose_callback(did, msg),
10
),
'local_vel': self.create_subscription(
Vector3,
f'{base_topic}/local_position/velocity',
lambda msg, did=drone_id: self.local_vel_callback(did, msg),
10
),
'loss_rate': self.create_subscription(
Float64,
f'{base_topic}/packet_loss_rate',
lambda msg, did=drone_id: self.loss_rate_callback(did, msg),
10
),
'state': self.create_subscription(
State,
f'{base_topic}/state',
lambda msg, did=drone_id: self.state_callback(did, msg),
10
),
'ping': self.create_subscription(
Float64,
f'{base_topic}/ping',
lambda msg, did=drone_id: self.ping_callback(did, msg),
10 10
), ),
'vfr_hud': self.create_subscription( 'vfr_hud': self.create_subscription(
@ -596,6 +566,39 @@ class DroneMonitor(Node):
'armed': msg.armed 'armed': msg.armed
} }
def summary_callback(self, drone_id, msg):
"""處理 summary topic (JSON 格式)"""
try:
data = json.loads(msg.data)
mode = data.get('mode_name', 'UNKNOWN')
if mode in self.filtered_modes:
return
# 根據 socket_id 更新 drone_id
socket_id = data.get('socket_id')
sysid = data.get('sysid')
if socket_id is not None and sysid is not None:
# 使用 socket_id 作為前綴
actual_drone_id = f's{socket_id}_{sysid}'
else:
actual_drone_id = drone_id
self.latest_data[(actual_drone_id, 'state')] = {
'mode': mode,
'armed': data.get('armed', False),
'socket_id': socket_id,
'sysid': sysid,
'vehicle_type': data.get('vehicle_type'),
'autopilot': data.get('autopilot'),
'gps_fix': data.get('gps_fix'),
'gps_fix_type': data.get('gps_fix'),
'connected': data.get('connected')
}
except json.JSONDecodeError as e:
print(f"Error parsing summary JSON for {drone_id}: {e}")
except Exception as e:
print(f"Error in summary_callback for {drone_id}: {e}")
def gps_callback(self, drone_id, msg): def gps_callback(self, drone_id, msg):
self.latest_data[(drone_id, 'gps')] = { self.latest_data[(drone_id, 'gps')] = {
'lat': msg.latitude, 'lat': msg.latitude,

Loading…
Cancel
Save