交互式乘法 myCobot 让学习充满乐趣!

本文经作者Fumitaka Kimizuka 授权我们翻译和转载。

原文链接:myCobotに「頷き」「首振り」「首傾げ」をしてもらう 🤖 - みかづきブログ・カスタム

引言

Fumitaka Kimizuka 创造了一个乘法表系统,帮助他的女儿享受学习乘法表的乐趣。她可以口头回答乘法问题,显示的数字就是乘积。如果她回答正确,myCobot 就会点头;如果她回答错误,myCobot 就会做出不同的动作。以下是作者对该系统开发过程的记录。
🤖

https://twitter.com/i/status/1793416553867706459

在实施这一机制时,我用 Node.js 编写了一个程序,让 myCobot "点头"、"摇头 "和 "歪头"。
https://twitter.com/i/status/1780785823220224188

这是我将其与 LINE Bot 相关联时创建的程序的改进版。

准备工作

首先,按照以下步骤使 myCobot 可以通过 Python 运行。

然后,使用 Node.js 和 Express 架设网络服务器。虽然你也可以使用 Python 设置网络服务器,但以我的技术水平,Node.js 对我来说更快。因此,我使用 Node.js 和 python-shell 来控制 myCobot。

python-shell - npm

.env

python 复制代码
# Specify the USB port to which myCobot is connected
MY_COBOT_PORT=/dev/cu.XXXXXXXX

app.js (Excerpt)

python 复制代码
const express = require('express');

const express = require('express');
const { PythonShell } = require('python-shell');
const app = express();
const http = require('http').Server(app);

app.use(express.json());
app.use('/', express.static(`${ __dirname }/public`));

async function move(color = [255, 255, 255], angles = [0, 0, 0, 0, 0, 0], interval = 200) {
  return new Promise((resolve, reject) => {
    PythonShell.runString(
      `from pymycobot.mycobot import MyCobot; MyCobot('${ process.env.MY_COBOT_PORT }').set_color(${ color }); from pymycobot.mycobot import MyCobot; MyCobot('${ process.env.MY_COBOT_PORT }').send_angles([${ angles }], ${ duration })`,
      null
    ).then(() => {
      setTimeout(() => resolve(), interval);
    }).catch(() => {
      reject();
    });
  });
}

move(
  [255, 255, 255], // LED matrix colors (RGB)
  [0, 0, 0, 0, 0, 0], // Angles of myCobot's joints (degrees)
  200
);

通过创建一个 "move "函数,该函数可以接受 LED 矩阵颜色、关节角度和驱动时间等参数,因此变得非常方便。

实施:

对于点头、摇头和歪头,请使用之前创建的`move`函数。

python 复制代码
// Nodding
async function doYes() {
  return new Promise(async (resolve, reject) => {
    const interval = 200;

    try {
      await move([0, 0, 255], [0, 0, 0, 45, 0, 0], interval);
      await move([0, 0, 255], [0, 0, 0, 0, 0, 0], interval);
      await move([0, 0, 255], [0, 0, 0, 45, 0, 0], interval);
      await move([0, 0, 255], [0, 0, 0, 0, 0, 0], interval);
      await move([0, 0, 255], [0, 0, 0, 45, 0, 0], interval);
      await move([0, 0, 255], [0, 0, 0, 0, 0, 0], interval);
      await move([255, 255, 255], [0, 0, 0, 0, 0, 0], interval);

      resolve();
    } catch (err) {
      console.error(err);

      reject();
    }
  });
}

// Shaking its head
async function doNo() {
  return new Promise(async (resolve, reject) => {
    const interval = 400;

    try {
      await move([255, 0, 0], [0, 0, 0, 0, 45, 0], interval / 2);
      await move([255, 0, 0], [0, 0, 0, 0, -45, 0], interval);
      await move([255, 0, 0], [0, 0, 0, 0, 45, 0], interval);
      await move([255, 0, 0], [0, 0, 0, 0, -45, 0], interval);
      await move([255, 0, 0], [0, 0, 0, 0, 0, 0], interval / 2);
      await move([255, 255, 255], [0, 0, 0, 0, 0, 0], interval / 2);

      resolve();
    } catch (err) {
      console.error(err);

      reject();
    }
  });
}

// Tilting its head
async function doHmm() {
  return new Promise(async (resolve, reject) => {
    const interval = 400;

    try {
      await move([255, 0, 255], [0, 0, 0, 0, 45, 0], interval / 2);
      await move([255, 0, 255], [0, 0, 0, 0, 45, 0], interval);
      await move([255, 0, 255], [0, 0, 0, 0, 45, 0], interval);
      await move([255, 0, 255], [0, 0, 0, 0, -45, 0], interval);
      await move([255, 0, 255], [0, 0, 0, 0, 0, 0], interval / 2);
      await move([255, 255, 255], [0, 0, 0, 0, 0, 0], interval / 2);

      resolve();
    } catch (err) {
      console.error(err);

      reject();
    }
  });
}

我是这样实现的,接下来,通过 Web API 调用点头、摇头和歪头动作。

app.js

python 复制代码
require('dotenv').config();

const express = require('express');
const { PythonShell } = require('python-shell');
const app = express();
const http = require('http').Server(app);

const PORT = 3000;

app.use(express.json());
app.use('/', express.static(`${ __dirname }/public`));

app.post('/yes', (req, res) => {
  doYes();
  res.send(200);
});

app.post('/no', (req, res) => {
  doNo();
  res.send(200);
});

app.post('/hmm', (req, res) => {
  doHmm();
  res.send(200);
});

// https://www.elephantrobotics.com/wp-content/uploads/2021/03/myCobot-User-Mannul-EN-V20210318.pdf
async function move(color = [255, 255, 255], angles = [0, 0, 0, 0, 0, 0], interval = duration) {
  return new Promise((resolve, reject) => {
    PythonShell.runString(
      `from pymycobot.mycobot import MyCobot; MyCobot('${ process.env.MY_COBOT_PORT }').set_color(${ color }); from pymycobot.mycobot import MyCobot; MyCobot('${ process.env.MY_COBOT_PORT }').send_angles([${ angles }], ${ duration })`,
      null
    ).then(() => {
      setTimeout(() => resolve(), interval);
    }).catch(() => {
      reject();
    });
  });
}

async function doYes() {
  return new Promise(async (resolve, reject) => {
    const interval = 200;

    try {
      await move([0, 0, 255], [0, 0, 0, 45, 0, 0], interval);
      await move([0, 0, 255], [0, 0, 0, 0, 0, 0], interval);
      await move([0, 0, 255], [0, 0, 0, 45, 0, 0], interval);
      await move([0, 0, 255], [0, 0, 0, 0, 0, 0], interval);
      await move([0, 0, 255], [0, 0, 0, 45, 0, 0], interval);
      await move([0, 0, 255], [0, 0, 0, 0, 0, 0], interval);
      await move([255, 255, 255], [0, 0, 0, 0, 0, 0], interval);

      resolve();
    } catch (err) {
      console.error(err);

      reject();
    }
  });
}

async function doNo() {
  return new Promise(async (resolve, reject) => {
    const interval = 400;

    try {
      await move([255, 0, 0], [0, 0, 0, 0, 45, 0], interval / 2);
      await move([255, 0, 0], [0, 0, 0, 0, -45, 0], interval);
      await move([255, 0, 0], [0, 0, 0, 0, 45, 0], interval);
      await move([255, 0, 0], [0, 0, 0, 0, -45, 0], interval);
      await move([255, 0, 0], [0, 0, 0, 0, 0, 0], interval / 2);
      await move([255, 255, 255], [0, 0, 0, 0, 0, 0], interval / 2);

      resolve();
    } catch (err) {
      console.error(err);

      reject();
    }
  });
}

async function doHmm() {
  return new Promise(async (resolve, reject) => {
    const interval = 400;

    try {
      await move([255, 0, 255], [0, 0, 0, 0, 45, 0], interval / 2);
      await move([255, 0, 255], [0, 0, 0, 0, 45, 0], interval);
      await move([255, 0, 255], [0, 0, 0, 0, 45, 0], interval);
      await move([255, 0, 255], [0, 0, 0, 0, -45, 0], interval);
      await move([255, 0, 255], [0, 0, 0, 0, 0, 0], interval / 2);
      await move([255, 255, 255], [0, 0, 0, 0, 0, 0], interval / 2);

      resolve();
    } catch (err) {
      console.error(err);

      reject();
    }
  });
}

try {
  doYes();
} catch(err) {
  console.error(err);
}

http.listen(PORT, '0.0.0.0');

有了这个设置、

向 `http://localhost:3000/yes\` 发送 POST 请求会让它点头。

向 `http://localhost:3000/no\` 发送 POST 请求会让它摇头。

向 `http://localhost:3000/hmm\` 发送 POST 请求会让它歪头。

将执行相应的操作。

DEMO

点头

摇头

歪着头

LED 矩阵的颜色也在悄然改变。

目前看起来是这样的,但如果再调整一下,效果可能会更好,尤其是头部的倾斜动作。

Github 存储库

https://github.com/kimizuka/mycobot-express/tree/example/timas-table

总结

我们非常感谢 Fumitaka Kimizuka 允许我们分享如此出色的技术案例研究。我们希望在阅读本文后,您能从中受到启发,创造出更多有趣而实用的项目。如果您有类似的想法或作品,请与我们分享,让我们共同推动技术进步和创新!

相关推荐
懒大王爱吃狼24 分钟前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
深度学习实战训练营29 分钟前
基于CNN-RNN的影像报告生成
人工智能·深度学习
秃头佛爷1 小时前
Python学习大纲总结及注意事项
开发语言·python·学习
昨日之日20062 小时前
Moonshine - 新型开源ASR(语音识别)模型,体积小,速度快,比OpenAI Whisper快五倍 本地一键整合包下载
人工智能·whisper·语音识别
浮生如梦_2 小时前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
深度学习lover2 小时前
<项目代码>YOLOv8 苹果腐烂识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·苹果腐烂识别
dayouziei3 小时前
java的类加载机制的学习
java·学习
热爱跑步的恒川3 小时前
【论文复现】基于图卷积网络的轻量化推荐模型
网络·人工智能·开源·aigc·ai编程
API快乐传递者3 小时前
淘宝反爬虫机制的主要手段有哪些?
爬虫·python
阡之尘埃5 小时前
Python数据分析案例61——信贷风控评分卡模型(A卡)(scorecardpy 全面解析)
人工智能·python·机器学习·数据分析·智能风控·信贷风控