webots函数详解 c语言

1.常用头文件

#include 
#include 
#include  //控制电机
#include //控制距离传感器

2.常用函数

2.1 初始化函数:wb_robot_int();

在调用任何别的c语言 API函数之前,需要先调用初始化函数。此函数用于初始化控制器和Webots之间的通信。

2.2 清理函数:wb_robot_cleanup();

此函数的作用和wb_robot_int()函数相反,用于关闭控制器和webots之间的同信。

注意:以上两个函数只在C API中使用,在其他语言中不存在。

2.3同步函数:wb_robot_step(TIME_STEP);

wb_robot_step(TIME_STEP)函数一般作为while和for的条件来使用;具体功能是同步控制器数据和仿真器的数据,例如传感器、电机等数据。所以每个控制器都需要使wb_robot_step(TIME_STEP)函数,要定期调用,因此它通常放置在主循环中,以便更新仿真器的数据;

TIME_STEP的数值表示控制步骤的持续时间,以毫秒为单位。此持续时间是指仿真时间,而不是现实世界的时间,因此实际上可能需要花费更少或更多的时间。TIME_STEP 必须是WorldInfo.basicTimeStep的倍数。

basicTimeStep字段定义了Webots执行模拟步骤的持续时间。它是一个浮点值,以毫秒表示,最小值为1。将该字段设置为较高的值将加速仿真,但将降低精度和稳定性,特别是对于物理计算和碰撞检测。通常建议对该值进行调优,以便找到合适的速度/精度折衷

//webots中的hello Word程序
#include 
#include 
#define TIME_STEP 32

int main() {
  wb_robot_init();

 //当Webots终止控制器时,此函数返回-1,退出while循环,所以当我们一直仿真运行,控制循环就会一直执行。
 //退出循环后,才会与Webots进行下一步通信,最后调用wb_robot_cleanup函数关闭控制器与Webots的通信。
  while(wb_robot_step(TIME_STEP) != -1)
    printf("Hello World!\n");

  wb_robot_cleanup();
  return 0; }

 

控制器终止

通常,控制器进会在循环无线中运行:当Webots退出,世界重新加载,加载新模拟或在Webots场景树中更改控制器名称时,它将终止(杀死)。当控制器进程将被 Webots 终止时,该函数返回 -1。然后控制器有1秒(实时)来保存重要数据,关闭文件等,然后才能被Webots有效地杀死。以下示例显示了如何在即将终止之前保存数

 

控制器终止的几种情况(wb_robot_step函数返回-1,Webots终止与控制器通信):

  • Webots quits; //退出Webots
  • the simulation is reset; //重置仿真
  • the world is reloaded; //重新加载世界
  • a new simulation is loaded; //加载新的模拟
  • the controller name is changed (by the user from the scene tree GUI or by a supervisor process). //更改控制器名称(由用户从场景树GUI或由管理进程更改)

3.设备函数

1.获取设备函数:wb_robot_get_device("设备名称");

我们在使用电机,传感器等设备前,需要使用该函数wb_robot_get_device("设备名称"),该函数的返回值是一个指针;

注:这里的设备名称是指:你在webots中定义的设备名称。

使用电机、传感器等设备前,需使用wb_robot_get_device函数获取设备的标签(WbDeviceTag)。传入该函数的参数(字符串)是你在Webots中定义的设备名称。如果传入无效的设备名称,则此函数返回0。

2.使能函数:wb_*_enable(sensor(传感器),TIME_STEP);

虽然电机使用前不需要使能,但是传感器、惯性单元IMU、键盘等在使用前必须使能(启用);那么我们就可以通过使能函数达成这一目的。

  • 距离传感器:wb_position_sensor_enable(sensor, TIME_STEP);
  • 接触传感器:wb_touch_sensor_enable(sensor, TIME_STEP);
  • 惯性单元:wb_inertial_unit_enable(sensor, TIME_STEP);
  • 键盘:wb_keyboard_enable(TIME_STEP);

更新一次传感器,惯性单元IMU,键盘keyboard的时间间隔为TIME_STEP,这里的TIME_STEP与控制周期(control step)相同。

3.失能函数:wb_*_disable();

与使能函数作用相反,用来禁用设备,提高仿真速度。

4.取值函数:wb_*_get_value(sensor);

作用:用于去传感器的值;

*:传感器的类型

sensor:传感器的名称;

例如获取距离传感器的最新值:wb_distance_sensor_get_value(sensor);

需要注意的是:有些设备返回的是向量值(返回数组地址,需要用指针接收)而不是标量值,例如以下函数:

const double *wb_gps_get_values(WbDeviceTag tag); //GPS
const double *wb_accelerometer_get_values(WbDeviceTag tag);
const double *wb_gyro_get_values(WbDeviceTag tag);
const double *wb_inertial_unit_get_roll_pitch_yaw(WbDeviceTag tag); //IMU

在C/C++中,该函数返回一个指针,该指针是函数内部分配的数组地址,指向三个双精度浮点型数值。因为数组只包含3个元素,所以数组索引超过2是非法的,可能会使控制器崩溃。控制器代码不能删除该数组,在必要时由系统自动删除。为了保证数组元素不被修改,所以定义一个常量指针来接收它。下面是使用这些函数的一个例子:

const double *pos = wb_gps_get_values(gps);

// OK, to read the values they should never be explicitly deleted by the controller code.
printf("MY_ROBOT is at position: %g %g %g\n", pos[0], pos[1], pos[2]);

// OK, to copy the values
double x, y, z;
x = pos[0];
y = pos[1];
z = pos[2];

// OK, another way to copy the values
double a[3] = { pos[0], pos[1], pos[2] };

// OK, yet another way to copy these values
double b[3];
memcpy(b, pos, sizeof(b));

以下是错误示例:

const double *pos = wb_gps_get_values(gps);

pos[0] = 3.5;      // ERROR: assignment of read-only location
double a = pos[3]; // ERROR: index out of range
delete [] pos;     // ERROR: illegal free
free(pos);         // ERROR: illegal free

下面是综合例子:

//例子:距离传感器的使用
#include 
#include 
#include 

#define TIME_STEP 32

int main() {
  wb_robot_init();

  //WbDeviceTag用于在控制器代码中标识设备,相当于定义一个WbDeviceTag类型的变量。
  WbDeviceTag sensor = wb_robot_get_device("my_distance_sensor");
  wb_distance_sensor_enable(sensor, TIME_STEP);//使能函数,定义传感器 ,惯性单位前,键盘都要使用

  while (wb_robot_step(TIME_STEP) != -1) {
    //在调用wb_robot_step函数时更新传感器值
    const double value = wb_distance_sensor_get_value(sensor); //取出传感器的最新值
    printf("Sensor value is %f\n", value);
  }

  wb_robot_cleanup();
  return 0;
}

3.执行器函数

与传感器函数不同的是,使用该执行器函数不需要使能函数wb_*_enable(sensor,TIME_STEP);

1.位置控制函数:wb_motor_set_position(motor,position);

作用:储存电机下一步的目标位置,但是不会立即启动该电机,在调用wb_robot_step后启用;wb_robot_step函数向电机发送驱动指令,但不等待电机完成运动(到达指定目标位置),它只在指定的数毫秒内模拟电机的运动。当wb_robot_step函数执行完毕返回时,电机已移动或转动的量取决于目标位置、控制步骤(control step)的持续时间(TIME_STEP),以及电机的速度、加速度、力和其他参数。如果设置了非常小的控制步长或较低的电机速度,则当wb_robot_step函数返回时,电机不会运动太多,在这种情况下,电机需要执行几个控制步骤后才能到达目标位置。如果设置了更长的持续时间或更高的电机速度,则当wb_robot_step函数返回时,电机可能已运动到目标位置。
需要注意的是:该函数仅指定期望的目标位置。与真实机器人一样,在基于物理的仿真中电机可能被障碍物阻挡,或因为电机的最大扭矩(maxForce)不足以抵抗重力等原因,导致电机可能无法到达目标位置。

//使用前一般先初始化
wb_motor_set_position(left_motor, INFINITY);
wb_motor_set_position(right_motor, INFINITY);

 

2.速度控制函数wb_motor_set_velocity(motor,velocity)

它与位置控制函数相似

作用:储存电机下一步的目标的速度,但是不会立即启动该电机,在调用wb_robot_step后启用;

//使用前一般先初始化
wb_motor_set_velocity(left_motor, 0.0);
wb_motor_set_velocity(right_motor, 0.0);

3、力矩控制函数:wb_motor_set_torque(motor, torque);

4、力控制函数:wb_motor_set_force(motor, force);

示例

//例子:以2Hz正弦信号控制电机转动
#include 
#include 
#include 

#define TIME_STEP 32

int main() {
  wb_robot_init();

  WbDeviceTag motor = wb_robot_get_device("my_motor");

  const double F = 2.0;   // 频率 2 Hz
  double t = 0.0;         // 仿真模拟时间
  while (wb_robot_step(TIME_STEP) != -1) {
    const double position = sin(t * 2.0 * M_PI * F);
    wb_motor_set_position(motor, position);
    t += (double)TIME_STEP / 1000.0; //将电机运动分解为与控制步骤相对应的离散步骤
  }

  wb_robot_cleanup();
  return 0;
}

 

 

 

你可能感兴趣的:(c语言,开发语言)