Open Dynamics Engine(ODE)物理引擎教程(A)–c++调用python函数实现数据可视化

下一教程

Open Dynamics Engine(ODE)物理引擎教程(B)–图表形式动态显示仿真结果(C++调用python第三方库)
(在这个教程中将在C++调用python函数的基础上,实现ODE物体状态的图标动态绘制功能)

本文实现的效果

C++中调用Python函数画一个表的效果。
Open Dynamics Engine(ODE)物理引擎教程(A)–c++调用python函数实现数据可视化_第1张图片

本文结构

  • 下一教程
  • 本文实现的效果
  • 0. 引言
  • 1. C++调用Python函数方法
    • 1.1 安装python
    • 1.2 配置Python
      • 1.2.1 文件的拷贝工作
      • 1.2.2 工程项目属性配置
    • 1.3 测试Python
      • 1.3.1 python脚本代码
      • 1.3.2 C++主函数格式
  • 2. 下一教程
  • 3. 课程推广

0. 引言

本系列教程是在上一个教程基础上进行的,所以请保证你是通过上一个教程过来的:

Open Dynamics Engine(ODE)物理引擎教程(3)–ODE仿真框架介绍与重力仿真

在使用ODE物理引擎做仿真后,我们可以存储下来数据使用matlab或者是Excel分析。在这里我们想要实现仿真过程中的动态数据显示,可以通过多种图像显示库如Gnuplotmatplotlib-cpp等,下面是他们的主页链接:

Gnuplot
简介【是一种用于多种操作系统的命令行式画图软件】

matplotlib-cpp
简介【Extremely simple yet powerful header-only C++ plotting library built on the popular matplotlib 】

这里我们想要使用python(也是对自己熟悉语言的锻炼)进行动态的图像分析,很重要的原因是可视化效果好,以及函数包丰富,未来还可以实现机器学习等等,也是提前做好接口。所以Open Dynamics Engine(ODE)物理引擎教程(A,B,C…)等系列就围绕python的相关内容编写,让我们共同提升。本文首先介绍如何在C++中调用python函数或者说是脚本。

1. C++调用Python函数方法

C++调用python函数的配置方法很多,但是有很多坑,这里提供我使用的一种方法,如有雷同,那就是我用的那种。关注Open Dynamics Engine(ODE)物理引擎教程系列的老朋友应该知道,我的环境是:

  • Windows10
  • Visual Studio 2017

更多Python与C/C++的API定义你可以查阅官方文档:
Python/C API Reference Manual

1.1 安装python

首先到python官网下载相应版本:

https://www.python.org/downloads/release/python-382/

我下载的是Python 3.8.2 x64的可执行文件。
Open Dynamics Engine(ODE)物理引擎教程(A)–c++调用python函数实现数据可视化_第2张图片
下载完成之后点击安装即可,没有什么要求,但是要记住自己的安装目录,我的是:

C:\Users\User_Name\AppData\Local\Programs\Python\Python38 //注意User_Name是你自己的用户名,我这里只不过用这个替换了

1.2 配置Python

还记得我们配置生成VS项目而建立的头文件和库函数的存放文件吗,这时候就排上用场了,不清楚的朋友可以查看这篇博文:

Open Dynamics Engine(ODE)物理引擎教程(2)–项目环境配置与“Hello ODEWorld”

1.2.1 文件的拷贝工作

首先我们需要将python安装目录下的头文件和库函数文件放到项目的相应引用文件中:
Open Dynamics Engine(ODE)物理引擎教程(A)–c++调用python函数实现数据可视化_第3张图片
是不是很熟悉的操作,由于python的头文件里面有很多文档,我们可以在ExternLab/include下建立python文件夹,然后将上图include文件夹中的所有内容拷贝到新建的python目录下。
同样的将上图的libs文件夹下的内容拷贝到ExternLab/lib文件夹下。
将上图中的python38.dll文件拷贝到VS项目生成可执行文件的地方,即ODEEnvironment\x64\Debug文件夹中,和ODEEnvironment.exe放在一起。

1.2.2 工程项目属性配置

由于上一个教程中已经进行过相关属性的配置,所以这里直接给出截图。
在VC++目录中的包含目录中增加:

$(SolutionDir)\..\ExternLab\include\python

Open Dynamics Engine(ODE)物理引擎教程(A)–c++调用python函数实现数据可视化_第4张图片
在链接器的输入中附加依赖项:

python38.lib

Open Dynamics Engine(ODE)物理引擎教程(A)–c++调用python函数实现数据可视化_第5张图片

1.3 测试Python

首先在网上找一个python脚本,感谢原作者Zaric_Chou的分享:

python画图之“小海龟”turtle

1.3.1 python脚本代码

我使用的是画钟表的案例:

# coding=utf-8 
import turtle 
from datetime import *
# 抬起画笔,向前运动一段距离放下 
def Skip(step): 
  turtle.penup() 
  turtle.forward(step) 
  turtle.pendown() 
def mkHand(name, length): 
  # 注册Turtle形状,建立表针Turtle 
  turtle.reset() 
  Skip(-length * 0.1) 
  # 开始记录多边形的顶点。当前的乌龟位置是多边形的第一个顶点。 
  turtle.begin_poly() 
  turtle.forward(length * 1.1) 
  # 停止记录多边形的顶点。当前的乌龟位置是多边形的最后一个顶点。将与第一个顶点相连。 
  turtle.end_poly() 
  # 返回最后记录的多边形。 
  handForm = turtle.get_poly() 
  turtle.register_shape(name, handForm) 
def Init(): 
  global secHand, minHand, hurHand, printer 
  # 重置Turtle指向北 
  turtle.mode("logo") 
  # 建立三个表针Turtle并初始化 
  mkHand("secHand", 135) 
  mkHand("minHand", 125) 
  mkHand("hurHand", 90) 
  secHand = turtle.Turtle() 
  secHand.shape("secHand") 
  minHand = turtle.Turtle() 
  minHand.shape("minHand") 
  hurHand = turtle.Turtle() 
  hurHand.shape("hurHand") 
  for hand in secHand, minHand, hurHand: 
    hand.shapesize(1, 1, 3) 
    hand.speed(0) 
  # 建立输出文字Turtle 
  printer = turtle.Turtle() 
  # 隐藏画笔的turtle形状 
  printer.hideturtle() 
  printer.penup() 
def SetupClock(radius): 
  # 建立表的外框 
  turtle.reset() 
  turtle.pensize(7) 
  for i in range(60): 
    Skip(radius) 
    if i % 5 == 0: 
      turtle.forward(20) 
      Skip(-radius - 20) 
        
      Skip(radius + 20) 
      if i == 0: 
        turtle.write(int(12), align="center", font=("Courier", 14, "bold")) 
      elif i == 30: 
        Skip(25) 
        turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) 
        Skip(-25) 
      elif (i == 25 or i == 35): 
        Skip(20) 
        turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) 
        Skip(-20) 
      else: 
        turtle.write(int(i/5), align="center", font=("Courier", 14, "bold")) 
      Skip(-radius - 20) 
    else: 
      turtle.dot(5) 
      Skip(-radius) 
    turtle.right(6)    
def Week(t):   
  week = ["星期一", "星期二", "星期三", 
      "星期四", "星期五", "星期六", "星期日"] 
  return week[t.weekday()]  
def Date(t): 
  y = t.year 
  m = t.month 
  d = t.day 
  return "%s %d%d" % (y, m, d)   
def Tick(): 
  # 绘制表针的动态显示 
  t = datetime.today() 
  second = t.second + t.microsecond * 0.000001
  minute = t.minute + second / 60.0
  hour = t.hour + minute / 60.0
  secHand.setheading(6 * second) 
  minHand.setheading(6 * minute) 
  hurHand.setheading(30 * hour)    
  turtle.tracer(False)  
  printer.forward(65) 
  printer.write(Week(t), align="center", 
         font=("Courier", 14, "bold")) 
  printer.back(130) 
  printer.write(Date(t), align="center", 
         font=("Courier", 14, "bold")) 
  printer.home() 
  turtle.tracer(True)   
  # 100ms后继续调用tick 
  turtle.ontimer(Tick, 100) 
def main(): 
  # 打开/关闭龟动画,并为更新图纸设置延迟。 
  turtle.tracer(False) 
  Init() 
  SetupClock(160) 
  turtle.tracer(True) 
  Tick() 
  turtle.mainloop() 
   
if __name__ == "__main__": 
  main()

将其保存为addTest.py的脚本,并存放在ODEEnvironment\x64\Debug文件夹中,和ODEEnvironment.exe放在一起。

1.3.2 C++主函数格式

接下来的代码发生在EnvMain.cpp中。
首先引用头文件

#include 

主函数中的函数格式:

int  main(int argc, char **argv) {

	cout << "Hello World!" << endl;
	Py_Initialize(); //这是python的初始化,第一次使用时一定要调用
	if (!Py_IsInitialized())
	{
		printf("初始化失败!");
		return 0;
	}
	PyObject* pModule = NULL; //先生成相应的对象
	PyObject* pFunc = NULL;
	pModule = PyImport_ImportModule("addTest");  //参数为Python脚本的文件名
	if (pModule)
	{
		pFunc = PyObject_GetAttrString(pModule, "main");   //获取函数
		PyEval_CallObject(pFunc, NULL);           //执行函数 这里的NULL是因为python脚本运行不需要参数
		//在后面我们将讲到如果有参数怎么办
	}
	else
	{
		printf("导入Python模块失败...\n");
	}
	ODEMain(argc, argv);
	Py_Finalize();
	return 0;
}

然后编译并运行,出现如下效果就说明你的python配置成功了:
Open Dynamics Engine(ODE)物理引擎教程(A)–c++调用python函数实现数据可视化_第6张图片

2. 下一教程

Open Dynamics Engine(ODE)物理引擎教程(B)–图表形式动态显示仿真结果(C++调用python第三方库)
(在这个教程中将在C++调用python函数的基础上,实现ODE物体状态的图标动态绘制功能)

3. 课程推广

Open Dynamics Engine(ODE)物理引擎教程(A)–c++调用python函数实现数据可视化_第7张图片

你可能感兴趣的:(ODE物理引擎教程)