npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

openfly

v1.0.3

Published

Drone flight control SDK for multi-rotor aircraft

Readme

OpenFly 无人机飞控 SDK

TypeScript SDK,用于通过串口控制多旋翼无人机。

安装

npm install openfly
npm install serialport  # peer dependency

快速开始

import { FlightController, MoveDirection } from 'openfly';

const drone = new FlightController();

await drone.connect();
await drone.takeOff(0, 100);           // 起飞到 100cm
await drone.moveCtrl(0, MoveDirection.forward, 50);  // 前进 50cm
await drone.rotation(0, 90);        // 旋转 90 度
await drone.land(0);                 // 降落
await drone.disconnect();

控制等待方式

默认每个命令后会等待到达目标(约 2-4 秒)。

// 方式 1: 自动等待(默认)
drone.setAutoDelay(true);  // 每个命令等待到达
await drone.moveCtrl(0, MoveDirection.forward, 50);

// 方式 2: 快速连续命令
drone.setAutoDelay(false);  // 命令立即返回
await drone.moveCtrl(0, MoveDirection.forward, 50);
await drone.rotation(0, 90);
// 手动等待
await drone.waitForMovement(0);

// 方式 3: 自定义等待
await drone.sleep(2000);  // 等待 2 秒

API 文档

FlightController

连接

| 方法 | 说明 | |------|------| | connect(useSerial?: boolean, tcpPort?: number) | 连接飞控 | | disconnect() | 断开连接 | | isConnected() | 检查连接状态 |

飞行控制

| 方法 | 说明 | |------|------| | takeOff(id, height) | 起飞到高度 (cm) | | land(id) | 降落 | | flyMode(id, mode) | 设置飞行模式 | | xySpeed(id, speed) | 设置水平速度 (cm/s) | | zSpeed(id, speed) | 设置垂直速度 (cm/s) |

移动

| 方法 | 说明 | |------|------| | move(id, mode, [x, y, z]) | 移动到绝对位置 | | moveCtrl(id, dir, distance) | 按方向移动 | | goTo(id, [x, y, z]) | 飞向坐标点 | | goToTag(id, tagId, height) | 飞向 AprilTag | | rotation(id, angle) | 旋转角度 (度) | | flyHigh(id, height) | 飞到高度 | | moveSearchDot(id, dir, distance) | 搜索黑点移动 | | moveSearchTag(id, dir, distance, tagId) | 搜索标签移动 | | moveFollowTag(id, dir, distance, tagId) | 跟随标签 | | moveSearchBlob(id, dir, distance, blob) | 搜索斑点移动 |

硬件控制

| 方法 | 说明 | |------|------| | ledCtrl(id, mode, color) | 控制 LED | | closeLed(id) | 关闭 LED | | servoCtrl(id, angle) | 舵机控制 (度) | | magnetCtrl(id, mode) | 磁铁控制 | | cameraDeg(id, deg) | 摄像头角度 | | switchCtrl(id, mode) | 开关控制 | | irSend(id, mode, [d0,d1,d2,d3]) | 红外发送 |

机械臂

| 方法 | 说明 | |------|------| | robotArmCtrl(id, index, time) | 控制机械臂 | | robotArmRecord(id, mode) | 记录/回放 | | robotArmCover(id, index) | 覆盖位置 | | serServoCtrl(id, index, value, time) | 串口舵机 |

视觉

| 方法 | 说明 | |------|------| | mvCheckMode(id, mode) | 设置视觉模式 | | mvCheckTag(id, tagId) | 检测 AprilTag | | mvCheckBlob(id, type, blob) | 检测斑点 | | photographMode(id, mode) | 拍照模式 | | shootCtrl(id, mode) | 射击控制 |

传感器查询

| 方法 | 说明 | |------|------| | getSensor(id) | 获取完整传感器数据 | | getFlySensor(id, type) | 获取特定值 | | getObsDistance(id, dir) | 障碍物距离 | | getKeyPress(id) | 按键状态 | | isMvCheck(id, mode) | 视觉检测结果 | | getBlobResult(id, type) | 斑点结果 | | getScaleWeight(id) | 电子秤重量 | | getShootResult(id, type) | 射击结果 | | isPhotoOk() | 照片是否完成 | | getFps() | 通���帧率 |

配置

| 方法 | 说明 | |------|------| | setAutoDelay(auto) | 启用/禁用自动等待 | | waitForMovement(id, threshold, timeout) | 手动等待移动 | | sleep(ms) | 休眠 | | getRoleNews(id, type) | 获取消息 | | clearRoleNews(id) | 清除消息 |

枚举值

// MoveDirection
0: forward   1: back     2: left    3: right
4: up        5: down     6: forwardLeft  7: forwardRight
8: backLeft  9: backRight

// FlightMode  
0: hover   1: oneKeyTakeOff   2: oneKeyLand   3: emergencyStop

// LedMode
0: off   1: solid   2: blink   3: breathe

类型

// 传感器数据
interface SensorData {
  id: number;           // 无人机 ID
  vol: number;         // 电池电压
  ssi: number;         // 信号强度
  obs_dist: number[4];  // 4 向障碍距离
  imu: number[3];      // [roll, pitch, yaw]
  loc: number[3];       // [x, y, z] 位置
  locErr: number[3];    // 位置误差
  mv: MvResult;        // 视觉结果
}

// 视觉结果
interface MvResult {
  flag: number;       // 检测标志
  tagId: number;     // 标签 ID
  blob_n: number;   // 斑点数量
  blob_s/w/h: number;
}

// 颜色
type Color = { r: number; g: number; b: number };

// 斑点参数
interface BlobParams {
  minArea: number; maxArea: number;
  threshold: number; pixelsThreshold: number;
  areaThreshold: number; merge: boolean;
};

// SensorProperty: 'tagID' | 'qrCode' | 'brCode' | 
//              'rol' | 'pit' | 'yaw' |
//              'loc_x' | 'loc_y' | 'loc_z' |
//              'err_x' | 'err_y' | 'err_z' | 'vol'

示例

基础飞行

import { FlightController, MoveDirection } from 'openfly';

const drone = new FlightController();
await drone.connect();

await drone.takeOff(0, 100);
await drone.moveCtrl(0, MoveDirection.forward, 50);
await drone.rotation(0, 90);
await drone.land(0);

await drone.disconnect();

连续命令(快)

drone.setAutoDelay(false);

await drone.takeOff(0, 80);
await drone.moveCtrl(0, MoveDirection.forward, 30);
await drone.rotation(0, 45);
await drone.goTo(0, [50, 50, 80]);

await drone.waitForMovement(0);

drone.setAutoDelay(true);
await drone.land(0);

传感器读取

setInterval(() => {
  const s = drone.getSensor(0);
  console.log('位置:', s?.loc);
  console.log('姿态:', s?.imu);
  console.log('电压:', drone.getFlySensor(0, 'vol'));
}, 100);

视觉追踪

await drone.mvCheckTag(0, 1);
while (!drone.isMvCheck(0, 0)) await drone.sleep(100);

const tag = drone.getFlySensor(0, 'tagID');
await drone.goToTag(0, tag, 50);

LED 和舵机

await drone.ledCtrl(0, 1, { r: 255, g: 0, b: 0 });
await drone.sleep(1000);
await drone.servoCtrl(0, 90);
await drone.magnetCtrl(0, 1);

多机协同

const drone = new FlightController(10);
await drone.connect();

await Promise.all([
  drone.takeOff(0, 80),
  drone.takeOff(1, 80),
]);

await Promise.all([
  drone.moveCtrl(0, MoveDirection.forward, 30),
  drone.moveCtrl(1, MoveDirection.back, 30),
]);

await Promise.all([drone.land(0), drone.land(1)]);

构建

npm install
npm run build
npm run typecheck

协议

  • 串口: 460800 波特
  • 数据包: [187][Length][Command][Data...][Checksum]

License

MIT