鸿蒙 Harmony OS 无人驾驶 mavlink 开发 你没看错,我做出来了
·
**大家好,完成udp 实现的同时,我先做了mavlink协议的转换,算是一个小型工程,给想在鸿蒙领域做无人驾驶的实现做自己的一份贡献**
先来点介绍,要实现mavlink 首先需要重官网下载源码,经过打包工具生成代码,目前的mavlink2 版本只有java 和 C 的代码 ,其他代码如js,ts,等都不行,特别是ts 缺少 pack 和unpack ,是因为官网没有上 node_mavlink
所以只能使用C ,怎么打包可以去搜索一下,这里不在赘述,
不会用ndk 的同学可以去看我前面的文章,有详细的讲怎么使用ndk
第一步创建ndk环境,我实现的有两个函数
export const mavlinkByteToMsg: (bytes: ArrayBuffer) => object;
export const mavLinkObject2buffer:(command:number,obj:object)=> Uint8Array
ok 相信大家一定熟悉,两个函数的作用就是消息转buffer,和buffer转消息
然后将C代码放进来
全都是.h 文件 放哪里不重要,你只要能引入就可以了
好了,接下来真正的代码要一步步的开始了
1 ,创建函数 (不重要)
EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor desc[] = {
{"mavLinkObject2buffer", nullptr, MavlinkMsgToByte, nullptr, nullptr, nullptr, napi_default, nullptr},
{"mavlinkByteToMsg", nullptr, MavlinkByteToMsg, nullptr, nullptr, nullptr, napi_default, nullptr}};
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
return exports;
}
2 ,实现mavlink 接收比较多 函数 MavlinkByteToMsg 是生成消息的
static napi_value MavlinkByteToMsg(napi_env env, napi_callback_info info) {
// // usdlink_parse_char 第一个参数是通道,用的wifi 基本是1,第4个参数是读取字节的状态,用来控制的
mavlink_message_t msg;
napi_value obj;
napi_status status2 = napi_create_object(env, &obj);
mavlink_status_t status1;
size_t argc = 1;
napi_value args[1];
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
// 检查参数个数
if (argc < 1) {
napi_throw_type_error(env, NULL, "Wrong number of arguments");
return nullptr;
}
napi_value jsArray = nullptr;
napi_create_array(env, &jsArray);
napi_value array = args[0];
// 检查参数是否为TypedArray
napi_typedarray_type array_type;
size_t length;
void *data;
napi_value array_buffer;
size_t byte_offset;
napi_get_typedarray_info(env, args[0], &array_type, &length, &data, &array_buffer, &byte_offset);
// 确保是Uint8Array
if (array_type != napi_uint8_array) {
napi_throw_error(env, nullptr, "Expected Uint8Array");
return nullptr;
}
for (int i = 0; i < length; i++) {
napi_value result;
napi_get_element(env, args[0], i, &result);
// 获取整数参数
int32_t number;
napi_get_value_int32(env, result, &number);
uint8_t data = (uint8_t)number;
if (mavlink_parse_char(1, data, &msg, &status1)) {
SafeSetProperty(env, obj, "msgid", msg.msgid);
SafeSetProperty(env, obj, "_message_id", msg.msgid);
if (msg.msgid == MAVLINK_MSG_ID_HEARTBEAT) { //这里就可以做你要接收的消息了比如心跳,
mavlink_heartbeat_t heartbeat;
mavlink_msg_heartbeat_decode(&msg, &heartbeat);//这个是消息里面有的直接在心跳的消息里搜索 _deco就出来了
SafeSetProperty(env, obj, "custom_mode", heartbeat.custom_mode);
SafeSetProperty(env, obj, "type", heartbeat.type);
SafeSetProperty(env, obj, "autopilot", heartbeat.autopilot);
SafeSetProperty(env, obj, "base_mode", heartbeat.base_mode);
SafeSetProperty(env, obj, "system_status", heartbeat.system_status);
SafeSetProperty(env, obj, "mavlink_version", heartbeat.mavlink_version);
}
}
return obj;
SafeSetProperty函数,这里面的实现根据你自己的需要去重新构造,我现在实现了简单逻辑,具体的你们自己补充,毕竟涉及比较多,我不可能全部展示,需要帮助的可以私聊我
这个函数有两个,一个是单个数据,一个是数组,所以要做两个转换函数
// 单个的
template <typename T> napi_status SafeSetProperty(napi_env env, napi_value object, const char *prop_name, T value) {
napi_value js_value;
napi_status status = CreateJSValue(env, value, &js_value); // 调用辅助函数创建JS值
if (status != napi_ok) {
return status;
}
return napi_set_named_property(env, object, prop_name, js_value);
}
// 数组版本:将C++数组(T*)转换为JS数组并设置为对象属性
template <typename T>
napi_status SafeSetProperty(napi_env env, napi_value object, const char *prop_name, T *array, size_t length) {
// 1. 创建JS数组(指定长度以优化性能)
napi_value js_array;
napi_status status = napi_create_array(env, &js_array);
if (status != napi_ok) {
return status;
}
// 2. 遍历C++数组,逐个转换元素并填充到JS数组
for (size_t i = 0; i < length; ++i) {
napi_value js_element;
auto value = *array[i];
status = CreateJSValue(env, value, &js_element); // 复用单个元素转换逻辑
if (status != napi_ok) {
return status;
}
// 将元素设置到JS数组的第i个索引
status = napi_set_element(env, js_array, i, js_element);
if (status != napi_ok) {
return status;
}
}
// 3. 将JS数组设置为对象属性
return napi_set_named_property(env, object, prop_name, js_array);
}
// 辅助函数:将单个C++值转换为N-API的JS值
template <typename T> napi_status CreateJSValue(napi_env env, T value, napi_value *js_value) {
// -------------------------- 有符号整数类型处理 --------------------------
if constexpr (std::is_same<T, int8_t>::value || // 8位有符号整数
std::is_same<T, int16_t>::value || // 16位有符号整数
std::is_same<T, int32_t>::value || // 32位有符号整数
std::is_same<T, short>::value || // 原生short(通常16位有符号)
std::is_same<T, int>::value) { // 原生int(通常32位有符号)
int32_t converted_value = static_cast<int32_t>(value);
return napi_create_int32(env, converted_value, js_value);
}
// -------------------------- 无符号整数类型处理 --------------------------
else if constexpr (std::is_same<T, uint8_t>::value || // 8位无符号整数
std::is_same<T, uint16_t>::value || // 16位无符号整数
std::is_same<T, uint32_t>::value) { // 32位无符号整数
uint32_t converted_value = static_cast<uint32_t>(value);
return napi_create_uint32(env, converted_value, js_value);
}
// -------------------------- 64位整数类型处理 --------------------------
else if constexpr (std::is_same<T, int64_t>::value || // 64位有符号整数
std::is_same<T, long long>::value) { // 原生long long(64位有符号)
int64_t converted_value = static_cast<int64_t>(value);
return napi_create_int64(env, converted_value, js_value);
}
// -------------------------- 浮点类型处理 --------------------------
else if constexpr (std::is_same<T, float>::value || // 32位浮点数
std::is_same<T, double>::value) { // 64位浮点数
double converted_value = static_cast<double>(value); // float提升为double(JS Number为双精度)
return napi_create_double(env, converted_value, js_value);
}
// -------------------------- 字符串类型处理(char[]/char*) --------------------------
else if constexpr (std::is_same<T, char *>::value || // 非const字符串
std::is_same<T, const char *>::value) { // const字符串(MAVLink常用)
return napi_create_string_utf8(env, value, NAPI_AUTO_LENGTH, js_value);
}
// -------------------------- 不支持的类型 --------------------------
else {
return napi_invalid_arg; // 返回无效参数状态码
}
}
ok 接收部分已经完成大家可以调用去看看
import testNapi from 'libentry.so';
import { UdpUtils } from '../udpconnect/UdpUtils';
@Entry
@Component
struct Index {
udpUtil = UdpUtils.getInstance();
aboutToAppear() {
// 初始化UDP工具
this.udpUtil.init((ip:string,buffer: Uint8Array) => {
if(ip){
this.message = ip
}
// 这收到buffer
console.log("buffer" + buffer)
// 然后进行数据处理
let obj = testNapi.mavlinkByteToMsg(buffer)
console.log(JSON.stringify(obj))
// MavLinkReceiver.process(obj)
});
}
我已经可以完美接收了,你们呢兄弟们
这些都是PX4仿真的数据不是真机数据,没有经济价值的哦,嘿嘿嘿
yqj---mavlinkMsg--->{"msgid":30,"_message_id":30,"time_boot_ms":2004603154,"roll":-0.00154349603690207,"pitch":-0.0034618950448930264,"yaw":-0.07689015567302704,"rollspeed":0.0007478658808395267,"pitchspeed":-0.002940803999081254,"yawspeed":0.0026230253279209137}
发送的部分在下一节实现
更多推荐

所有评论(0)