文档创建日期:2023年4月14日
文档内容:如何在webots中绘制数据值随时间变化的曲线
文档作者:RobotFreak
在webots中进行机器人仿真时,不可避免地也会用到pid,在对pid进行调参的过程中,曲线图十分重要。单纯只通过终端看数据的数值变化很难调出比较理想的效果,还是需要曲线图看波形才可以。于是有一个能画图的节点就十分重要。
通过查阅webots的Webots documentation: Display (cyberbotics.com),发现Display节点可以实现画图、可视化的功能。
webots中的Display节点可以模拟一个嵌入式屏幕,或者显示任何图形信息例如图表,文本,机器人轨迹,滤波后的摄像头图像等等。
显示Display的overlay
想要显示display的overlay小窗口需要取消勾选Overlays中的Hide All Display Overlays:
Display初始化
主要是根据display的名称获取DeviceTag,对参数初始化。
void initDisplay(Display* displayPtr)
{
displayPtr->id = wb_robot_get_device(displayPtr->name);
displayPtr->width = wb_display_get_width(displayPtr->id);
displayPtr->height = wb_display_get_height(displayPtr->id);
displayPtr->maxValue = DISPLAY_FOOTY_MAX_VALUE;
displayPtr->pointToDraw.x = 0;
displayPtr->pointToDraw.y = 0;
}
Display是一个结构体,保存了显示设备的相关参数和信息。
typedef struct
{
WbDeviceTag id;
const char* name;
int height; //display的高度(像素数)
int width; //display的宽度(像素数)
double maxValue; //display的显示数据的最大值,y轴最大值(绝对值)
Point2DimInt pointToDraw; //要画的点
}Display;
在Display中画出数据曲线
画曲线有两个思路:
- 每次画一个点,逐个像素的画pixel
- 画直线,两次数据的横坐标(t)可以有一定间隔但不能太大
第一种思路
第一种思路的实现方法如下:
void displayDrawPoint(Display* displayPtr, double value)
{
if (displayPtr->pointToDraw.x >= displayPtr->width) //限制在宽的范围内
displayPtr->pointToDraw.x = 0;
displayPtr->pointToDraw.x += 1; //逐渐往后画
int midHeight = displayPtr->height / 2; //中间高度,向上为正(y变小),向下为负(y变大)
displayPtr->pointToDraw.y = midHeight - value / displayPtr->maxValue * midHeight; //根据要画的值与最大值的比值决定点的y坐标
wb_display_draw_pixel(displayPtr->id, displayPtr->pointToDraw.x, displayPtr->pointToDraw.y); //画一个像素
//如何从左到右画完一次之后再次从左边开始时不受之前画的影响?
}
因为我想在display中画出分正负的曲线,所以我以高的中间(y轴)为基准,向上为正,向下为负,越偏离基准线,绝对值就越大。
按照第一种思路画出来实现的效果如下:
在webots中绘制数据曲线_画点