写这玩意的初衷是我所在的某个群搭建了私有的 Mattermost 聊天环境来防御天朝网络环境日益严重的自我审查
程序一共有两个部分, QQ 部分依旧使用的是我们的老朋友Coolq HTTP API
通过 http api 进行发送,通过 Websocket 接受消息推送
Mattermost 部分同样是监听 Websocket 服务器并进行转发
当初写这个脚本时踩了很多关于 Python 多进程和协程的奇怪的坑,下面的代码为啥能正常跑我完全不知道(划掉)
下面是效果
写这玩意的初衷是我所在的某个群搭建了私有的 Mattermost 聊天环境来防御天朝网络环境日益严重的自我审查
程序一共有两个部分, QQ 部分依旧使用的是我们的老朋友Coolq HTTP API
通过 http api 进行发送,通过 Websocket 接受消息推送
Mattermost 部分同样是监听 Websocket 服务器并进行转发
当初写这个脚本时踩了很多关于 Python 多进程和协程的奇怪的坑,下面的代码为啥能正常跑我完全不知道(划掉)
下面是效果
很久以前就有写一个这玩意的想法了,前一阵子了解到了 Wolfram 搞了一个面向开发者的 Wolfram Engine,于是打算搞一个基于这个的 QQBot。 因为 Wolfram Engine 部署的位置和系统等因素,不知为何 Python 的 Wolfram Client 接口一计算就会报错,于是只能用简单粗暴的使用 提取命令 -> 创建 .wl
脚本 -> 解释运行并获取结果 这种十分不优雅的解决方法了。 仍然依赖 Coolq HTTP API 下面是代码
这篇博客源自我一个弃坑的项目,原计划是实现对 Bilibili 用户的收藏夹进行解析并自动下载其中的视频。 (代码只写了 API 解析部分,比较丢人,所以扔在 https://paste.ubuntu.com/p/PDpqqMN2vz/ 里了)
0x01 用户收藏夹 API
** 1.用户收藏夹列表 **
API 地址: https://api.bilibili.com/medialist/gateway/base/created?pn=1&ps=100&up_mid=[用户UID]&is_space=0&jsonp=jsonp
需要的 Headers 参数:
self.head = {
'Cookie' : cookie,
'User-Agent' : user_agent,
'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding' : 'gzip, deflate, br',
'Accept-Language' : 'zh-CN,zh;q=0.9',
'Cache-Control' : 'max-age=0',
'Host' : 'api.bilibili.com',
'Upgrade-Insecure-Requests' : '1'
}
返回的参数(以我自己 SpinMrY, 10688065
为例):
VEX 手柄共有四组按键与两组摇杆。 在 Robot C 中,手柄的操作也被抽象到一个数组 vexRT[] 上。 在这个数组中,按键以 BtnXY 命名,其中 X 代表按键属于哪一组,Y 代表按键具体的名称。比如 Btn7U 代表第七组按键的 U 键。而摇杆以通道 ChX 命名,其中 X 代表第几通道摇杆。比如 Ch1 代表第一通道的摇杆。 当一个按键按下时,vexRT 数组中对应下标的值会变为 1,而未按下时,数组对应下标的值为 0。 下面是判断一个按键是否被按下的代码,当按键 7U 被按下时,电机 port2 开始以最大速度正转,当按键被松开时,电机 port2 停止转动。
if(vexRT[Btn7U] == 1){
motor[port2] = 127;
}
else if(vexRT[Btn7U] == 0){
motor[port2] = 0;
}
摇杆输出的是一个线性变化的值,其区间大约在 $$[-127,127]$$ 之间,也就是说,我们可以将摇杆值直接赋值给电机,从而实现摇杆控制电机转速。
int speed = vexRT[Ch1];
motor[port2] = speed;
上面我们了解了如何通过编程获取手柄按键与摇杆的状态,下面我们将利用上面的知识开始实际操作。 假设我们的机器人有四个电机分别驱动机器人的前后左右四个轮子,我们将用两种方式通过摇杆控制机器人的运动。 以下的代码是双摇杆控制机器人运动的例子。通过两边摇杆的控制来使机器人比较灵活的前后运动与转弯。
#pragma config(Motor, port2, right_front, tmotorVex393_MC29, openLoop)
#pragma config(Motor, port7, left_back, tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor, port8, right_back, tmotorVex393_MC29, openLoop)
#pragma config(Motor, port9, left_front, tmotorVex393_MC29, openLoop, reversed)
int left_speed, right_speed, rtX, rtY;
const int noise = 15;//这里指摇杆的"噪音",即当摇杆值大于这个值时电机才会开始运动。
void DualJoystick(){
left_speed = vexRT[Ch3];
right_speed =vexRT[Ch2];
if(abs(left_speed) > noise && abs(right_speed) > noise){
motor[right_back] = -1 * right_speed;
motor[right_front] = -1 * right_speed;
motor[left_back] = -1 * left_speed;
motor[left_front] = -1 * left_speed;
}else{
motor[right_back] = 0;
motor[right_front] = 0;
motor[left_back] = 0;
motor[left_front] = 0;
}
}
而如果我们要使用单个摇杆控制,我们就要用到差速法,通过获取单个摇杆横竖两个通道的值,分别计算两侧轮子需要的功率,从而实现机器人灵活的操作。 下面是代码。
#pragma config(Motor, port2, right_front, tmotorVex393_MC29, openLoop)
#pragma config(Motor, port7, left_back, tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor, port8, right_back, tmotorVex393_MC29, openLoop)
#pragma config(Motor, port9, left_front, tmotorVex393_MC29, openLoop, reversed)
int left_speed, right_speed, rtX, rtY;
const int noise = 15;//这里指摇杆的"噪音",即当摇杆值大于这个值时电机才会开始运动。
void SingleJoystick(){
rtX = vexRT[Ch4];
rtY = vexRT[Ch3];
if(abs(rtX) > noise || abs(rtY) > noise){
if(rtY > -1 * noise){
left_speed = ((-1 * rtY) - rtX) >> 1;
right_speed = ((-1 * rtY) + rtX) >> 1;
}
else if(rtY < -1 * noise){
left_speed = ((-1 * rtY) + rtX) >> 1;
right_speed = ((-1 * rtY) - rtX) >> 1;
}
}
else{
right_speed = 0;
left_speed = 0;
}
motor[left_back] = left_speed;
motor[left_front] = left_speed;
motor[right_back] = right_speed;
motor[right_front] = right_speed;
}
rt,应老师要求,为了造福下届学弟学妹,特此写下此入门教程。(下届不是都用 V5 了吗(划掉)) 下面这篇教程相当于一个 Hello World 的例子,将通过程序驱动一个电机。
Robot C 中大部分基础语法与 C 语言相同,在此就不一一赘述了(其实是懒)。 一个简单的 Robot C 程序通常是以以下结构存在的:
#pragma config(blablablabla)
void fun(){
/*blablablabla*/
}
task main(){
/*blablablabla*/
}
其中 task 代表一个任务。Robot C 语言支持多任务,在后文中会对此进行介绍。 在将此程序烧写到主控盒后,程序会从 main() 任务开始执行。 在后面的教程中我将介绍有关 Robot C 的编程结构。
VEX EDR 主控共有十个电机端口,其中有八个为三线端口,其余两个为双线端口。 要通过程序控制电机,我们必须先配置电机。 在 Robot C 中,配置电机可以通过单击_Motor and Sensor Setup_按钮来配置,如图所示:
也可以通过以下代码来配置:
#pragma config(Motor, port2, left_front, tmotorVex393_MC29, openLoop, reversed)
配置完成后,即可开始编程来操控电机。
在 VEX Robot C 中,有一种十分方便的控制电机的方式,那就是 motor[] 数组。 通过使用motor[portX]
可以操控端口 X 电机的功率,其中赋值范围为 $$ [-127,127] $$ 。当赋值为负时,电机会反转。 比如,以下代码会使端口 2 的电机正转 1s 后反转 1s 最后停止。
motor[port2] = 127;//将电机 2 设置为最大功率正转
wait1Msec(1000);//此语句的作用为使主控盒延时 1000ms 再执行下面的语句
motor[port2] = -127;//将电机 2 设置为最大功率反转
wait1Msec(1000);
motor[port2] = 0;
以上就是控制电机的一种简单方法了,下面来让我们写一个完整的 VEX Robot C 程序。
#pragma config(Motor, port2, Left, tmotorVex393_MC29, openLoop)
task main(){
while(1){
motor[port2] = 127
wait1Msec(1000);
motor[port2] = -127;
wait1Msec(1000);
motor[port2] = 0;
}
}
首先确保主控盒烧写了同 Robot C 同版本的固件。 将主控盒通过数据线连接至计算机后,待到主控盒两个 LED 灯变为绿色后,点击 Compile Program 对程序进行重新编译,然后点击 Download 按钮开始烧写程序。