1.常用的头文件
#include <webots/robot.h> #include <stdio.h> #include <webots/motor.h> //控制电机 #include <webots/distance_sensor.h>//控制距离传感器
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 <webots/robot.h> #include <stdio.h> #define TIME_STEP 32 int main() { wb_robot_init(); //当Webots当控制器终止时,该函数返回-1while因此,当我们一直模拟运行时,控制循环就会一直执行。 ///退出循环后Webots下一步通信,最后调用wb_robot_cleanup控制器和函数关闭Webots的通信。 ///退出循环后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 在中间,函数返回一个指针,指向三个双精度浮点值。数组索引超过2是非法的,因为数组只含有3个元素,可能会使控制器崩溃。必要时,系统将自动删除控制器代码。定义常量指针接收它,以确保数组元素不被修改。以下是使用这些函数的例子:
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 <webots/robot.h> #include <webots/distance_sensor.h> #include <stdio.h> #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 <webots/robot.h>
#include <webots/motor.h>
#include <math.h>
#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;
}