6自由度并联拉线写字机器人实现写字功能

news2024/11/24 23:12:53

1. 功能说明

      本文示例将实现R287样机6自由度并联拉线写字机器人写字(机器时代)的功能。

      该机器人有两部分:绘图机构、走纸机构。绘图机构由6个舵机模块近似正六边形位置分布,共同控制位于中心的画笔;还具备一个走纸机构,走纸机构是由一个大圆周舵机驱动的。

2. 6自由度并联拉线写字机器人逆解算法

      该6自由度并联拉线写字机器人的运动控制采用逆运动更容易一些,下面我们将对其逆运动算法进行介绍。我们先确定该6自由度并联拉线写字机器人的位置,通过建立坐标系的方法确定位置。这里我们选择在6自由度并联拉线写字机器人外一点建立一个直角坐标系,Z轴范围——笔架上下接线间距60,坐标系Z轴0点为7X11平板平面,这里面我们需要求解出每个舵机转动角度与画笔位置的关系:

      各舵机坐标(注意这里面的Z轴坐标是以实际作用到舵机上的为准)

          1(97,55,-10)

          2(25,200,50)

          3(97,345,-10)

          4(302,345,50)

          5(375,200,-10)

          6(302,55,50)

      中心点(x,y,z);目标点(xt,yt,zt);舵机半径 radius——24.0

 中心点到每个舵机的距离:

basic\_dist=\sqrt{(x-x_i)^2+(y-y_i)^2+(z-z_i)^2}

目标点到每个舵机的距离 :

dist=\sqrt{(x_t-x_i)^2+(y_t-y_i)^2+(z_t-z_i)^2}

 中心点到目标点舵机需要转动的角度(弧长公式):

degree=90.0+\frac{(dist-basic\_dist)\times 180}{M\_PI\times radius} +0.5

       其中90.0为笔在中心时舵机初始角度(这个很重要,舵机角度安装一定要注意),M_PI=3.1415926,0.5用于五入(为了补充运动过程中无法避免的损耗产生的运动误差)。

3. 电子硬件

     本实验中采用了以下硬件:

主控板

Basra主控板(兼容Arduino Uno)‍

扩展板

Bigfish2.1扩展板‍

电池7.4V锂电池

其它

画笔、画笔套管、连线、纸张等

电路连接说明: 舵机连接:按圆盘顺时针方向,舵机位置依次对应Bigfish扩展板的D4, D7, D11,D3, D8, D12

4. 功能实现

     编程环境:Arduino 1.8.19

下面提供一个6自由度并联拉线写字机器人写字(机器时代)的参考例程(servo_writing.ino):

/*------------------------------------------------------------------------------------

  版权说明:Copyright 2023 Robottime(Beijing) Technology Co., Ltd. All Rights Reserved.

           Distributed under MIT license.See file LICENSE for detail or copy at

           https://opensource.org/licenses/MIT

           by 机器谱 2023-04-20 https://www.robotway.com/

  ------------------------------*/

/*

* 舵机连接,按圆盘顺时针舵机位置依次对应Bigfish:4, 7, 11, 3, 8, 12

* 书写范围:dx --> 50; dy --> 40

*/

#include <Arduino.h>

#include <avr/pgmspace.h>

#include "model.h"

#include "words.h"

#include <Servo.h>


#define SQU 0

#define JI 1

#define QI 2

#define SHI 3

#define DAI 4


Servo myServo[SERVO_NUM];     //笔筒控制舵机数组

Servo myServo1;               //走纸舵机

Servo myServo2;               //压纸舵机

int servo_port[SERVO_NUM] = {4,7,11,3,8,12};   //笔筒控制舵机引脚   

int words_num[10] = {};   


Point squ[] = {};              //字体

Point ji[] = {};

Point qi[] = {};

Point shi[] = {};

Point dai[] = {};   


int pos_x = 0, pos_y = 1, pos_z = 2;


boolean pos_test = false;      //位置测试, 真为测试


void setup() {

  Serial.begin(9600);

  myServo1.attach(16);         //走纸舵机引脚

  myServo2.attach(17);         //压纸舵机引脚

  myServo1.write(88);          //走纸停

  pressServoDown();            //压纸

 

  if(pos_test) posTest();      //坐标位置测试

  wordsArrayLength();          //计算flash中存储的字体数组长度

  delay(1000);

}


void loop() {                  //写字

//   writing(SQU);

  writing(JI);                 //机

  writing(QI);                 //器

  writing(SHI);                //时

  writing(DAI);                //代

  while(1){};

}


void setPos(Point pos) {                               

  static const float _basic_dists[kActuatorCount] = {

    distance(kInitialPoint, kActuatorOrigins[0]),

    distance(kInitialPoint, kActuatorOrigins[1]),

    distance(kInitialPoint, kActuatorOrigins[2]),

    distance(kInitialPoint, kActuatorOrigins[3]),

    distance(kInitialPoint, kActuatorOrigins[4]),

    distance(kInitialPoint, kActuatorOrigins[5])

  };

  int degree[kActuatorCount] = {};

  for (int i = 0; i < kActuatorCount; ++i)

  {

    float dist = distance(pos, kActuatorOrigins[i]);

    float deg = 90.0 + (dist - _basic_dists[i]) /

                   kActuatorRadius / M_PI * 180.0;

    degree[i] = floor(deg+0.5);

  }

  for (int i = 0; i < kActuatorCount; ++i)

  {

    ServoGo(i, map(degree[i], 0, 180, 700, 2100));

  }

}


void writeLine(Point a, Point b, unsigned long t) {

  static const int dt = 50;

  unsigned long k = t / dt;

  float dx = (b.x - a.x) / (float)k;

  float dy = (b.y - a.y) / (float)k;

  Point p = a;

  for (int i = 0; i < k; ++i)

  {

    setPos(p);

    delay(dt);

    p.x += dx;

    p.y += dy;

  }

}


void ServoStart(int which)

{

  if(!myServo[which].attached())myServo[which].attach(servo_port[which]);

  pinMode(servo_port[which], OUTPUT);

}



void ServoStop(int which)

{

  myServo[which].detach();

  digitalWrite(servo_port[which],LOW);

}


void ServoGo(int which , int where)

{

    ServoStart(which);

    myServo[which].writeMicroseconds(where);

}


void posTest(){

//    setPos({175, 185, 20});   //最小坐标

//    delay(1000);

    setPos({200, 200, 50});   //中间坐标,确定笔的位置时可将位置设置为中间坐标,打开开关然后机械调整舵机角度直到笔筒在中间位置即可

    delay(1000);

//    setPos({225, 225, 20});   //最大坐标

//    delay(1000);


    while(1){delay(10);};

}


void wordsArrayLength(){

   words_num[0] = sizeof(squArray) / sizeof(squArray[0]) / 3;

   words_num[1] = sizeof(jiArray) / sizeof(jiArray[0]) / 3;             //机

   words_num[2] = sizeof(qiArray) / sizeof(qiArray[0]) / 3;             //器

   words_num[3] = sizeof(shiArray) / sizeof(shiArray[0]) / 3;           //时

   words_num[4] = sizeof(daiArray) / sizeof(daiArray[0]) / 3;           //代

}


void readProgmem(int p, Point a, Point b, int ary[]){

    a.x = pgm_read_word_near( ary + p * 3 + pos_x) + 175;

    a.y = pgm_read_word_near( ary + p * 3 + pos_y) + 185;

    a.z = pgm_read_word_near( ary + p * 3 + pos_z);

   

    b.x = pgm_read_word_near( ary + (p + 1) * 3 + pos_x) + 175;

    b.y = pgm_read_word_near( ary + (p + 1) * 3 + pos_y) + 185;

    b.z = pgm_read_word_near( ary + (p + 1) * 3 + pos_z);

   

    writeLine(a, b, 500);


//    Serial.print(a.x);  

//    Serial.print("_");

//    Serial.print(a.y);

//    Serial.print(" ");

//    Serial.print(b.x);  

//    Serial.print("_");

//    Serial.println(b.y);

}


void writing(int which){

  for(int i=0;i<words_num[which] - 1;i++){

    switch(which){

        case 0:

          readProgmem(i, squ[i], squ[i+1], squArray);

        break;

        case 1:

          readProgmem(i, ji[i], ji[i+1], jiArray);

        break;

        case 2:

          readProgmem(i, qi[i], qi[i+1], qiArray);

        break;

        case 3:

          readProgmem(i, shi[i], shi[i+1], shiArray);

        break;

        case 4:

          readProgmem(i, dai[i], dai[i+1], daiArray);

        break;

    }

    pos_x = 0;

    pos_y = 1;

    pos_z = 2;

  }

  setPos({200, 200, 50});

  delay(1000);

  pressServoUp();

  delay(100);

  positionSwitch();

  pressServoDown();

}


void positionSwitch(){                //走纸函数

    myServo1.write(80);

    delay(500);

    myServo1.write(88);

    delay(100);

}


void pressServoDown(){                //压杆落

  myServo2.write(70);  

}


void pressServoUp(){                  //压杆抬

  myServo2.write(75);  

}

5. 资料内容

①写字-例程源代码

②写字-样机3D文件

资料内容详见:6自由度并联拉线写字机器人-写字

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/531084.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java进阶-面向对象进阶(多态包权限修饰符代码块)

1 多态 1.1 多态的形式 多态是继封装、继承之后&#xff0c;面向对象的第三大特性。 多态是出现在继承或者实现关系中的。 多态体现的格式&#xff1a; 父类类型 变量名 new 子类/实现类构造器(); 变量名.方法名();多态的前提&#xff1a;有继承关系&#xff0c;子类对象…

数显压力开关NISE30A、PS42、NZSE30A

数显压力开关是一种具有高精度和可靠性的压力开关&#xff0c;广泛应用于工业自动化、石油化工、电力系统等领域。它通过测量压力并将信号转换为数字形式来控制设备或系统的运行。 数显压力开关的主要组成部分包括传感器、微处理器、显示器和输出电路等。传感器通常采用压阻式…

助力 VR/AR 等复杂图像场景极致高清,火山引擎夺得 NTIRE 大赛双料冠军

动手点关注 干货不迷路 近日&#xff0c;CVPR Workshop 下属的 NTIRE2023大赛公布比赛结果&#xff0c;在双目超分双三次插值保真赛道和 360 全景图像超分赛道上&#xff0c;火山引擎多媒体实验室凭借自主研发的算法获得了双料冠军&#xff0c;技术能力达到行业领先水平。 NTIR…

GEE:基于Landsat影像的长时间序列构建(1985-2020NDVI年度合成时间序列)

作者:CSDN @ _养乐多_ 本文记录的代码是一个用于构建年度合成影像集合的脚本。它通过调用一系列函数来获取给定时间范围内的 Landsat 影像集合,并进行预处理和合成。其中包括光谱指数计算、波段调整、遥感影像的中值合成等步骤。 结果如下图所示, 脚本的主要步骤如下: 定…

我让gpt写了一段正则表达式代码,可是运行报错,可以帮忙看看哪里出了问题?...

点击上方“Python爬虫与数据挖掘”&#xff0c;进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 忽闻海上有仙山&#xff0c;山在虚无缥缈间。 大家好&#xff0c;我是皮皮。 一、前言 前几天在Python最强王者群【HZL】问了一个Python正则表达式的问…

如何避免旧代码成包袱?5步教你接手别人的系统

&#x1f449;腾小云导读 老系统的代码&#xff0c;是每一个程序员都不想去触碰的领域&#xff0c;秉着能跑就行的原则&#xff0c;任由其自生自灭。本期就给大家讲讲&#xff0c;接手一套故障频发的复杂老系统需要从哪些地方着手。内容包括&#xff1a;代码串讲、监控建设和告…

一文搞懂!如何高效微调你的 LLM

作者 | guolipa 整理 | NewBeeNLP 公众号 https://zhuanlan.zhihu.com/p/621700272 当前以 ChatGPT 为代表的预训练语言模型&#xff08;PLM&#xff09;规模变得越来越大&#xff0c;在消费级硬件上进行全量微调&#xff08;Full Fine-Tuning&#xff09;变得不可行。此外&am…

NIPS2022|南京大学提出基于点击后行为的广义延迟反馈模型

Generalized Delayed Feedback Model with Post-Click Information in Recommender Systems Jia-Qi Yang De-Chuan Zhan Nanjing University https://proceedings.neurips.cc/paper_files/paper/2022/file/a7f90da65dd41d699d00e95700e6fa1e-Paper-Conference.pdf 转化率预估&a…

记录--css水滴登录界面

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 前言 今天我们来分享一款非常有趣的登录界面&#xff0c;它使用HTML和CSS制作&#xff0c;具有动态的水波纹效果&#xff0c;让用户在登录时感受到了一股清凉之感。 基本html框架 <!DOCTYPE html&g…

营收“新高”盈利“新低”,东软还能“硬起来”吗?

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 “2022年是商业环境艰难和动荡的一年。在过去的一年中&#xff0c;东软集团面对经济下行压力、汇率双向波动等诸多外部不确定性因素的影响&#xff0c;特别是第四季度的影响&#xff0c;使得东软的业务和项目节奏被严重拖累…

Spring Security 基本介绍及基础项目搭建

目录 SpringSecurity 框架简介 概要 历史 同款产品对比shiro SpringSecurity 入门案例 创建一个项目 添加一个配置类 运行这个项目 权限管理中的相关概念 SpringSecurity 基本原理 过滤器链 ​编辑 UserDetailsService 接口讲解 PasswordEncoder 接口讲解 Spri…

软件工程(三)-统一过程与敏捷方法

1、统一过程 统一过程也叫UP或者RUP。这种开发方法是在基于构建的方法发展而来&#xff0c;也是基于构建化的思想发展而来。 统一过程的三大特点 用例驱动 在进行软件开发过程中&#xff0c;是用什么驱动力去推动整个过程 用例驱动就是一开始会构建用例&#xff0c;然后一步一…

人脸识别2:InsightFace实现人脸识别Face Recognition(含源码)

目录 1. 前言 2. 项目安装 3. 人脸识别系统 &#xff08;1&#xff09;人脸检测和关键点检测 &#xff08;2&#xff09;人脸校准 &#xff08;3&#xff09;人脸特征提取 &#xff08;4&#xff09;人脸比对(1:1) &#xff08;5&#xff09;人脸搜索(1:N) &#xff08…

【操作系统】文件管理

文章目录 文件管理初识文件的属性文件内部的数据如何组织起来&#xff1f;文件之间应该如何组织起来&#xff1f;操作系统应该向上提供哪些功能&#xff1f;从上往下看&#xff0c;文件应该如何存放在外存&#xff1f;其他需要由操作系统实现的文件管理功能 文件的逻辑结构无结…

【CVPR 2023的AIGC应用汇总(8)】3D相关(编辑/重建/生成) diffusion扩散/GAN生成对抗网络方法...

【CVPR 2023的AIGC应用汇总(7)】face相关&#xff08;换脸/编辑/恢复&#xff09; diffusion扩散/GAN生成对抗 【CVPR 2023的AIGC应用汇总(6)】医学图像diffusion扩散/GAN生成对抗网络 【CVPR 2023的AIGC应用汇总(5)】语义布局可控生成&#xff0c;基于diffusion扩散/GAN生成对…

Java数据库项目之满汉楼

文章和代码已经归档至【Github仓库&#xff1a;https://github.com/timerring/java-tutorial 】或者公众号【AIShareLab】回复 java 也可获取。 文章目录 程序框架图代码实现数据库Java多表查询思路 程序框架图 代码实现 数据库 -- 创建满汉楼的数据库 CREATE DATABASE mhl -…

输入输出IO流

文章目录 1.数据源2.流3.IO流的分类4.字节流4.1文件字节输入流1. FileInputStream类概述2. FileInputStream类构造方法3. FileInputStream类常用方法 4.2文件字节输出流1. FileOutputStream类概述2. FileOutputStream类构造方法3. FileOutputStream类常用方法 5字符流5.1. File…

philsolophy of life: blessing in disguise

有个成语叫: "塞翁失马" , 这个讲的是在战国时期&#xff0c;有个叫"塞翁"的老人养了很多马&#xff0c;有一天他丢了一匹马&#xff0c;邻居来劝说他&#xff0c;不要着急&#xff0c;说不定哪天就回来了&#xff0c;"丢了一匹马或许是好事&#xf…

【壁纸小程序】推荐一款壁纸小程序

壁纸很多 直接在手机切换下载即可 感兴趣的朋友可以看看 小程序二维码

第五章 介绍Productions - 业务流程和业务逻辑

文章目录 第五章 介绍Productions - 业务流程和业务逻辑业务流程和业务逻辑介绍业务流程的类型数据转换业务规则 第五章 介绍Productions - 业务流程和业务逻辑 业务流程和业务逻辑 本章描述业务流程中支持的逻辑种类。 介绍 业务流程是production的中间部分。它们接受来自…