之前一直标题是续集,欠考虑,看起来不是那么的明确,现在题目开始加功能描述,这样更清晰一点。
实际在现实中,对于电机来说,简单的直流电机,想要让他反转,最简单的方法就是将正负极反接
但是在仿真中,为我们只需要在速度前方加一个负号,就可以将他的旋转方向更改。
首先,我们想要在仿真中实现功能,我们就需要遵守仿真的一些规则,那就先介绍第一个头文件
#include <webots/robot.h>我们在webots中仿真的目的就是来搭建机器人,写一些相关的驱动或者逻辑,然后来实现我们想要的功能,所以我们需要先引用webots对于机器人的使用规则的头文件,这是 Webots 控制器程序的核心头文件,里面包含了与仿真时间、主循环相关的函数。下面是一些常见功能
🔧 常见功能:
函数 | 作用 |
|---|---|
wb_robot_init() | 初始化机器人,必须在程序一开始调用 |
wb_robot_step(time_step) | 推动仿真运行,更新所有设备(电机、传感器等)状态 |
wb_robot_cleanup() | 清理资源(通常在程序结尾调用) |
wb_robot_get_basic_time_step() | 获取仿真的基础时间步(ms) |
✅ 示例用法:
#include <webots/robot.h>
int main() {
wb_robot_init(); // 初始化
int time_step = wb_robot_get_basic_time_step(); // 获取时间步
while (wb_robot_step(time_step) != -1) {
// 机器人每一步的逻辑写在这里
}
wb_robot_cleanup(); // 清理资源
return 0;
}然后这里会发现有个很奇怪的代码:while (wb_robot_step(time_step) != -1) ,为什么要这样写个判断,其实主要是和仿真的原理有关系,wb_robot_step(time_step)函数做两件事:
time_step 毫秒(比如 32ms);
它的返回值是:
返回值 | 意义 |
|---|
0 | 仿真继续运行 |
|---|
-1 | 仿真窗口被关闭,或者仿真被终止了 |
|---|
可以这么说,只要仿真还在继续,我们就每隔 time_step 毫秒运行一次循环。
那这个是仿真世界整体的一个规则,但是我们需要用到小车的具体部件驱动,比如电机,传感器等,我们先介绍电机,他也有一个整体的库,专门是电机驱动:
#include <webots/motor.h>他的名字就一目了然,motor,他也有很多功能,我们简单介绍
🔧 常见功能:
函数 | 作用 |
|---|---|
wb_motor_get_device("name") | 获取一个马达设备指针 |
wb_motor_set_position(motor, pos) | 设置电机目标位置(单位:弧度),INFINITY 表示自由旋转 |
wb_motor_set_velocity(motor, velocity) | 设置电机速度(单位:rad/s) |
wb_motor_set_acceleration(motor, accel) | 可选:设置电机加速度 |
✅ 示例用法:
#include <webots/motor.h>
WbDeviceTag left_motor;
WbDeviceTag right_motor;
left_motor = wb_motor_get_device("left wheel motor");
right_motor = wb_motor_get_device("right wheel motor");
// 设置成无限转动(不是角度控制)
wb_motor_set_position(left_motor, INFINITY);
wb_motor_set_position(right_motor, INFINITY);
// 设置速度
wb_motor_set_velocity(left_motor, 3.0);
wb_motor_set_velocity(right_motor, 3.0);注意:如果你不设置为 INFINITY,电机就会默认以“角度控制”模式运行。
简单小车控制完整框架示例,拥有这两个头文件,我们就可以简单使用了,但是也要注意修改方法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <webots/motor.h>
#include <webots/robot.h>
#define TIME_STEP 64
static WbDeviceTag left_motor, right_motor;
// 前进
void forward() {
wb_motor_set_velocity(left_motor, 1.0);
wb_motor_set_velocity(right_motor, 1.0);
}
// 后退
void back() {
wb_motor_set_velocity(left_motor, -1.0);
wb_motor_set_velocity(right_motor, -1.0);
}
int main(int argc, char **argv) {
wb_robot_init();
// 获取电机设备
left_motor = wb_robot_get_device("left wheel motor");
right_motor = wb_robot_get_device("right wheel motor");
// 设置为速度控制模式
wb_motor_set_position(left_motor, INFINITY);
wb_motor_set_position(right_motor, INFINITY);
wb_motor_set_velocity(left_motor, 0.0);
wb_motor_set_velocity(right_motor, 0.0);
int num = 1; // 循环计数器
while (wb_robot_step(TIME_STEP) != -1) {
if (num % 2 == 1) {
forward();
} else {
back();
}
num++;
}
wb_robot_cleanup();
return 0;
}这个程序运行起来会抖动哈哈,就是很快的在前后动所以会抖动
所以我们需要再浅浅的优化一下,就是让他前进两秒,后退两秒
代码如下
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <webots/motor.h>
#include <webots/robot.h>
#define TIME_STEP 64
static WbDeviceTag left_motor, right_motor;
// 前进
void forward() {
wb_motor_set_velocity(left_motor, 1.0);
wb_motor_set_velocity(right_motor, 1.0);
}
// 后退
void back() {
wb_motor_set_velocity(left_motor, -1.0);
wb_motor_set_velocity(right_motor, -1.0);
}
void stopmotor()
{
wb_motor_set_velocity(left_motor, 0.0);
wb_motor_set_velocity(right_motor, 0.0);
}
void delay_ms(int ms) {
int time_step = TIME_STEP; // 使用全局宏定义
int steps = (int)((double)ms / time_step + 0.5); // 四舍五入
for (int i = 0; i < steps; i++) {
wb_robot_step(time_step);
}
}
int main(int argc, char **argv) {
wb_robot_init();
// 获取电机设备
left_motor = wb_robot_get_device("left wheel motor");
right_motor = wb_robot_get_device("right wheel motor");
// 设置为速度控制模式
wb_motor_set_position(left_motor, INFINITY);
wb_motor_set_position(right_motor, INFINITY);
wb_motor_set_velocity(left_motor, 0.0);
wb_motor_set_velocity(right_motor, 0.0);
int num = 1; // 循环计数器
while (wb_robot_step(TIME_STEP) != -1) {
if (num % 2 == 1) {
forward();
delay_ms(2000);
stopmotor();
} else {
back();
delay_ms(2000);
stopmotor();
}
num++;
}
wb_robot_cleanup();
return 0;
}演示一下,视频不会上传,先这样

最后呢,简单和大家聊一下对于仿真中的延时问题
不知道大家操作过arduino的一些板子没有,我编写一些小车的驱动时,保持状态会使用delay(时间)来进行延时,他的这个逻辑是可以保持delay代码上的状态一段时间,还有在Python中,time.sleep(1000),其实是舒缓一秒,就是这一秒什么也不干,一秒后再进行接下来的动作,但是在仿真中,我搜了搜,不太一样
举例来说
void delay_ms(int ms) {
int time_step = TIME_STEP; // 使用全局宏定义
int steps = (int)((double)ms / time_step + 0.5); // 四舍五入
for (int i = 0; i < steps; i++) {
wb_robot_step(time_step);
}
}在这个封装的函数中,函数的名字是延时,延时的意思便是等待,按理来说是等待多少秒,但其实里面的操作完全没有暂停的功能,反而是在推进仿真的进行
第一步获取了时间步长,第二步,计算了时间除以时间步长(一步多长时间),最后的结果就是步数,也就是算出走这么多步可以推动时间,第三步运用for循环,循环一共的步数,达到我们延时的目的,说起来也好理解,仿真中是我想保持这个状态多长时间,我就给他这个这个时间对应的步数,实物控制中,我让电机设置成前进状态需要几毫秒,加一个延时,延时过后切换状态也是合理的,设置状态那个时间可以忽略不计。
举个例子,我想让小车前进两秒停止
仿真中:小车的前进状态设置了,如果仿真步不推动,整个世界就是静止的,所以需要仿真步数推动,走完两秒后,仿真步数使用完,小车停止
现实中:小车设置了前进状态,他便会一直前进,延时两秒过后还会前进,因为代码没有改变状态,当加了延时两秒,依旧两秒过后还会前进,想停止我们必须在延时后加一个停止的代码,这样才会停止。大概就是这个意思。
然后这一个就可以了,还是不算太难的