1. mavlinkROS2Nodes.py 更新姿態發佈的 topic
2. 新增 interface AttitudeRaw 與對應的 package.xml & CMakeList
Chiyu Chen 1 week ago
parent 75d9d260e1
commit 7f8babfa5e

@ -8,11 +8,14 @@ endif()
# find dependencies # find dependencies
find_package(ament_cmake REQUIRED) find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED) find_package(rosidl_default_generators REQUIRED)
find_package(std_msgs REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME} rosidl_generate_interfaces(${PROJECT_NAME}
"msg/AttitudeRaw.msg"
"srv/MavPing.srv" "srv/MavPing.srv"
"srv/MavCommandLong.srv" "srv/MavCommandLong.srv"
"srv/MavPositionTargetGlobalInt.srv" "srv/MavPositionTargetGlobalInt.srv"
DEPENDENCIES std_msgs
) )
ament_package() ament_package()

@ -0,0 +1,9 @@
uint32 seq
builtin_interfaces/Time stamp
string frame_id
float32 roll
float32 pitch
float32 yaw
float32 rollspeed
float32 pitchspeed
float32 yawspeed

@ -15,6 +15,9 @@
<test_depend>ament_lint_auto</test_depend> <test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend> <test_depend>ament_lint_common</test_depend>
<build_depend>std_msgs</build_depend>
<exec_depend>std_msgs</exec_depend>
<export> <export>
<build_type>ament_cmake</build_type> <build_type>ament_cmake</build_type>
</export> </export>

@ -32,6 +32,7 @@ import mavros_msgs.msg
# ROS2 Service imports # ROS2 Service imports
import fc_interfaces.srv as fcsrv import fc_interfaces.srv as fcsrv
import fc_interfaces.msg as fcmsg
from .ackEnum import serviceAckResult from .ackEnum import serviceAckResult
# 自定義 imports # 自定義 imports
@ -231,7 +232,7 @@ class VehicleStatusPublisher(Node):
publisher.publish(msg) publisher.publish(msg)
def _publish_position_ned(self, sysid: int, status: mvv.ComponentStatus): def _publish_position_ned(self, sysid: int, status: mvv.ComponentStatus):
"""發布 LOCAL_POSITION_NEDNED 座標,含位置與速度)""" """發布 LOCAL_POSITION_NED (NED 座標,含位置與速度)"""
if not self.rate_controller.should_publish(sysid, 'position_ned'): if not self.rate_controller.should_publish(sysid, 'position_ned'):
return return
@ -267,34 +268,28 @@ class VehicleStatusPublisher(Node):
publisher.publish(msg) publisher.publish(msg)
def _publish_attitude(self, sysid: int, status: mvv.ComponentStatus): def _publish_attitude(self, sysid: int, status: mvv.ComponentStatus):
"""發布姿態IMU""" """發布原始姿態roll/pitch/yaw 與角速度"""
if not self.rate_controller.should_publish(sysid, 'attitude'): if not self.rate_controller.should_publish(sysid, 'attitude'):
return return
att = status.attitude att = status.attitude
if att.roll is None: if att.roll is None or att.pitch is None or att.yaw is None:
return return
publisher = self._get_or_create_publisher(sysid, 'attitude', sensor_msgs.msg.Imu) publisher = self._get_or_create_publisher(
sysid, 'attitude', fcmsg.AttitudeRaw
)
if publisher.get_subscription_count() == 0: if publisher.get_subscription_count() == 0:
return return
msg = sensor_msgs.msg.Imu() msg = fcmsg.AttitudeRaw()
msg.stamp = self.get_clock().now().to_msg()
# 歐拉角轉四元數 msg.roll = float(att.roll)
qx, qy, qz, qw = self._euler_to_quaternion( msg.pitch = float(att.pitch)
att.roll, att.pitch, att.yaw msg.yaw = float(att.yaw)
) msg.rollspeed = float(att.rollspeed) if att.rollspeed is not None else 0.0
msg.orientation.x = qx msg.pitchspeed = float(att.pitchspeed) if att.pitchspeed is not None else 0.0
msg.orientation.y = qy msg.yawspeed = float(att.yawspeed) if att.yawspeed is not None else 0.0
msg.orientation.z = qz
msg.orientation.w = qw
# 角速度
if att.rollspeed is not None:
msg.angular_velocity.x = att.rollspeed
msg.angular_velocity.y = att.pitchspeed
msg.angular_velocity.z = att.yawspeed
publisher.publish(msg) publisher.publish(msg)
@ -1137,7 +1132,8 @@ ros2_manager = fc_ros_manager()
2026.04.07 2026.04.07
1. 完成 ros2 MavPositionTargetGlobalInt 區域 1. 完成 ros2 MavPositionTargetGlobalInt 區域
2. 優化 response.ack_result 回傳值的資訊 2. 優化 response.ack_result 回傳值的資訊
3. 新增 _publish_position_ned() 發布剛體座標的訊息
4. 重製 _publish_attitude() 使其更簡單的去發布姿態訊息
TODO TODO
1. service 部分會需要跟 mavlinkobject 大量互動 也許需要考慮對方的生命週期 1. service 部分會需要跟 mavlinkobject 大量互動 也許需要考慮對方的生命週期

@ -38,6 +38,7 @@ class SerialMode(Enum):
"""連接類型""" """連接類型"""
STRAIGHT = auto() # 原始數據直通 STRAIGHT = auto() # 原始數據直通
XBEEAPI2AT = auto() # XBee API 模式 XBEEAPI2AT = auto() # XBee API 模式
XBEEAPI_POLL = auto()
NOT_USE = auto() # 不使用 NOT_USE = auto() # 不使用
@ -176,10 +177,10 @@ class XBeeFrameProcessor(FrameProcessor):
"""根據 frame type 分派;若是 RX payload 回傳 bytes其餘回傳 None""" """根據 frame type 分派;若是 RX payload 回傳 bytes其餘回傳 None"""
frame_type = frame[3] frame_type = frame[3]
if frame_type == self.FRAME_TYPE_RX_PACKET: if frame_type == self.FRAME_TYPE_RX_PACKET: # mavlink
return self._decapsulate(frame) return self._decapsulate(frame)
if frame_type == self.FRAME_TYPE_AT_RESPONSE: if frame_type == self.FRAME_TYPE_AT_RESPONSE: # AT command
if self.at_handler is not None: if self.at_handler is not None:
self.at_handler.handle_frame(frame) self.at_handler.handle_frame(frame)
return None return None
@ -335,9 +336,10 @@ class ATCommandHandler:
def _handle_rssi(self, data: bytes): def _handle_rssi(self, data: bytes):
"""處理 DB (RSSI) 回應:單 byte 無號值,單位 dBm""" """處理 DB (RSSI) 回應:單 byte 無號值,單位 dBm"""
pass pass
# if data: if data:
# print(f"[{self.serial_port}] RSSI = -{data[0]} dBm") # dev print(f"[{self.serial_port}] RSSI = -{data[0]} dBm") # dev
# logger.debug(f"[{self.serial_port}] RSSI = -{data[0]} dBm") # dev # logger.debug(f"[{self.serial_port}] RSSI = -{data[0]} dBm") # dev
pass
def _handle_serial_high(self, data: bytes): def _handle_serial_high(self, data: bytes):
"""處理 SH (Serial Number High)""" """處理 SH (Serial Number High)"""
@ -370,6 +372,10 @@ class SerialHandler(asyncio.Protocol):
at_handler = ATCommandHandler(self.serial_port_str) at_handler = ATCommandHandler(self.serial_port_str)
return XBeeFrameProcessor(at_handler=at_handler) return XBeeFrameProcessor(at_handler=at_handler)
# if self.serial_mode == SerialMode.XBEEAPI_POLL:
# at_handler = ATCommandHandler_new(self.serial_port_str)
# return XBeeFrameProcessor(at_handler=at_handler)
logger.warning(f"Unknown serial mode: {self.serial_mode}, using Raw") logger.warning(f"Unknown serial mode: {self.serial_mode}, using Raw")
return RawFrameProcessor() return RawFrameProcessor()

@ -7,6 +7,13 @@
<maintainer email="chiyu1468@hotmail.com">picars</maintainer> <maintainer email="chiyu1468@hotmail.com">picars</maintainer>
<license>TODO: License declaration</license> <license>TODO: License declaration</license>
<exec_depend>fc_interfaces</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>sensor_msgs</exec_depend>
<exec_depend>geometry_msgs</exec_depend>
<exec_depend>nav_msgs</exec_depend>
<exec_depend>mavros_msgs</exec_depend>
<test_depend>ament_copyright</test_depend> <test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend> <test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend> <test_depend>ament_pep257</test_depend>

Loading…
Cancel
Save