如何让处理使用数组的一部分
How to get Processing to use a part of an array
该软件用于加速度计芯片的实时分析。但是,它不会使用数组组件生成图形。当我用实际数字替换 void drawAxes 中的 dat[0/1/2] 部分时,会生成图形。
有什么方法可以让 dat[] 数组在这个系统中工作,或者我可以使用任何替代方法吗?
dat[]*100 只是为了放大插入的值。
//Accelerometer graphing programme
//Author: Owain L. Evans, owainlevans@outlook.com
//Takes data from Arduino and produces a 3-Dimensional visualisation
import processing.serial.*;
Serial myPort; //Serial Port
String DataLine; //Input from serial port
float[] dat;
PVector a = new PVector(100, 50, 20);
void setup()
{
size(1024, 720, P3D);
strokeWeight(3);
dat = new float[3];
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw() {
if (myPort.available() > 0)
{DataLine = myPort.readStringUntil('\n');
}
if (DataLine != null) {
println(DataLine);
float dat[] = float(split(DataLine, ",")); //parse comma-separated number string into numbers
println(dat);
println();
}
background(250);
drawAxes(dat[0]*100, dat[1]*100, dat[2]*100); //draw original coordinate system
translate(width * 0.5, height * 0.5, 0);
rotateX(map(mouseY,0,height,-PI,PI));
rotateY(map(mouseX,0,width,-PI,PI));
drawAxes(dat[0]*100, dat[1]*100, dat[2]*100);
pushMatrix();
translate(a.x, a.y, a.z); //isolate coordinate system and draw translated A point
popMatrix();
}
void drawAxes(float x, float y, float z) {
//X - red
stroke(192, 0, 0);
line( 0, 0, 0, x, 0, 0);
//Y - green
stroke(0, 192, 0);
line(0, 0, 0, 0, y, 0);
//Z - blue
stroke(0, 0, 192);
line(0, 0, 0, 0, 0, z);
}
很难说出数组发生了什么,但您可以向 drawAxes()
添加参数,这将消除与 dat
的紧密耦合,并使其可重新用于其他草图:
void drawAxes(float x, float y, float z) {
//X - red
stroke(192, 0, 0);
line( 0, 0, 0, x, 0, 0);
//Y - green
stroke(0, 192, 0);
line(0, 0, 0, 0, y, 0);
//Z - blue
stroke(0, 0, 192);
line(0, 0, 0, 0, 0, z);
}
(例如 drawAxes(dat[0] * 100, dat[1] * 100, dat[2] * 100);
)
更新 我明白你的意思:你想构建一个传入数据的图表和绘图。
问题是目前您只存储了一个不断更新的样本。
要绘制具有多个值的图表,您需要:
- 创建一个数组来存储多个样本
- 更新数组(在新值到达时移动旧值)
- 遍历数组并绘制每个值
第 1 步: 创建一个 [n-samples][3]
二维数组来存储传入数据。
为了争论起见,让我们存储 30 个样本的历史记录:
int sampleDimensions = 3;
// how many samples to record
int numSamples = 30;
// where to store the data
float[][] samples = new float[numSamples][sampleDimensions];
步骤 2: 更新样本(移动旧数据,添加新数据):
// read a new sample x,y,z entry and append it
void updateSamples(float x, float y, float z) {
// shift oldest samples by 1: count backwards from oldest sample to 2nd sample
for (int i = numSamples - 1; i > 0; i--) {
// copy previous sample data: offsetting old data by 1
samples[i][0] = samples[i-1][0];
samples[i][1] = samples[i-1][1];
samples[i][2] = samples[i-1][2];
}
// add newest entry as the first sample (replacing old data)
samples[0][0] = x;
samples[0][1] = y;
samples[0][2] = z;
}
步骤 3 遍历数据并绘图:
// render samples on screen with the option to scale the data
void drawSamples(float scale) {
for (int i = 0 ; i < numSamples; i++){
drawAxes(samples[i][0] * scale, samples[i][1] * scale, samples[i][2] * scale);
}
}
请记住,这在渲染方面并不是非常高效,但是对于 30 个样本应该没问题。最后,重要的是可视化风格的易读性。
如果你想做一个更简单的渲染可视化,你可以简单地渲染一条线:
void drawSamples(float scale) {
beginShape();
for (int i = 0 ; i < numSamples; i++){
vertex(samples[i][0] * scale, samples[i][1] * scale, samples[i][2] * scale);
}
endShape();
}
综合来看:
import processing.serial.*;
Serial myPort; //Serial Port
String dataLine; //Input from serial port
PVector a = new PVector(100, 50, 20);
int sampleDimensions = 3;
// how many samples to record
int numSamples = 30;
// where to store the data
float[][] samples = new float[numSamples][sampleDimensions];
// stores a single data sample from serial
float[] sample = new float[sampleDimensions];
// how much to scale data for visualisation
float sampleRenderScale = 100;
void setup() {
size(1024, 720, P3D);
strokeWeight(3);
noFill();
// try to open serial connection: display error otherwise (port missing, or busy (already open in Serial Monitor, etc.))
try {
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}catch(Exception e) {
println("error openin serial port: " + Serial.list()[0]);
e.printStackTrace();
}
}
void draw() {
if(myPort != null){
if (myPort.available() > 0){
dataLine = myPort.readStringUntil('\n');
if (dataLine != null) {
println(dataLine);
sample = float(split(dataLine, ",")); //parse comma-separated number string into numbers
println(sample);
if(sample == null || sample.length < 3){
println("parsed less than the expected 3 values:");
return;
}
println();
// add new sample to the list of recorded samples
updateSamples(sample[0], sample[1], sample[2]);
}
}
}
background(250);
drawAxes(sample[0] * sampleRenderScale, sample[1] * sampleRenderScale, sample[2] * sampleRenderScale); //draw original coordinate system
translate(width * 0.5, height * 0.5, 0);
rotateX(map(mouseY, 0, height, -PI, PI));
rotateY(map(mouseX, 0, width, -PI, PI));
drawAxes(sample[0] * sampleRenderScale, sample[1] * sampleRenderScale, sample[2] * sampleRenderScale);
// draw recorded samples
drawSamples(sampleRenderScale);
pushMatrix();
translate(a.x, a.y, a.z); //isolate coordinate system and draw translated A point
popMatrix();
}
// read a new sample x,y,z entry and append it
void updateSamples(float x, float y, float z) {
// shift oldest samples by 1: count backwards from oldest sample to 2nd sample
for (int i = numSamples - 1; i > 0; i--) {
// copy previous sample data: offsetting old data by 1
samples[i][0] = samples[i-1][0];
samples[i][1] = samples[i-1][1];
samples[i][2] = samples[i-1][2];
}
// add newest entry as the first sample (replacing old data)
samples[0][0] = x;
samples[0][1] = y;
samples[0][2] = z;
}
// render samples on screen with the option to scale the data
void drawSamples(float scale) {
beginShape();
for (int i = 0 ; i < numSamples; i++){
vertex(samples[i][0] * scale, samples[i][1] * scale, samples[i][2] * scale);
}
endShape();
}
void drawAxes(float x, float y, float z) {
//X - red
stroke(192, 0, 0);
line( 0, 0, 0, x, 0, 0);
//Y - green
stroke(0, 192, 0);
line(0, 0, 0, 0, y, 0);
//Z - blue
stroke(0, 0, 192);
line(0, 0, 0, 0, 0, z);
}
注意一些变化:
DataLine
重命名为 dataLine
(根据 Java Naming Conventions)
- 通常将变量重命名为易于理解的内容are/do并格式化代码以便于阅读
- 处理串行端口连接时出错。您已经对传入数据进行了错误处理,这很棒。
我们的想法是随着你的进步养成良好的习惯。
如果您有时间探索其他语言,我推荐 Python 和一些模块,
如果感兴趣,可能会启动 cluserting/classifying 传感器数据:
- pyserial用于串口通信
- SciPy:
numpy
for fast array manipulation, matplotlib for plotting and sklearn 对于 classiciation/clustering/etc.
该软件用于加速度计芯片的实时分析。但是,它不会使用数组组件生成图形。当我用实际数字替换 void drawAxes 中的 dat[0/1/2] 部分时,会生成图形。
有什么方法可以让 dat[] 数组在这个系统中工作,或者我可以使用任何替代方法吗? dat[]*100 只是为了放大插入的值。
//Accelerometer graphing programme
//Author: Owain L. Evans, owainlevans@outlook.com
//Takes data from Arduino and produces a 3-Dimensional visualisation
import processing.serial.*;
Serial myPort; //Serial Port
String DataLine; //Input from serial port
float[] dat;
PVector a = new PVector(100, 50, 20);
void setup()
{
size(1024, 720, P3D);
strokeWeight(3);
dat = new float[3];
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw() {
if (myPort.available() > 0)
{DataLine = myPort.readStringUntil('\n');
}
if (DataLine != null) {
println(DataLine);
float dat[] = float(split(DataLine, ",")); //parse comma-separated number string into numbers
println(dat);
println();
}
background(250);
drawAxes(dat[0]*100, dat[1]*100, dat[2]*100); //draw original coordinate system
translate(width * 0.5, height * 0.5, 0);
rotateX(map(mouseY,0,height,-PI,PI));
rotateY(map(mouseX,0,width,-PI,PI));
drawAxes(dat[0]*100, dat[1]*100, dat[2]*100);
pushMatrix();
translate(a.x, a.y, a.z); //isolate coordinate system and draw translated A point
popMatrix();
}
void drawAxes(float x, float y, float z) {
//X - red
stroke(192, 0, 0);
line( 0, 0, 0, x, 0, 0);
//Y - green
stroke(0, 192, 0);
line(0, 0, 0, 0, y, 0);
//Z - blue
stroke(0, 0, 192);
line(0, 0, 0, 0, 0, z);
}
很难说出数组发生了什么,但您可以向 drawAxes()
添加参数,这将消除与 dat
的紧密耦合,并使其可重新用于其他草图:
void drawAxes(float x, float y, float z) {
//X - red
stroke(192, 0, 0);
line( 0, 0, 0, x, 0, 0);
//Y - green
stroke(0, 192, 0);
line(0, 0, 0, 0, y, 0);
//Z - blue
stroke(0, 0, 192);
line(0, 0, 0, 0, 0, z);
}
(例如 drawAxes(dat[0] * 100, dat[1] * 100, dat[2] * 100);
)
更新 我明白你的意思:你想构建一个传入数据的图表和绘图。
问题是目前您只存储了一个不断更新的样本。
要绘制具有多个值的图表,您需要:
- 创建一个数组来存储多个样本
- 更新数组(在新值到达时移动旧值)
- 遍历数组并绘制每个值
第 1 步: 创建一个 [n-samples][3]
二维数组来存储传入数据。
为了争论起见,让我们存储 30 个样本的历史记录:
int sampleDimensions = 3;
// how many samples to record
int numSamples = 30;
// where to store the data
float[][] samples = new float[numSamples][sampleDimensions];
步骤 2: 更新样本(移动旧数据,添加新数据):
// read a new sample x,y,z entry and append it
void updateSamples(float x, float y, float z) {
// shift oldest samples by 1: count backwards from oldest sample to 2nd sample
for (int i = numSamples - 1; i > 0; i--) {
// copy previous sample data: offsetting old data by 1
samples[i][0] = samples[i-1][0];
samples[i][1] = samples[i-1][1];
samples[i][2] = samples[i-1][2];
}
// add newest entry as the first sample (replacing old data)
samples[0][0] = x;
samples[0][1] = y;
samples[0][2] = z;
}
步骤 3 遍历数据并绘图:
// render samples on screen with the option to scale the data
void drawSamples(float scale) {
for (int i = 0 ; i < numSamples; i++){
drawAxes(samples[i][0] * scale, samples[i][1] * scale, samples[i][2] * scale);
}
}
请记住,这在渲染方面并不是非常高效,但是对于 30 个样本应该没问题。最后,重要的是可视化风格的易读性。
如果你想做一个更简单的渲染可视化,你可以简单地渲染一条线:
void drawSamples(float scale) {
beginShape();
for (int i = 0 ; i < numSamples; i++){
vertex(samples[i][0] * scale, samples[i][1] * scale, samples[i][2] * scale);
}
endShape();
}
综合来看:
import processing.serial.*;
Serial myPort; //Serial Port
String dataLine; //Input from serial port
PVector a = new PVector(100, 50, 20);
int sampleDimensions = 3;
// how many samples to record
int numSamples = 30;
// where to store the data
float[][] samples = new float[numSamples][sampleDimensions];
// stores a single data sample from serial
float[] sample = new float[sampleDimensions];
// how much to scale data for visualisation
float sampleRenderScale = 100;
void setup() {
size(1024, 720, P3D);
strokeWeight(3);
noFill();
// try to open serial connection: display error otherwise (port missing, or busy (already open in Serial Monitor, etc.))
try {
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}catch(Exception e) {
println("error openin serial port: " + Serial.list()[0]);
e.printStackTrace();
}
}
void draw() {
if(myPort != null){
if (myPort.available() > 0){
dataLine = myPort.readStringUntil('\n');
if (dataLine != null) {
println(dataLine);
sample = float(split(dataLine, ",")); //parse comma-separated number string into numbers
println(sample);
if(sample == null || sample.length < 3){
println("parsed less than the expected 3 values:");
return;
}
println();
// add new sample to the list of recorded samples
updateSamples(sample[0], sample[1], sample[2]);
}
}
}
background(250);
drawAxes(sample[0] * sampleRenderScale, sample[1] * sampleRenderScale, sample[2] * sampleRenderScale); //draw original coordinate system
translate(width * 0.5, height * 0.5, 0);
rotateX(map(mouseY, 0, height, -PI, PI));
rotateY(map(mouseX, 0, width, -PI, PI));
drawAxes(sample[0] * sampleRenderScale, sample[1] * sampleRenderScale, sample[2] * sampleRenderScale);
// draw recorded samples
drawSamples(sampleRenderScale);
pushMatrix();
translate(a.x, a.y, a.z); //isolate coordinate system and draw translated A point
popMatrix();
}
// read a new sample x,y,z entry and append it
void updateSamples(float x, float y, float z) {
// shift oldest samples by 1: count backwards from oldest sample to 2nd sample
for (int i = numSamples - 1; i > 0; i--) {
// copy previous sample data: offsetting old data by 1
samples[i][0] = samples[i-1][0];
samples[i][1] = samples[i-1][1];
samples[i][2] = samples[i-1][2];
}
// add newest entry as the first sample (replacing old data)
samples[0][0] = x;
samples[0][1] = y;
samples[0][2] = z;
}
// render samples on screen with the option to scale the data
void drawSamples(float scale) {
beginShape();
for (int i = 0 ; i < numSamples; i++){
vertex(samples[i][0] * scale, samples[i][1] * scale, samples[i][2] * scale);
}
endShape();
}
void drawAxes(float x, float y, float z) {
//X - red
stroke(192, 0, 0);
line( 0, 0, 0, x, 0, 0);
//Y - green
stroke(0, 192, 0);
line(0, 0, 0, 0, y, 0);
//Z - blue
stroke(0, 0, 192);
line(0, 0, 0, 0, 0, z);
}
注意一些变化:
DataLine
重命名为dataLine
(根据 Java Naming Conventions)- 通常将变量重命名为易于理解的内容are/do并格式化代码以便于阅读
- 处理串行端口连接时出错。您已经对传入数据进行了错误处理,这很棒。
我们的想法是随着你的进步养成良好的习惯。
如果您有时间探索其他语言,我推荐 Python 和一些模块, 如果感兴趣,可能会启动 cluserting/classifying 传感器数据:
- pyserial用于串口通信
- SciPy:
numpy
for fast array manipulation, matplotlib for plotting and sklearn 对于 classiciation/clustering/etc.