首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >仿真续集-------让我的小车前进两秒,后退两秒

仿真续集-------让我的小车前进两秒,后退两秒

作者头像
用户11770632
发布2025-11-15 10:50:46
发布2025-11-15 10:50:46
1220
举报

之前一直标题是续集,欠考虑,看起来不是那么的明确,现在题目开始加功能描述,这样更清晰一点。

如何让小车前进后退?

实际在现实中,对于电机来说,简单的直流电机,想要让他反转,最简单的方法就是将正负极反接

但是在仿真中,为我们只需要在速度前方加一个负号,就可以将他的旋转方向更改。

首先,我们想要在仿真中实现功能,我们就需要遵守仿真的一些规则,那就先介绍第一个头文件

代码语言:javascript
复制
#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)

✅ 示例用法:

代码语言:javascript
复制
#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)函数做两件事:

  1. 推动仿真时间前进一个 time_step 毫秒(比如 32ms);
  2. 等待 Webots 引擎完成一帧的物理/传感器/图像仿真,然后返回一个值。

 它的返回值是:

返回值

意义

0

仿真继续运行

-1

仿真窗口被关闭,或者仿真被终止了

 可以这么说,只要仿真还在继续,我们就每隔 time_step 毫秒运行一次循环。

那这个是仿真世界整体的一个规则,但是我们需要用到小车的具体部件驱动,比如电机,传感器等,我们先介绍电机,他也有一个整体的库,专门是电机驱动:

代码语言:javascript
复制
#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)

可选:设置电机加速度

 ✅ 示例用法:

代码语言:javascript
复制
#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,电机就会默认以“角度控制”模式运行。

简单小车控制完整框架示例,拥有这两个头文件,我们就可以简单使用了,但是也要注意修改方法

代码语言:javascript
复制
#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;
}

这个程序运行起来会抖动哈哈,就是很快的在前后动所以会抖动

所以我们需要再浅浅的优化一下,就是让他前进两秒,后退两秒

代码如下

代码语言:javascript
复制
#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),其实是舒缓一秒,就是这一秒什么也不干,一秒后再进行接下来的动作,但是在仿真中,我搜了搜,不太一样

举例来说

代码语言:javascript
复制
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循环,循环一共的步数,达到我们延时的目的,说起来也好理解,仿真中是我想保持这个状态多长时间,我就给他这个这个时间对应的步数,实物控制中,我让电机设置成前进状态需要几毫秒,加一个延时,延时过后切换状态也是合理的,设置状态那个时间可以忽略不计。

举个例子,我想让小车前进两秒停止

仿真中:小车的前进状态设置了,如果仿真步不推动,整个世界就是静止的,所以需要仿真步数推动,走完两秒后,仿真步数使用完,小车停止

现实中:小车设置了前进状态,他便会一直前进,延时两秒过后还会前进,因为代码没有改变状态,当加了延时两秒,依旧两秒过后还会前进,想停止我们必须在延时后加一个停止的代码,这样才会停止。大概就是这个意思。

然后这一个就可以了,还是不算太难的

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-04-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 如何让小车前进后退?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档