Changed calculator to use physics simulation
This commit is contained in:
parent
62d379fd3b
commit
24f16d2491
2
Makefile
2
Makefile
@ -1,2 +1,2 @@
|
||||
all:
|
||||
g++ -std=c++11 gcode.cpp main.cpp Point.cpp -o gcode_time
|
||||
g++ -std=c++11 gcode.cpp main.cpp Point.cpp TimeCalc.cpp -o gcode_time
|
||||
|
||||
16
README.md
16
README.md
@ -1,6 +1,10 @@
|
||||
# Gcode Estimator
|
||||
C/C++ Gcode Estimator
|
||||
|
||||
# Credits
|
||||
JSON Library Used - https://github.com/nlohmann/json
|
||||
v3.11.2
|
||||
|
||||
### Prerequisites
|
||||
`g++ make`
|
||||
|
||||
@ -8,12 +12,18 @@ C/C++ Gcode Estimator
|
||||
1. Go to the directory
|
||||
2. Execute `make`
|
||||
|
||||
### Settings
|
||||
* Use as is to get linear calculations for time
|
||||
* Copy `config_example.json` to `config.json` and edit based on your printer settings
|
||||
|
||||
### Usage
|
||||
`./gcode_time [file]`
|
||||
`./gcode_time [file] ...`
|
||||
|
||||
**file** - a file containing gcode
|
||||
|
||||
### Example output
|
||||
`Estimation - 05:20:10`
|
||||
`Estimation - 05:20:10`
|
||||
|
||||
`Adding 10% - 05:52:11`
|
||||
`Adding 10% - 05:52:11`
|
||||
|
||||
`Removing 10% - 04:48:09`
|
||||
|
||||
468
TimeCalc.cpp
Normal file
468
TimeCalc.cpp
Normal file
@ -0,0 +1,468 @@
|
||||
// 1. Dx Dy Dz De; e_total_offset += De;
|
||||
// 2. m = sqrt(Dx * Dx + Dy * Dy + Dz * Dz)
|
||||
// 3. Dx /= m; Dy /= m; Dz /= m; De /= m;
|
||||
// 4. V = min(speed, Vmax_x / Dx, Vmax_y / Dy, Vmax_z / Dz, Vmax_e / De);
|
||||
// 5. A = min(Amax_x / Dx, Amax_y / Dy, Amax_z / Dz, Amax_e / De);
|
||||
// 6. Vx = V * Dx; Vy = V * Dy; Vz = V * Dz; Ve = V * De;
|
||||
// 6.1 Vend_prev_x = Vx; ... -> Calculate prev move and wait for current Vend
|
||||
// 7. Ax = A * Dx; Ay = A * Dy; Az = A * Dz; Ae = A * De;
|
||||
// 8. time = max(calc_time_complex(x), ...(y), ...(z), ...(e))
|
||||
|
||||
#include "TimeCalc.h"
|
||||
|
||||
#define DEBUG_CALC 0
|
||||
|
||||
#include <limits>
|
||||
#include "math.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
static double vector_min(const vector<double>& vec)
|
||||
{
|
||||
double min;
|
||||
int idx;
|
||||
|
||||
if (vec.empty())
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
min = abs(vec[0]);
|
||||
|
||||
for (int i = 1; i < vec.size(); ++i)
|
||||
{
|
||||
if (abs(vec[i]) < min)
|
||||
{
|
||||
min = abs(vec[i]);
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
return vec[idx];
|
||||
}
|
||||
|
||||
static double vector_max(const vector<double>& vec)
|
||||
{
|
||||
double max;
|
||||
int idx;
|
||||
|
||||
if (vec.empty())
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
idx = 0;
|
||||
max = abs(vec[0]);
|
||||
|
||||
for (int i = 1; i < vec.size(); ++i)
|
||||
{
|
||||
if (abs(vec[i]) > max)
|
||||
{
|
||||
idx = i;
|
||||
max = abs(vec[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return vec[idx];
|
||||
}
|
||||
|
||||
static double calc_dist(double vel, double accel, double t)
|
||||
{
|
||||
return vel * t + 0.5 * accel * t * t;
|
||||
}
|
||||
|
||||
static double calc_time_to_accel(double accel, double vel_start, double vel_end)
|
||||
{
|
||||
return abs((vel_start - vel_end) / accel);
|
||||
}
|
||||
|
||||
// Triangle Velocity
|
||||
static double calc_time_very_complex(double dist, double vel_start, double vel_end, double accel)
|
||||
{
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double d;
|
||||
double val[2];
|
||||
double res = 0;
|
||||
|
||||
if (accel == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
a = accel;
|
||||
b = 2 * vel_end;
|
||||
c = (vel_end * vel_end - vel_start * vel_start)/(2 * accel) - dist;
|
||||
d = b * b - 4 * a * c;
|
||||
|
||||
d = sqrt(d);
|
||||
|
||||
val[0] = (-b + d)/(2*a);
|
||||
val[1] = (-b - d)/(2*a);
|
||||
|
||||
if (val[0] >= 0)
|
||||
{
|
||||
res = val[0];
|
||||
}
|
||||
|
||||
if (val[1] >= 0)
|
||||
{
|
||||
res = val[1];
|
||||
}
|
||||
|
||||
return (2 * res + (vel_end - vel_start) / accel);
|
||||
}
|
||||
|
||||
static double calc_time_complex(double dist, double accel, double max_vel_change, double vel_start, double vel_end, double vel_max_target)
|
||||
{
|
||||
double result = 0.0;
|
||||
double accel_time;
|
||||
double accel_dist;
|
||||
double deccel_time;
|
||||
double deccel_dist;
|
||||
|
||||
if (dist == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (accel == 0)
|
||||
{
|
||||
// Linear calculation - It's something
|
||||
return dist/vel_max_target;
|
||||
}
|
||||
|
||||
// "Instant" velocity change on <= "Jerk"
|
||||
if (vel_max_target != vel_start)
|
||||
{
|
||||
if (abs(vel_max_target - vel_start) <= max_vel_change)
|
||||
{
|
||||
vel_start = vel_max_target;
|
||||
}
|
||||
}
|
||||
|
||||
// "Instant" velocity change on <= "Jerk"
|
||||
if (vel_max_target != vel_end)
|
||||
{
|
||||
if (abs(vel_max_target - vel_end) <= max_vel_change)
|
||||
{
|
||||
vel_end = vel_max_target;
|
||||
}
|
||||
}
|
||||
|
||||
accel_time = calc_time_to_accel(accel, vel_start, vel_max_target);
|
||||
accel_dist = calc_dist(vel_start, accel, accel_time);
|
||||
|
||||
deccel_time = calc_time_to_accel(accel, vel_max_target, vel_end);
|
||||
deccel_dist = calc_dist(vel_max_target, -accel, deccel_time);
|
||||
|
||||
// Triangle Velocity
|
||||
if (abs(accel_dist + deccel_dist) > abs(dist))
|
||||
{
|
||||
result = calc_time_very_complex(dist, vel_start, vel_end, accel);
|
||||
// Something's fucky
|
||||
if (0 == result)
|
||||
{
|
||||
// Linear calculation - It's something
|
||||
return abs(dist/vel_max_target);
|
||||
}
|
||||
}
|
||||
// Trapezoid Velocity
|
||||
else
|
||||
{
|
||||
dist -= (accel_dist + deccel_dist);
|
||||
result += (accel_time + deccel_time);
|
||||
result += abs(dist / vel_max_target);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
TimeCalc::PrinterMove::PrinterMove()
|
||||
: dist(0.0)
|
||||
{
|
||||
fill_n(delta, AXIS_COUNT, 0.0);
|
||||
fill_n(unit, AXIS_COUNT, 0.0);
|
||||
fill_n(vel, AXIS_COUNT, 0.0);
|
||||
fill_n(accel, AXIS_COUNT, 0.0);
|
||||
fill_n(vel_start, AXIS_COUNT, 0.0);
|
||||
fill_n(vel_end, AXIS_COUNT, 0.0);
|
||||
}
|
||||
|
||||
TimeCalc::TimeCalc()
|
||||
: m_time(0.0)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void TimeCalc::reset()
|
||||
{
|
||||
m_time = 0.0;
|
||||
|
||||
fill_n(m_extruder_length, EXTRUDER_COUNT, 0.0);
|
||||
fill_n(m_pos, AXIS_COUNT, 0.0);
|
||||
fill_n(m_accel_max, AXIS_COUNT, 0.0);
|
||||
fill_n(m_vel_max, AXIS_COUNT, 0.0);
|
||||
fill_n(m_jerk_max, AXIS_COUNT, 0.0);
|
||||
|
||||
m_moves.clear();
|
||||
}
|
||||
|
||||
void TimeCalc::add_move(Point new_pos, double speed)
|
||||
{
|
||||
PrinterMove move_new;
|
||||
vector<double> temp;
|
||||
Point pos_temp;
|
||||
double pos_new[AXIS_COUNT];
|
||||
double vel;
|
||||
double accel;
|
||||
double prev_move_idx;
|
||||
static int counter = 0;
|
||||
|
||||
pos_new[0] = new_pos.x;
|
||||
pos_new[1] = new_pos.y;
|
||||
pos_new[2] = new_pos.z;
|
||||
pos_new[3] = new_pos.e;
|
||||
|
||||
pos_temp = Point(m_pos[0], m_pos[1], m_pos[2], m_pos[3]);
|
||||
|
||||
move_new.dist = new_pos.get_dist(pos_temp);
|
||||
|
||||
#if DEBUG_CALC
|
||||
cout << "---" << endl;
|
||||
cout << "Dist - " << move_new.dist << endl;
|
||||
#endif
|
||||
|
||||
if (0.0 == move_new.dist)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate Delta And Unit Vector
|
||||
for (int i = 0 ; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
move_new.delta[i] = pos_new[i] - m_pos[i];
|
||||
move_new.unit[i] = move_new.delta[i] / move_new.dist;
|
||||
#if DEBUG_CALC
|
||||
cout << "Unit [" << i << "] - " << move_new.unit[i] << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Calculate velocity
|
||||
temp.clear();
|
||||
temp.push_back(speed);
|
||||
for (int i = 0 ; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
if (0.0 != move_new.unit[i] && 0.0 != m_vel_max[i])
|
||||
{
|
||||
temp.push_back(m_vel_max[i] / move_new.unit[i]);
|
||||
}
|
||||
}
|
||||
vel = abs(vector_min(temp));
|
||||
|
||||
#if DEBUG_CALC
|
||||
cout << "Vel - " << vel << endl;
|
||||
#endif
|
||||
|
||||
// Calculate acceleration
|
||||
temp.clear();
|
||||
for (int i = 0 ; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
if (0.0 != move_new.unit[i] && 0.0 != m_accel_max[i])
|
||||
{
|
||||
temp.push_back(m_accel_max[i] / move_new.unit[i]);
|
||||
}
|
||||
}
|
||||
accel = abs(vector_min(temp));
|
||||
|
||||
#if DEBUG_CALC
|
||||
cout << "Accel - " << accel << endl;
|
||||
#endif
|
||||
|
||||
// Calculate Component Velocity and Acceleration
|
||||
for (int i = 0 ; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
move_new.vel[i] = vel * move_new.unit[i];
|
||||
move_new.accel[i] = accel * move_new.unit[i];
|
||||
}
|
||||
|
||||
// Calculate veclocities for/from previous move
|
||||
if (!m_moves.empty())
|
||||
{
|
||||
prev_move_idx = m_moves.size() - 1;
|
||||
|
||||
for (int i = 0; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
// If we're changing direction
|
||||
if (m_moves[prev_move_idx].vel[i] * move_new.vel[i] < 0)
|
||||
{
|
||||
m_moves[prev_move_idx].vel_end[i] = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we're accelerating
|
||||
if (abs(m_moves[prev_move_idx].vel[i]) < abs(move_new.vel[i]))
|
||||
{
|
||||
m_moves[prev_move_idx].vel_end[i] = m_moves[prev_move_idx].vel[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
m_moves[prev_move_idx].vel_end[i] = move_new.vel[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calc end velocity for prev move
|
||||
temp.clear();
|
||||
for (int i = 0; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
if (0.0 != m_moves[prev_move_idx].unit[i])
|
||||
{
|
||||
temp.push_back(m_moves[prev_move_idx].vel_end[i] / m_moves[prev_move_idx].unit[i]);
|
||||
}
|
||||
}
|
||||
vel = vector_min(temp);
|
||||
|
||||
for (int i = 0; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
m_moves[prev_move_idx].vel_end[i] = vel * m_moves[prev_move_idx].unit[i];
|
||||
move_new.vel_start[i] = m_moves[prev_move_idx].vel_end[i];
|
||||
#if DEBUG_CALC
|
||||
cout << "Vel Start [" << i << "] - " << m_moves[prev_move_idx].vel_end[i] << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Do a move calculation
|
||||
flush();
|
||||
}
|
||||
|
||||
m_moves.push_back(move_new);
|
||||
for (int i = 0; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
m_pos[i] = pos_new[i];
|
||||
}
|
||||
}
|
||||
|
||||
void TimeCalc::set_pos(Point new_pos)
|
||||
{
|
||||
flush();
|
||||
if (new_pos.e != m_pos[3])
|
||||
{
|
||||
m_extruder_length[0] += m_pos[3];
|
||||
m_extruder_length[0] -= new_pos.e;
|
||||
}
|
||||
|
||||
m_pos[0] = new_pos.x;
|
||||
m_pos[1] = new_pos.y;
|
||||
m_pos[2] = new_pos.z;
|
||||
m_pos[3] = new_pos.e;
|
||||
}
|
||||
|
||||
void TimeCalc::flush()
|
||||
{
|
||||
vector<double> times;
|
||||
double max;
|
||||
|
||||
for (PrinterMove& move : m_moves)
|
||||
{
|
||||
// Find the slowest axis and add it to the total time
|
||||
times.clear();
|
||||
for (int i = 0; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
times.push_back(calc_time_complex(move.delta[i], move.accel[i],
|
||||
m_jerk_max[i], move.vel_start[i], move.vel_end[i], move.vel[i]));
|
||||
}
|
||||
max = vector_max(times);
|
||||
|
||||
if (max < 0)
|
||||
{
|
||||
printf("Dist - %10.5f - %10.5f\n", move.dist, max);
|
||||
|
||||
for (int i = 0; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
printf("Delta [%d] - %10.5f\n", i, move.delta[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
printf("Unit [%d] - %10.5f\n", i, move.unit[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
printf("V0 [%d] - %10.5f\n", i, move.vel_start[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
printf("Vel [%d] - %10.5f\n", i, move.vel[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
printf("V2 [%d] - %10.5f\n", i, move.vel_end[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < AXIS_COUNT; ++i)
|
||||
{
|
||||
printf("Accel [%d] - %10.5f\n", i, move.accel[i]);
|
||||
}
|
||||
}
|
||||
m_time += max;
|
||||
}
|
||||
m_moves.clear();
|
||||
}
|
||||
|
||||
void TimeCalc::add_time(double time)
|
||||
{
|
||||
m_time += time;
|
||||
}
|
||||
|
||||
double TimeCalc::get_time() const
|
||||
{
|
||||
return m_time;
|
||||
}
|
||||
|
||||
double TimeCalc::get_extruder_length(int idx) const
|
||||
{
|
||||
if (idx >= EXTRUDER_COUNT)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return m_extruder_length[idx] + m_pos[3 + idx];
|
||||
}
|
||||
|
||||
Point TimeCalc::get_pos() const
|
||||
{
|
||||
return Point(m_pos[0], m_pos[1], m_pos[2], m_pos[3]);
|
||||
}
|
||||
|
||||
void TimeCalc::set_max_acceleration(int axis, double value)
|
||||
{
|
||||
if ((axis > 0) && (axis < AXIS_COUNT))
|
||||
{
|
||||
m_accel_max[axis] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void TimeCalc::set_max_velocity(int axis, double value)
|
||||
{
|
||||
if ((axis > 0) && (axis < AXIS_COUNT))
|
||||
{
|
||||
m_vel_max[axis] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void TimeCalc::set_max_jerk(int axis, double value)
|
||||
{
|
||||
if ((axis > 0) && (axis < AXIS_COUNT))
|
||||
{
|
||||
m_jerk_max[axis] = value;
|
||||
}
|
||||
}
|
||||
56
TimeCalc.h
Normal file
56
TimeCalc.h
Normal file
@ -0,0 +1,56 @@
|
||||
#ifndef TIMECALC_H_
|
||||
#define TIMECALC_H_
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "Point.h"
|
||||
#define EXTRUDER_COUNT 1
|
||||
#define AXIS_COUNT (3 + EXTRUDER_COUNT)
|
||||
|
||||
class TimeCalc
|
||||
{
|
||||
public:
|
||||
struct PrinterMove
|
||||
{
|
||||
PrinterMove();
|
||||
|
||||
double dist;
|
||||
double delta[AXIS_COUNT];
|
||||
double unit[AXIS_COUNT];
|
||||
double vel[AXIS_COUNT];
|
||||
double accel[AXIS_COUNT];
|
||||
double vel_start[AXIS_COUNT];
|
||||
double vel_end[AXIS_COUNT];
|
||||
};
|
||||
|
||||
private:
|
||||
double m_extruder_length[EXTRUDER_COUNT];
|
||||
double m_time;
|
||||
double m_pos[AXIS_COUNT];
|
||||
|
||||
double m_accel_max[AXIS_COUNT];
|
||||
double m_vel_max[AXIS_COUNT];
|
||||
double m_jerk_max[AXIS_COUNT];
|
||||
|
||||
std::vector<PrinterMove> m_moves;
|
||||
|
||||
public:
|
||||
TimeCalc();
|
||||
|
||||
void reset();
|
||||
|
||||
void add_move(Point new_pos, double speed);
|
||||
void set_pos(Point new_pos);
|
||||
void flush();
|
||||
void add_time(double time);
|
||||
double get_time() const;
|
||||
double get_extruder_length(int idx) const;
|
||||
Point get_pos() const;
|
||||
|
||||
void set_max_acceleration(int axis, double value);
|
||||
void set_max_velocity(int axis, double value);
|
||||
void set_max_jerk(int axis, double value);
|
||||
};
|
||||
|
||||
#endif // TIMECALC_H_
|
||||
28
config_example.json
Normal file
28
config_example.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"x":
|
||||
{
|
||||
"acceleration": 500,
|
||||
"velocity": 500,
|
||||
"jerk": 10
|
||||
},
|
||||
"y":
|
||||
{
|
||||
"acceleration": 500,
|
||||
"velocity": 500,
|
||||
"jerk": 10
|
||||
},
|
||||
"z":
|
||||
{
|
||||
"acceleration": 100,
|
||||
"velocity": 5,
|
||||
"jerk": 0.4
|
||||
},
|
||||
"extruders":
|
||||
[
|
||||
{
|
||||
"acceleration": 500,
|
||||
"velocity": 50,
|
||||
"jerk": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
165
gcode.cpp
165
gcode.cpp
@ -37,16 +37,21 @@ pair<char, double> extract_argument(const string& str)
|
||||
return result;
|
||||
}
|
||||
|
||||
void gcode_dummy(const vector<string>&, TimeCalc&, double&)
|
||||
{
|
||||
}
|
||||
|
||||
// Linear Move
|
||||
double g1(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
void g1(const vector<string>& line_tokens, TimeCalc& calc, double& speed)
|
||||
{
|
||||
double result;
|
||||
vector<string>::const_iterator it;
|
||||
pair<char, double> arg;
|
||||
Point end;
|
||||
Point pos = calc.get_pos();
|
||||
Point pos_old = pos;
|
||||
double distance;
|
||||
static int counter = 1;
|
||||
|
||||
end = pos;
|
||||
it = line_tokens.begin();
|
||||
for (++it; it != line_tokens.end(); ++it)
|
||||
{
|
||||
@ -56,28 +61,34 @@ double g1(const vector<string>& line_tokens, Point& pos, double& speed, double&
|
||||
{
|
||||
// Extruder
|
||||
case 'E':
|
||||
end.e = arg.second;
|
||||
case 'e':
|
||||
pos.e = arg.second;
|
||||
break;
|
||||
|
||||
// Feedrate (Speed) in units/min
|
||||
case 'F':
|
||||
case 'f':
|
||||
speed = arg.second / 60;
|
||||
break;
|
||||
|
||||
// Laser power
|
||||
case 'S':
|
||||
case 's':
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
end.x = arg.second;
|
||||
case 'x':
|
||||
pos.x = arg.second;
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
end.y = arg.second;
|
||||
case 'y':
|
||||
pos.y = arg.second;
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
end.z = arg.second;
|
||||
case 'z':
|
||||
pos.z = arg.second;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -86,45 +97,11 @@ double g1(const vector<string>& line_tokens, Point& pos, double& speed, double&
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
for (vector<string>::const_iterator it = line_tokens.begin(); it != line_tokens.end(); ++it)
|
||||
{
|
||||
cout << *it << " ";
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
cout << "Old pos - ";
|
||||
pos.print();
|
||||
cout << endl;
|
||||
cout << "New pos - ";
|
||||
end.print();
|
||||
cout << endl;
|
||||
#endif // DEBUG
|
||||
|
||||
result = 0;
|
||||
// Perform time calc
|
||||
distance = pos.get_dist(end);
|
||||
#if DEBUG
|
||||
cout << "Distance - " << distance << endl;
|
||||
cout << "Speed - " << speed << endl;
|
||||
#endif
|
||||
if (0 != speed)
|
||||
{
|
||||
result = distance / speed;
|
||||
}
|
||||
|
||||
// Our new position
|
||||
pos = end;
|
||||
|
||||
#if DEBUG
|
||||
cout << "Time - " << result << endl << endl;
|
||||
#endif // DEBUG
|
||||
|
||||
return result;
|
||||
calc.add_move(pos, speed);
|
||||
}
|
||||
|
||||
// Dwell
|
||||
double g4(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
void g4(const vector<string>& line_tokens, TimeCalc& calc, double& speed)
|
||||
{
|
||||
double result;
|
||||
vector<string>::const_iterator it;
|
||||
@ -140,11 +117,13 @@ double g4(const vector<string>& line_tokens, Point& pos, double& speed, double&
|
||||
{
|
||||
// P is for miliseconds
|
||||
case 'P':
|
||||
case 'p':
|
||||
result += arg.second / 1000;
|
||||
break;
|
||||
|
||||
// S is for seconds
|
||||
case 'S':
|
||||
case 's':
|
||||
result += arg.second;
|
||||
break;
|
||||
|
||||
@ -154,43 +133,27 @@ double g4(const vector<string>& line_tokens, Point& pos, double& speed, double&
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
for (vector<string>::const_iterator it = line_tokens.begin(); it != line_tokens.end(); ++it)
|
||||
{
|
||||
cout << *it << " ";
|
||||
}
|
||||
cout << endl;
|
||||
|
||||
cout << "Time - " << result << endl << endl;
|
||||
#endif // DEBUG
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Set Units to Milimeters
|
||||
double g21(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
{
|
||||
return 0;
|
||||
calc.add_time(result);
|
||||
}
|
||||
|
||||
// Move to Origin (Home)
|
||||
double g28(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
void g28(const vector<string>& line_tokens, TimeCalc& calc, double& speed)
|
||||
{
|
||||
// Used only at beginning or end so not relevant
|
||||
return 0;
|
||||
}
|
||||
Point pos = calc.get_pos();
|
||||
|
||||
// Set to Absolute Positioning
|
||||
double g90(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
{
|
||||
return 0;
|
||||
pos.x = 0;
|
||||
pos.y = 0;
|
||||
pos.z = 0;
|
||||
|
||||
calc.set_pos(pos);
|
||||
}
|
||||
|
||||
// Set Position
|
||||
double g92(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
void g92(const vector<string>& line_tokens, TimeCalc& calc, double& speed)
|
||||
{
|
||||
vector<string>::const_iterator it;
|
||||
pair<char, double> arg;
|
||||
Point pos = calc.get_pos();
|
||||
|
||||
#if DEBUG
|
||||
for (vector<string>::const_iterator it = line_tokens.begin(); it != line_tokens.end(); ++it)
|
||||
@ -212,20 +175,22 @@ double g92(const vector<string>& line_tokens, Point& pos, double& speed, double&
|
||||
switch (arg.first)
|
||||
{
|
||||
case 'E':
|
||||
e_total_offset += pos.e;
|
||||
e_total_offset -= arg.second;
|
||||
case 'e':
|
||||
pos.e = arg.second;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
case 'x':
|
||||
pos.x = arg.second;
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
case 'y':
|
||||
pos.y = arg.second;
|
||||
break;
|
||||
|
||||
case 'Z':
|
||||
case 'z':
|
||||
pos.z = arg.second;
|
||||
break;
|
||||
|
||||
@ -242,61 +207,5 @@ double g92(const vector<string>& line_tokens, Point& pos, double& speed, double&
|
||||
#endif // DEBUG
|
||||
|
||||
// There's no actual movement
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set extruder to absolute mode
|
||||
double m82(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Stop idle hold
|
||||
double m84(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set Extruder Temperature
|
||||
double m104(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Fan On
|
||||
double m106(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Fan Off
|
||||
double m107(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set Extruder Temperature and Wait
|
||||
double m109(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
{
|
||||
// Assume everything is preheated
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Display Message
|
||||
double m117(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set Bed Temperature (Fast)
|
||||
double m140(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Wait for bed temperature to reach target temp
|
||||
double m190(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset)
|
||||
{
|
||||
// Assume everything is preheated
|
||||
return 0;
|
||||
calc.set_pos(pos);
|
||||
}
|
||||
|
||||
27
gcode.h
27
gcode.h
@ -5,28 +5,21 @@
|
||||
#include <string>
|
||||
|
||||
#include "Point.h"
|
||||
#include "TimeCalc.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
// Typedef of the function pointer
|
||||
typedef double (*gcode_cmd_t)(const vector<string>&, Point&, double&, double&);
|
||||
typedef void (*gcode_cmd_t)(const vector<string>&, TimeCalc&, double&);
|
||||
|
||||
// Always returns 0 sec
|
||||
void gcode_dummy(const vector<string>&, TimeCalc&, double&);
|
||||
|
||||
// All handled gcode commands
|
||||
double g1(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double g4(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double g21(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double g28(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double g90(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double g92(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
|
||||
double m82(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double m84(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double m104(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double m106(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double m107(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double m109(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double m117(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double m140(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
double m190(const vector<string>& line_tokens, Point& pos, double& speed, double& e_total_offset);
|
||||
void g1(const vector<string>& line_tokens, TimeCalc& calc, double& speed);
|
||||
void g4(const vector<string>& line_tokens, TimeCalc& calc, double& speed);
|
||||
void g28(const vector<string>& line_tokens, TimeCalc& calc, double& speed);
|
||||
void g92(const vector<string>& line_tokens, TimeCalc& calc, double& speed);
|
||||
|
||||
#endif // GCODE_H_
|
||||
|
||||
188
main.cpp
188
main.cpp
@ -7,12 +7,14 @@
|
||||
|
||||
#include "Point.h"
|
||||
#include "gcode.h"
|
||||
#include "json.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void usage(char *name)
|
||||
{
|
||||
cout << "Usage: " << name << " [file]" << endl;
|
||||
cout << "Usage:" << endl;
|
||||
cout << name << " [file] ..." << endl;
|
||||
}
|
||||
|
||||
bool is_gcode(const string& line)
|
||||
@ -78,44 +80,44 @@ void init_map(map<string, gcode_cmd_t>& gcode_map)
|
||||
gcode_map["G4"] = g4;
|
||||
gcode_map["g4"] = g4;
|
||||
|
||||
gcode_map["G21"] = g21;
|
||||
gcode_map["g21"] = g21;
|
||||
gcode_map["G21"] = gcode_dummy;
|
||||
gcode_map["g21"] = gcode_dummy;
|
||||
|
||||
gcode_map["G28"] = g28;
|
||||
gcode_map["g28"] = g28;
|
||||
|
||||
gcode_map["G90"] = g90;
|
||||
gcode_map["g90"] = g90;
|
||||
gcode_map["G90"] = gcode_dummy;
|
||||
gcode_map["g90"] = gcode_dummy;
|
||||
|
||||
gcode_map["G92"] = g92;
|
||||
gcode_map["g92"] = g92;
|
||||
|
||||
gcode_map["M82"] = m82;
|
||||
gcode_map["m82"] = m82;
|
||||
gcode_map["M82"] = gcode_dummy;
|
||||
gcode_map["m82"] = gcode_dummy;
|
||||
|
||||
gcode_map["M84"] = m84;
|
||||
gcode_map["m84"] = m84;
|
||||
gcode_map["M84"] = gcode_dummy;
|
||||
gcode_map["m84"] = gcode_dummy;
|
||||
|
||||
gcode_map["M104"] = m104;
|
||||
gcode_map["m104"] = m104;
|
||||
gcode_map["M104"] = gcode_dummy;
|
||||
gcode_map["m104"] = gcode_dummy;
|
||||
|
||||
gcode_map["M106"] = m106;
|
||||
gcode_map["m106"] = m106;
|
||||
gcode_map["M106"] = gcode_dummy;
|
||||
gcode_map["m106"] = gcode_dummy;
|
||||
|
||||
gcode_map["M107"] = m107;
|
||||
gcode_map["m107"] = m107;
|
||||
gcode_map["M107"] = gcode_dummy;
|
||||
gcode_map["m107"] = gcode_dummy;
|
||||
|
||||
gcode_map["M109"] = m109;
|
||||
gcode_map["m109"] = m109;
|
||||
gcode_map["M109"] = gcode_dummy;
|
||||
gcode_map["m109"] = gcode_dummy;
|
||||
|
||||
gcode_map["M117"] = m117;
|
||||
gcode_map["m117"] = m117;
|
||||
gcode_map["M117"] = gcode_dummy;
|
||||
gcode_map["m117"] = gcode_dummy;
|
||||
|
||||
gcode_map["M140"] = m140;
|
||||
gcode_map["m140"] = m140;
|
||||
gcode_map["M140"] = gcode_dummy;
|
||||
gcode_map["m140"] = gcode_dummy;
|
||||
|
||||
gcode_map["M190"] = m190;
|
||||
gcode_map["m190"] = m190;
|
||||
gcode_map["M190"] = gcode_dummy;
|
||||
gcode_map["m190"] = gcode_dummy;
|
||||
}
|
||||
|
||||
void print_time(double sec)
|
||||
@ -131,18 +133,79 @@ void print_time(double sec)
|
||||
printf("%02d:%02d:%02.0f", hours, min, sec);
|
||||
}
|
||||
|
||||
void init_calc(TimeCalc& calc)
|
||||
{
|
||||
ifstream file("config.json");
|
||||
nlohmann::json conf;
|
||||
vector<string> conf_keys = {"x", "y", "z"};
|
||||
|
||||
try
|
||||
{
|
||||
file >> conf;
|
||||
}
|
||||
catch (const exception& e)
|
||||
{
|
||||
cout << e.what() << endl;
|
||||
return;
|
||||
}
|
||||
file.close();
|
||||
|
||||
for (int i = 0; i < conf_keys.size(); ++i)
|
||||
{
|
||||
string key = conf_keys[i];
|
||||
if (conf.contains(key) && conf[key].is_object())
|
||||
{
|
||||
if (conf[key].contains("acceleration") && conf[key]["acceleration"].is_number())
|
||||
{
|
||||
calc.set_max_acceleration(i, conf[key]["acceleration"]);
|
||||
}
|
||||
|
||||
if (conf[key].contains("velocity") && conf[key]["velocity"].is_number())
|
||||
{
|
||||
calc.set_max_velocity(i, conf[key]["velocity"]);
|
||||
}
|
||||
|
||||
if (conf[key].contains("jerk") && conf[key]["jerk"].is_number())
|
||||
{
|
||||
calc.set_max_jerk(i, conf[key]["jerk"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (conf.contains("extruders") && conf["extruders"].is_array())
|
||||
{
|
||||
for (int i = 0; i < conf["extruders"].size(); ++i)
|
||||
{
|
||||
if (conf["extruders"][i].contains("acceleration") && conf["extruders"][i]["acceleration"].is_number())
|
||||
{
|
||||
calc.set_max_acceleration(3 + i, conf["extruders"][i]["acceleration"]);
|
||||
}
|
||||
|
||||
if (conf["extruders"][i].contains("velocity") && conf["extruders"][i]["velocity"].is_number())
|
||||
{
|
||||
calc.set_max_velocity(3 + i, conf["extruders"][i]["velocity"]);
|
||||
}
|
||||
|
||||
if (conf["extruders"][i].contains("jerk") && conf["extruders"][i]["jerk"].is_number())
|
||||
{
|
||||
calc.set_max_jerk(3 + i, conf["extruders"][i]["jerk"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ifstream file;
|
||||
string line;
|
||||
vector<string> filenames(&(argv[1]), &(argv[argc]));
|
||||
vector<string> line_tokens;
|
||||
|
||||
map<string, gcode_cmd_t> gcode_map;
|
||||
|
||||
Point pos;
|
||||
TimeCalc calc;
|
||||
double speed;
|
||||
double total_time;
|
||||
double e_total;
|
||||
int hours;
|
||||
int minutes;
|
||||
|
||||
@ -152,48 +215,55 @@ int main(int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pos.x = 0;
|
||||
pos.y = 0;
|
||||
pos.z = 0;
|
||||
pos.e = 0;
|
||||
speed = 0;
|
||||
total_time = 0;
|
||||
e_total = 0;
|
||||
|
||||
init_map(gcode_map);
|
||||
|
||||
file.open(argv[1]);
|
||||
while (!file.eof())
|
||||
for (string& fname : filenames)
|
||||
{
|
||||
getline(file, line);
|
||||
if (!is_gcode(remove_comments(line)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
line_tokens = tokenize_line(line);
|
||||
calc.reset();
|
||||
init_calc(calc);
|
||||
speed = 0;
|
||||
|
||||
if (0 != gcode_map.count(line_tokens[0]))
|
||||
file.open(fname);
|
||||
while (!file.eof())
|
||||
{
|
||||
total_time += gcode_map[line_tokens[0]](line_tokens, pos, speed, e_total);
|
||||
getline(file, line);
|
||||
if (!is_gcode(remove_comments(line)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
line_tokens = tokenize_line(line);
|
||||
|
||||
if (0 != gcode_map.count(line_tokens[0]))
|
||||
{
|
||||
gcode_map[line_tokens[0]](line_tokens, calc, speed);
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "Unknown Gcode '" << line_tokens[0] << "'" << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
file.close();
|
||||
|
||||
if (filenames.size() > 1)
|
||||
{
|
||||
cout << "Unknown Gcode '" << line_tokens[0] << "'" << endl;
|
||||
cout << "--- " << fname << " ---" << endl;
|
||||
}
|
||||
|
||||
calc.flush();
|
||||
total_time = calc.get_time();
|
||||
cout << "Filament - " << calc.get_extruder_length(0) << "mm" << endl;
|
||||
|
||||
cout << "Estimation - ";
|
||||
print_time(total_time);
|
||||
cout << endl;
|
||||
|
||||
cout << "Adding 10% - ";
|
||||
print_time(total_time * 1.1);
|
||||
cout << endl;
|
||||
|
||||
cout << "Removing 10% - ";
|
||||
print_time(total_time * 0.9);
|
||||
cout << endl;
|
||||
}
|
||||
file.close();
|
||||
|
||||
e_total += pos.e;
|
||||
|
||||
cout << "Filament - " << e_total << "mm" << endl;
|
||||
|
||||
cout << "Estimation - ";
|
||||
print_time(total_time);
|
||||
cout << endl;
|
||||
|
||||
cout << "Adding 10% - ";
|
||||
print_time(total_time * 1.1);
|
||||
cout << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user