又是一次课程学习的结束,辅导学生的过程也很受益,温故而知新。该组同学需要Arduino控制多达6个舵机,而且基于距离这一参数,在不同距离值之间会有不同的触发事件,也就是6个舵机转的角度都有所不同,而且还伴随着几盏灯的变化。灯的变化我在这篇文章中就略去以后谈,就以控制舵机来做一总结。我首先用Processing来模拟这一过程。因为Processing可以借Arduino(Firmata)库来实现P5代理Arduino运作,后期可直接使用该模型控制舵机,倘若不用该库,直接移植到C/C++ 语言系统中编写Arduino程序执行运作也非常方便。因此模拟的这一举措是值得参考的。

开始

首先要规划好每个状态,实质上这有点创建状态机的味道,但是因为这是学生想要做的交互模型,这次就从简了。不同区间所触发的事件见下表所示:

当然表格中的数值是我想当然的,暂且就这么定。

【1】 分了5块区域,分别去检测距离值distance是否在该区域,作相应动作

【2】 一种6个舵机 ---- 上方3个 UP-A UP-B UP-C 下方3个 DOWN-A DOWN-B DOWN-C

编写

变量声明

/////////////////////////////
// 6个舵机 信号引脚 定义
/////////////////////////////
final int UP_A_SERVO = 11;
final int UP_B_SERVO = 10;
final int UP_C_SERVO = 9;
final int DOWN_A_SERVO = 6;
final int DOWN_B_SERVO = 5;
final int DOWN_C_SERVO = 3; ///////////////////////////////
// 6个舵机 实际角度 声明定义
///////////////////////////////
float UP_A_SERVO_rot = 0;
float UP_B_SERVO_rot = 0;
float UP_C_SERVO_rot = 0;
float DOWN_A_SERVO_rot = 0;
float DOWN_B_SERVO_rot = 0;
float DOWN_C_SERVO_rot = 0; ///////////////////////////////
// 6个舵机 目标角度 声明定义
///////////////////////////////
float UP_A_SERVO_rot_target = 0;
float UP_B_SERVO_rot_target = 0;
float UP_C_SERVO_rot_target = 0;
float DOWN_A_SERVO_rot_target = 0;
float DOWN_B_SERVO_rot_target = 0;
float DOWN_C_SERVO_rot_target = 0; // 检测的距离 待输入
int distance = 0;
// 缓动系数,控制数值变化快慢
float easing = 0.02; //////////////////////////////////////
// 方便计算每帧流逝的时间,方便计时
//////////////////////////////////////
float nowtime;
float oldtime;
float deltatime;
float timer; // 计时器,具体数值代表总流逝的时间 // 状态量 距离数值的区间
//*******************
// 0 缺省
// 1 区间1
// 2 区间2
// 3 区间3
// 4 区间4
// 5 区间5
//*******************
int state = 0; // 计时器触发次数的计数
int tempindex = 0; // 方便检测区间变动的触发[事件]
int frame4state1 = 0;
int frame4state2 = 0;
int frame4state3 = 0;
int frame4state4 = 0;
int frame4state5 = 0; // 声明一个改变数值变化模式的开关量
// false - 线性变化
// true - 缓动变化
// 待完善 可改为枚举,创建多种方式
boolean valueChangeKey = false;
//////////////////////////////////////
// 定义每区间极值 最小 最大
//////////////////////////////////////
final static int DurA1 = 0;
final static int DurB1 = 50; final static int DurA2 = 50;
final static int DurB2 = 100; final static int DurA3 = 100;
final static int DurB3 = 200; final static int DurA4 = 200;
final static int DurB4 = 400; final static int DurA5 = 400;
final static int DurB5 = 500; ///////////////////////////////////////////////
// 临时变量 表示代表更换区间展示的UI方框透明度
///////////////////////////////////////////////
float value4durChange_1 = 0;
float value4durChange_2 = 0;
float value4durChange_3 = 0;
float value4durChange_4 = 0;
float value4durChange_5 = 0; //////////////////////////////////////
// 临时变量 表示每舵机变化时的状态
//////////////////////////////////////
float value4ServoState_1 = 0;
float value4ServoState_2 = 0;
float value4ServoState_3 = 0;
float value4ServoState_4 = 0;
float value4ServoState_5 = 0;
float value4ServoState_6 = 0; ////////////////////////////////////////////
// 临时变量 表示每舵机可视化UI的方框透明度
////////////////////////////////////////////
float value4ServoChange_1 = 0;
float value4ServoChange_2 = 0;
float value4ServoChange_3 = 0;
float value4ServoChange_4 = 0;
float value4ServoChange_5 = 0;
float value4ServoChange_6 = 0; ////////////////////////////////////////////////////
// 临时变量 表示每舵机更改目标参数时的触发事件开关
////////////////////////////////////////////////////
boolean temp4changekey_1 = false;
boolean temp4changekey_2 = false;
boolean temp4changekey_3 = false;
boolean temp4changekey_4 = false;
boolean temp4changekey_5 = false;
boolean temp4changekey_6 = false;

重要函数

// 线性数值变化
float getLinearValue(float x, float tx)
{
if (x < tx)
x += 1;
else if (x > tx)
x -= 1;
else
x = tx; return x;
} // 更新状态
void updateState() {
if (state == 0) {
frame4state1 = 0;
frame4state2 = 0;
frame4state3 = 0;
frame4state4 = 0;
frame4state5 = 0;
}
if (state == 1) {
//frame4state1 = 0;
frame4state2 = 0;
frame4state3 = 0;
frame4state4 = 0;
frame4state5 = 0;
}
if (state == 2) {
frame4state1 = 0;
//frame4state2 = 0;
frame4state3 = 0;
frame4state4 = 0;
frame4state5 = 0;
}
if (state == 3) {
frame4state1 = 0;
frame4state2 = 0;
//frame4state3 = 0;
frame4state4 = 0;
frame4state5 = 0;
}
if (state == 4) {
frame4state1 = 0;
frame4state2 = 0;
frame4state3 = 0;
//frame4state4 = 0;
frame4state5 = 0;
} if (state == 5) {
frame4state1 = 0;
frame4state2 = 0;
frame4state3 = 0;
frame4state4 = 0;
//frame4state5 = 0;
}
} // 处理状态
void handleState() { if (state == 2)
{
timer += deltatime;
if (timer > 2000)
{
timer = 0;
tempindex ++; if (tempindex == 1) {
DOWN_B_SERVO_rot_target = 90;
value4ServoState_5 = 5; // 既是触发状态,又是计数5[可看成5帧],下同
} if (tempindex == 2) {
DOWN_C_SERVO_rot_target = 90;
value4ServoState_6 = 5;
}
}
} if (state == 3)
{
timer += deltatime;
if (timer > 2000)
{
timer = 0;
tempindex ++; if (tempindex == 1) {
DOWN_A_SERVO_rot_target = 90;
value4ServoState_4 = 5;
} if (tempindex == 2) {
DOWN_B_SERVO_rot_target = 90;
value4ServoState_5 = 5;
} if (tempindex == 3) {
DOWN_C_SERVO_rot_target = 90;
value4ServoState_6 = 5;
}
}
} if (state == 4)
{
timer += deltatime;
if (timer > 2000)
{
timer = 0;
tempindex ++; if (tempindex == 1) {
DOWN_B_SERVO_rot_target = 0;
value4ServoState_5 = 5;
} if (tempindex == 2) {
DOWN_A_SERVO_rot_target = 0;
value4ServoState_4 = 5;
}
}
}
} // 更新每区间
void updatePerDuring() {
//*************
// DUR 1
//************* if (distance >= DurA1 && distance < DurB1)
{
if (frame4state1 == 0) { //这里的if判断结构代表区间变化所触发的事件[执行一次],下同
tempindex = 0;
timer = 0;
value4durChange_1 = 250; value4ServoState_1 = 5;
value4ServoState_2 = 5;
value4ServoState_3 = 5;
value4ServoState_4 = 5;
value4ServoState_5 = 5;
value4ServoState_6 = 5;
}
frame4state1 ++;
state = 1; UP_A_SERVO_rot_target = 30;
UP_B_SERVO_rot_target = 90;
UP_C_SERVO_rot_target = 150;
DOWN_A_SERVO_rot_target = 0;
DOWN_B_SERVO_rot_target = 0;
DOWN_C_SERVO_rot_target = 0;
} //*************
// DUR 2
//************* if (distance >= DurA2 && distance < DurB2)
{
if (frame4state2 == 0) {
tempindex = 0;
timer = 0;
value4durChange_2 = 250;
value4ServoState_1 = 5;
value4ServoState_2 = 5;
value4ServoState_3 = 5;
value4ServoState_4 = 5;
}
frame4state2 ++; state = 2; UP_A_SERVO_rot_target = 50;
UP_B_SERVO_rot_target = 80;
UP_C_SERVO_rot_target = 120; if (tempindex == 0) {
DOWN_A_SERVO_rot_target = 90;
}
} //*************
// DUR 3
//************* if (distance >= DurA3 && distance < DurB3) {
if (frame4state3 == 0) {
tempindex = 0;
timer = 0;
value4durChange_3 = 250; value4ServoState_1 = 5;
value4ServoState_2 = 5;
value4ServoState_3 = 5;
}
frame4state3 ++; state = 3; UP_A_SERVO_rot_target = 0;
UP_B_SERVO_rot_target = 0;
UP_C_SERVO_rot_target = 0;
} //*************
// DUR 4
//************* if (distance >= DurA4 && distance < DurB4) {
if (frame4state4 == 0) {
tempindex = 0;
timer = 0;
value4durChange_4 = 250;
value4ServoState_1 = 5;
value4ServoState_2 = 5;
value4ServoState_3 = 5;
value4ServoState_6 = 5;
}
frame4state4 ++; state = 4;
UP_A_SERVO_rot_target = 0;
UP_B_SERVO_rot_target = 0;
UP_C_SERVO_rot_target = 0; if (tempindex == 0) {
DOWN_C_SERVO_rot_target = 0;
}
} //*************
// DUR 5
//************* if (distance >= DurA5 && distance < DurB5) {
if (frame4state5 == 0) {
tempindex = 0;
timer = 0;
value4durChange_5 = 250; value4ServoState_1 = 5;
value4ServoState_2 = 5;
value4ServoState_3 = 5;
value4ServoState_4 = 5;
value4ServoState_5 = 5;
value4ServoState_6 = 5;
}
frame4state5 ++; state = 5; UP_A_SERVO_rot_target = 0;
UP_B_SERVO_rot_target = 0;
UP_C_SERVO_rot_target = 0;
DOWN_A_SERVO_rot_target = 0;
DOWN_B_SERVO_rot_target = 0;
DOWN_C_SERVO_rot_target = 0;
}
}

绘画函数

// 绘制区间变化时的事件切换[描述]
void updateDuringChangeEffect() {
push();
noStroke();
fill(250, 0, 0, value4durChange_1);
rect(0+DurA1, height/2-20, DurB1-DurA1, 20);
pop();
push();
noStroke();
fill(250, 0, 0, value4durChange_2);
rect(0+DurA2, height/2-20, DurB2-DurA2, 20);
pop();
push();
noStroke();
fill(250, 0, 0, value4durChange_3);
rect(0+DurA3, height/2-20, DurB3-DurA3, 20);
pop();
push();
noStroke();
fill(250, 0, 0, value4durChange_4);
rect(0+DurA4, height/2-20, DurB4-DurA4, 20);
pop();
push();
noStroke();
fill(250, 0, 0, value4durChange_5);
rect(0+DurA5, height/2-20, DurB5-DurA5, 20);
pop(); value4durChange_1 -= 12;
value4durChange_2 -= 12;
value4durChange_3 -= 12;
value4durChange_4 -= 12;
value4durChange_5 -= 12;
value4durChange_1 = constrain(value4durChange_1, 0, 255);
value4durChange_2 = constrain(value4durChange_2, 0, 255);
value4durChange_3 = constrain(value4durChange_3, 0, 255);
value4durChange_4 = constrain(value4durChange_4, 0, 255);
value4durChange_5 = constrain(value4durChange_5, 0, 255);
} // 绘制每舵机被定义新角度时的触发事件[描述]
void updateServoDefinedEvent()
{ //1
if (value4ServoState_1 == 5)
{
temp4changekey_1 = true;
}
if (temp4changekey_1)
{
value4ServoState_1 -= 1; if (value4ServoState_1 > 0) {
value4ServoChange_1 = 230;
} else {
value4ServoChange_1 = 0;
temp4changekey_1 = false;
}
}
// 2
////////////////////
if (value4ServoState_2 == 5)
{
temp4changekey_2 = true;
}
if (temp4changekey_2)
{
value4ServoState_2 -= 1; if (value4ServoState_2 > 0) {
value4ServoChange_2 = 230;
} else {
value4ServoChange_2 = 0;
temp4changekey_2 = false;
}
} // 3
////////////////////
if (value4ServoState_3 == 5)
{
temp4changekey_3 = true;
}
if (temp4changekey_3)
{
value4ServoState_3 -= 1; if (value4ServoState_3 > 0) {
value4ServoChange_3 = 230;
} else {
value4ServoChange_3 = 0;
temp4changekey_3 = false;
}
} // 4
////////////////////
if (value4ServoState_4 == 5)
{
temp4changekey_4 = true;
}
if (temp4changekey_4)
{
value4ServoState_4 -= 1; if (value4ServoState_4 > 0) {
value4ServoChange_4 = 230;
} else {
value4ServoChange_4 = 0;
temp4changekey_4 = false;
}
} // 5
////////////////////
if (value4ServoState_5 == 5)
{
temp4changekey_5 = true;
}
if (temp4changekey_5)
{
value4ServoState_5 -= 1; if (value4ServoState_5 > 0) {
value4ServoChange_5 = 230;
} else {
value4ServoChange_5 = 0;
temp4changekey_5 = false;
}
}
// 6
////////////////////
if (value4ServoState_6 == 5)
{
temp4changekey_6 = true;
}
if (temp4changekey_6)
{
value4ServoState_6 -= 1; if (value4ServoState_6 > 0) {
value4ServoChange_6 = 230;
} else {
value4ServoChange_6 = 0;
temp4changekey_6 = false;
}
} push();
translate(0, 0);
fill(250, value4ServoChange_1);
rect(200, 35, 20, 20);
pop();
push();
translate(0, 30);
fill(250, value4ServoChange_2);
rect(200, 35, 20, 20);
pop();
push();
translate(0, 30*2);
fill(250, value4ServoChange_3);
rect(200, 35, 20, 20);
pop();
push();
translate(0, 30*3);
fill(250, value4ServoChange_4);
rect(200, 35, 20, 20);
pop();
push();
translate(0, 30*4);
fill(250, value4ServoChange_5);
rect(200, 35, 20, 20);
pop();
push();
translate(0, 30*5);
fill(250, value4ServoChange_6);
rect(200, 35, 20, 20);
pop();
} ////////////////////////////////////////////////////////////////////////////
//DRAW FUNCTION
//////////////////////////////////////////////////////////////////////////// void drawUI(){ updateDuringChangeEffect();
updateServoDefinedEvent(); //*************
// 区间
//************* push();
//noStroke();
stroke(250);
strokeWeight(2);
fill(250, 50);
rect(0, height/2, DurB1-DurA1, height/2);
pop();
push();
//noStroke(); stroke(250);
strokeWeight(2);
fill(250, 50);
rect(0+DurA2, height/2, DurB2-DurA2, height/2);
pop();
push();
//noStroke(); stroke(250);
strokeWeight(2);
fill(250, 50);
rect(0+DurA3, height/2, DurB3-DurA3, height/2);
pop();
push();
//noStroke(); stroke(250);
strokeWeight(2);
fill(250, 50);
rect(0+DurA4, height/2, DurB4-DurA4, height/2);
pop();
push();
//noStroke(); stroke(250);
strokeWeight(2);
fill(250, 50);
rect(0+DurA5, height/2, DurB5-DurA5, height/2);
pop(); //*************
// 区间
//************* switch(state)
{
case 1:
push();
noStroke();
fill(250, 220);
rect(0+DurA1, height/2, DurB1-DurA1, height/2);
pop();
break;
case 2:
push();
noStroke();
fill(250, 220);
rect(0+DurA2, height/2, DurB2-DurA2, height/2);
pop();
break;
case 3:
push();
noStroke();
fill(250, 220);
rect(0+DurA3, height/2, DurB3-DurA3, height/2);
pop();
break;
case 4:
push();
noStroke();
fill(250, 220);
rect(0+DurA4, height/2, DurB4-DurA4, height/2);
pop();
break;
case 5:
push();
noStroke();
fill(250, 220);
rect(0+DurA5, height/2, DurB5-DurA5, height/2);
pop();
break;
} push();
translate(0, 0);
fill(250, 100);
rect(200, 35, 20, 20);
pop();
push();
translate(0, 30);
fill(250, 100);
rect(200, 35, 20, 20);
pop();
push();
translate(0, 30*2);
fill(250, 100);
rect(200, 35, 20, 20);
pop();
push();
translate(0, 30*3);
fill(250, 100);
rect(200, 35, 20, 20);
pop();
push();
translate(0, 30*4);
fill(250, 100);
rect(200, 35, 20, 20);
pop();
push();
translate(0, 30*5);
fill(250, 100);
rect(200, 35, 20, 20);
pop();
/*
text("UP_A_SERVO - " + round(UP_A_SERVO_rot), 50, 50);
text("UP_B_SERVO - " + round(UP_B_SERVO_rot), 50, 50+30*1);
text("UP_C_SERVO - " + round(UP_C_SERVO_rot), 50, 50+30*2);
text("DOWN_A_SERVO - " + round(DOWN_A_SERVO_rot), 50, 50+30*3);
text("DOWN_B_SERVO - " + round(DOWN_B_SERVO_rot), 50, 50+30*4);
text("DOWN_C_SERVO - " + round(DOWN_C_SERVO_rot), 50, 50+30*5);
*/ // 字符描述 舵机 旋转角度
text("UP_A_SERVO - " + round(UP_A_SERVO_rot), 50, 50);
text("UP_B_SERVO - " + round(UP_B_SERVO_rot), 50, 50+30*1);
text("UP_C_SERVO - " + round(UP_C_SERVO_rot), 50, 50+30*2);
text("DOWN_A_SERVO - " + round(DOWN_A_SERVO_rot), 50, 50+30*3);
text("DOWN_B_SERVO - " + round(DOWN_B_SERVO_rot), 50, 50+30*4);
text("DOWN_C_SERVO - " + round(DOWN_C_SERVO_rot), 50, 50+30*5); }

主页签

void setup() {
size(460, 500);
} void draw() { //刷新画布
background(0);
//鼠标模拟测距
if (mouseY >= height/2) {
distance = mouseX;
} //计算deltatime 每帧流逝时间
//方便计时
nowtime = millis();
deltatime = nowtime - oldtime;
oldtime = nowtime; updateState(); //刷新状态
handleState(); //执行状态 // 更新每区间
updatePerDuring(); if (valueChangeKey)
{
UP_A_SERVO_rot += (UP_A_SERVO_rot_target - UP_A_SERVO_rot) * easing;
UP_B_SERVO_rot += (UP_B_SERVO_rot_target - UP_B_SERVO_rot) * easing;
UP_C_SERVO_rot += (UP_C_SERVO_rot_target - UP_C_SERVO_rot) * easing; DOWN_A_SERVO_rot += (DOWN_A_SERVO_rot_target - DOWN_A_SERVO_rot) * easing;
DOWN_B_SERVO_rot += (DOWN_B_SERVO_rot_target - DOWN_B_SERVO_rot) * easing;
DOWN_C_SERVO_rot += (DOWN_C_SERVO_rot_target - DOWN_C_SERVO_rot) * easing;
} else
{
UP_A_SERVO_rot = getLinearValue(UP_A_SERVO_rot, UP_A_SERVO_rot_target);
UP_B_SERVO_rot = getLinearValue(UP_B_SERVO_rot, UP_B_SERVO_rot_target);
UP_C_SERVO_rot = getLinearValue(UP_C_SERVO_rot, UP_C_SERVO_rot_target); DOWN_A_SERVO_rot = getLinearValue(DOWN_A_SERVO_rot, DOWN_A_SERVO_rot_target);
DOWN_B_SERVO_rot = getLinearValue(DOWN_B_SERVO_rot, DOWN_B_SERVO_rot_target);
DOWN_C_SERVO_rot = getLinearValue(DOWN_C_SERVO_rot, DOWN_C_SERVO_rot_target);
} UP_A_SERVO_rot = constrain(UP_A_SERVO_rot, 0, 180);
UP_B_SERVO_rot = constrain(UP_B_SERVO_rot, 0, 180);
UP_C_SERVO_rot = constrain(UP_C_SERVO_rot, 0, 180);
DOWN_A_SERVO_rot = constrain(DOWN_A_SERVO_rot, 0, 180);
DOWN_B_SERVO_rot = constrain(DOWN_B_SERVO_rot, 0, 180);
DOWN_C_SERVO_rot = constrain(DOWN_C_SERVO_rot, 0, 180);
// 绘制 UI
drawUI();
} void keyPressed() {
if (key == '1') { //按【1】改变数值过渡方式 线性/缓动
valueChangeKey = !valueChangeKey;
println(valueChangeKey); // 防止 小数值干扰最后四舍五入,且确保数值区间
UP_A_SERVO_rot = constrain(round(UP_A_SERVO_rot), 0, 180);
UP_B_SERVO_rot = constrain(round(UP_B_SERVO_rot), 0, 180);
UP_C_SERVO_rot = constrain(round(UP_C_SERVO_rot), 0, 180);
DOWN_A_SERVO_rot = constrain(round(DOWN_A_SERVO_rot), 0, 180);
DOWN_B_SERVO_rot = constrain(round(DOWN_B_SERVO_rot), 0, 180);
DOWN_C_SERVO_rot = constrain(round(DOWN_C_SERVO_rot), 0, 180);
}
}

小结

上节源码中有足够的注释,这里就不多赘述。其实思路很清晰,6个舵机每次都随6种状态改变预想的角度值[目标值],不过有些状态会随计时系统慢慢推进。另外在数值上设立了线性变化和缓动变化两种过渡方式。

如果再增设硬件,比如再多点舵机控制,那么最好是上class 类,也就是把相关函数抽象成类中方法,遍历运行。而且这将是一个系统,包含有事件机制、数值分析与处理、状态机等。不过该篇这样写对于初学者,尤其是在校学生而言,更有参考价值。当然啦,这是纸上谈兵式的模拟演示,要真正接线再上实物那可还得花大量精力和时间,加油共勉

附上最后的模拟效果 ----

顺序

无序

Processing模拟控制多台舵机-以距离为参数 程序参考的更多相关文章

  1. Linux模拟控制网络时延

    之前以为可以使用Linux自带的工具模拟控制网络时延,所以上网找了一些资料.后来发现,找到的资料目前只支持在一个网卡上模拟发送报文的时延,而不能设置有差别的网络时延,或者说当要模拟的向A发送的时延与要 ...

  2. 台达PLC实现远程下载程序

    台达PLC实现远程下载程序 日期:2019-04-27                    时间    08:33:57 让物联变得更简单 18-09-2411:25 明明在公司调试没问题的设备一到 ...

  3. BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。面向切面 将声明性事务管理集成到应用程序中

    Spring 系列: Spring 框架简介 https://www.ibm.com/developerworks/cn/java/wa-spring1/ Spring 框架简介 Spring AOP ...

  4. Synergy – 教你在局域网中用一套键盘/鼠标控制多台电脑

    想必很多人都拥有多台电脑,譬如台式机+笔记本,很多时候我们都会同时打开它们工作.可是你有没发现,如果桌子上摆放着多台电脑多套键盘鼠标,不停来回切换使用是否很累呢?如果说现在可以只用一套键鼠,就能同时控 ...

  5. python-web-selenium模拟控制浏览器

    用 selenium 模块控制浏览器 启动 selenium 控制的浏览器 from selenium import webdriver brower = webdriver.Firefox() br ...

  6. 一个鼠标键盘控制两台甚至多台主机的方法--Synergy

    在多台主机,不同系统中操作.避免了更换键鼠的麻烦.即使下面图中的功能. 鼠标同时在三台或者多台主机之间进行移动,而且是无缝滑动,鼠标直接从左滑倒右,而且支持,这台电脑复制,另一台黏贴.非常的方便实用. ...

  7. RVIZ实现模拟控制小车

    RVIZ是一个强大的可视化工具,可以看到机器人的传感器和内部状态. 1.安装rbx1功能包Rbx1是国外一本关于ros的书中的配套源码,包含了机器人的基本仿真.导航.路径规划.图像处理.语音识别等等. ...

  8. synergy一个鼠标键盘控制多台电脑

    有些时候我们同时操作多台电脑,但是我们只用一个鼠标和一个键盘,如果通过转换器啊或者是多个鼠标键盘就非常不方便了 下面我介绍一下通过安装synergy这个软件来给开发人员提供方便 这个软件安装比较简单, ...

  9. Unity2D模拟控制位移

    using UnityEngine; using System.Collections; public class PlayerController : MonoBehaviour { public ...

  10. iOS开发小技巧--TableView Group样式中控制每个section之间的距离

    一.TableView的Group样式中,默认的每个section都有sectionHeader和sectionFooter,只要调整这两个的大小就可以实现section之前的间距扩大或缩小 二.项目 ...

随机推荐

  1. DB-GBP功能使用探索

    目录 1.DBGPT支持的功能 2.配置StarRocks数据库 3. ChatBI 4. APP创建使用 5. 元数据库配置 6. API 调用探索 6.1 app 6.2 datasources ...

  2. openEuler欧拉安装Docker

    ​1. dnf配置 # 更新镜像源缓存 dnf makecache # 修改chrony时间同步配置 sed -i 's/pool pool.ntp.org iburst/pool ntp.aliyu ...

  3. docker-compose network名称定义

    docker-compose启动的网络名称: 1.没有自定义网络名 $ cat docker-compose.yaml version: '2' services: zookeeper1: image ...

  4. 如何在BASH中将制表符分隔值(TSV)文件转换为逗号分隔值(CSV)文件?(How do I convert a tab-separated values (TSV) file to a comma-separated values (CSV) file in BASH?)

    我有一些TSV文件需要转换为CSV文件. BASH中是否有任何解决方案,例如使用awk来转换这些?我可以这样使用sed,但担心它会出错: sed 's/\t/,/g' file.tsv > fi ...

  5. consul discovery prefer-ip-address

    spring.cloud.consul.discovery.prefer-ip-address: 'true'

  6. Netty系列之Netty安全性

    1.1. 严峻的安全形势 1.1.1. OpenSSL Heart bleed漏洞 2014年上半年对网络安全影响最大的问题就是OpenSSL Heart bleed漏洞,来自Codenomicon和 ...

  7. 在Asp.netCore中使用Attribute来描述限流

    前言 同事问我Asp.netCore的RateLimiting是怎么使用的,我回答说很简单的,你只要按照如下步骤来: 在RateLimiterOptions上注册policy,记住policy对应的p ...

  8. Qt数据库应用4-数据打印到纸张

    一.前言 数据能够打印到pdf文件,当然可以打印到纸张,而且使用qprinter默认就是打印到纸张的,上一篇文章写得功能是打印到pdf,其实还要单独特殊设置打印到文件,并指定格式为pdf.不指定输出文 ...

  9. Sqlsugar 跨库查询小心得(同服务器不同数据库)

    同一个服务器下的不同数据库,目前还没有进行跨服务器的查询,以后有待研究-- 1.使用的是Left Join左查询,因此连接字符串应该是写的第一个表所在的数据库的连接字符串 假设数据库A,B,连接字符串 ...

  10. 以大模型攻大模型之💫Jailbreaking Black Box Large Language Models in 🎢Twenty Queries

    "在高层次上,PAIR将两个黑盒LLMs--我们称之为攻击者和目标--相互对抗--"具体是如何对抗的?请各位看官仔细阅读~