LinuxCNC S-разгон и торможение

Обсуждение установки, настройки и использования LinuxCNC. Вопросы по Gкоду.
Аватара пользователя
Nick
Мастер
Сообщения: 22776
Зарегистрирован: 23 ноя 2009, 16:45
Репутация: 1735
Заслуга: Developer
Откуда: Gatchina, Saint-Petersburg distr., Russia
Контактная информация:

LinuxCNC S-разгон и торможение

Сообщение Nick »

В воздухе летает настойчивая мысль реализовать таки S-разгон в LinuxCNC.
Вроде как уже есть что-то подобное:
https://github.com/araisrobo/linuxcnc/b ... s/tp.c#808

Но мне кажется что-то они с этой функцией намудрили... :problem:

В связи с этим есть желание самому разобраться, где бы почитать про функции, которые надо переписать для реализации S-разгона?

Насколько я понимаю надо переписать планировщик скоростей и сглаживатель траекторий.
Аватара пользователя
Nick
Мастер
Сообщения: 22776
Зарегистрирован: 23 ноя 2009, 16:45
Репутация: 1735
Заслуга: Developer
Откуда: Gatchina, Saint-Petersburg distr., Russia
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение Nick »

Что намудрили с функцией разгона Araisrobo:

Было:

Код: Выделить всё

void tcRunCycle(TP_STRUCT *tp, TC_STRUCT *tc, double *v, int *on_final_decel) {
    double discr, maxnewvel, newvel, newaccel=0;
    if(!tc->blending) tc->vel_at_blend_start = tc->currentvel;

    discr = 0.5 * tc->cycle_time * tc->currentvel - (tc->target - tc->progress);
    
    if(discr > 0.0) {
        // should never happen: means we've overshot the target
        newvel = maxnewvel = 0.0;
    } else {
        discr = 0.25 * pmSq(tc->cycle_time) - 2.0 / tc->maxaccel * discr;
        newvel = maxnewvel = -0.5 * tc->maxaccel * tc->cycle_time + tc->maxaccel * pmSqrt(discr);
    }
    
    if(newvel <= 0.0) {
        // also should never happen - if we already finished this tc, it was
        // caught above
        newvel = newaccel = 0.0;
        tc->progress = tc->target;
    } else {
        // constrain velocity
        if(newvel > tc->reqvel * tc->feed_override) newvel = tc->reqvel * tc->feed_override;
        if(newvel > tc->maxvel) newvel = tc->maxvel;

        // if the motion is not purely rotary axes (and therefore in angular units) ...
        if(!(tc->motion_type == TC_LINEAR && tc->coords.line.xyz.tmag_zero && tc->coords.line.uvw.tmag_zero)) {
            // ... clamp motion's velocity at TRAJ MAX_VELOCITY (tooltip maxvel)
            // except when it's synced to spindle position.
            if((!tc->synchronized || tc->velocity_mode) && newvel > tp->vLimit) {
                newvel = tp->vLimit;
            }
        }

        // get resulting acceleration
        newaccel = (newvel - tc->currentvel) / tc->cycle_time;
        
        // constrain acceleration and get resulting velocity
        if(newaccel > 0.0 && newaccel > tc->maxaccel) {
            newaccel = tc->maxaccel;
            newvel = tc->currentvel + newaccel * tc->cycle_time;
        }
        if(newaccel < 0.0 && newaccel < -tc->maxaccel) {
            newaccel = -tc->maxaccel;
            newvel = tc->currentvel + newaccel * tc->cycle_time;
        }
        // update position in this tc
        tc->progress += (newvel + tc->currentvel) * 0.5 * tc->cycle_time;
    }
    tc->currentvel = newvel;
    if(v) *v = newvel;
    if(on_final_decel) *on_final_decel = fabs(maxnewvel - newvel) < 0.001;
}
Т.е. простое вычисление ускорения и скорости для нормального движения исходя из текущей и максимальной скорости, ускорения, положения и заданного положения.

Стало:

Код: Выделить всё

/*
 Continuous form
 PT = P0 + V0T + 1/2A0T2 + 1/6JT3
 VT = V0 + A0T + 1/2 JT2
 AT = A0 + JT

 Discrete time form (let T be 1, then T^2 == 1, T^3 == 1)
 PT = PT + VT + 1/2AT + 1/6J
 VT = VT + AT + 1/2JT
 AT = AT + JT
 */
/**
 * S-curve Velocity Profiler FSM
 * Yishin Li <ysli@araisrobo.com>
 * ARAIS ROBOT TECHNOLOGY, http://www.araisrobo.com/
 **/
void tcRunCycle(TP_STRUCT *tp, TC_STRUCT *tc) 
{
    double t, t1, vel, v1, dist, req_vel;
    int immediate_state;
    double tc_target;
    
    if(tc->seamless_blend_mode == SMLBLND_ENABLE) {
        tc_target = tc->target + tc->nexttc_target;
    } else {
        tc_target = tc->target;
    }

    immediate_state = 0;
    do {
        switch (tc->accel_state) {
        case ACCEL_S0:
            // AT = AT + JT
            // VT = VT + AT + 1/2JT
            // PT = PT + VT + 1/2AT + 1/6JT
            tc->cur_accel = tc->cur_accel + tc->jerk;
            tc->cur_vel = tc->cur_vel + tc->cur_accel + 0.5 * tc->jerk;
            tc->progress = tc->progress + tc->cur_vel + 0.5 * tc->cur_accel + 1.0/6.0 * tc->jerk;
            
            // check if we hit accel limit at next BP
            if ((tc->cur_accel + tc->jerk) >= tc->maxaccel) {
                tc->cur_accel = tc->maxaccel;
                tc->accel_state = ACCEL_S1;
                break;
            }
            
            // check if we will hit velocity limit; 
            // assume we start decel from here to "accel == 0"
            //
            // AT = A0 + JT (let AT = 0 to calculate T)
            // VT = V0 + A0T + 1/2JT2
            t = ceil(tc->cur_accel / tc->jerk);
            req_vel = tc->reqvel * tc->feed_override * tc->cycle_time;
            if (req_vel > tc->maxvel) {
                req_vel = tc->maxvel;
            }
            vel = req_vel - tc->cur_accel * t + 0.5 * tc->jerk * t * t;
            if (tc->cur_vel >= vel) {
                tc->accel_state = ACCEL_S2;
                break;
            }

            // check if we will hit progress limit
            // AT = AT + JT
            // VT = V0 + A0T + 1/2 JT^2
            // PT = P0 + V0T + 1/2A0T^2 + 1/6JT^3
            // distance for S2
            t = ceil(tc->cur_accel/tc->jerk);
            dist = tc->progress + tc->cur_vel * t + 0.5 * tc->cur_accel * t * t
                   - 1.0/6.0 * tc->jerk * t * t * t;
            vel = tc->cur_vel + tc->cur_accel * t - 0.5 * tc->jerk * t * t;
            // distance for S3
            dist += (vel);
            
            /* 
            0.5 * vel = vel + 0 * t1 - 0.5 * j * t1 * t1;
            t1 = sqrt(vel/j)
            */
            t = ceil(sqrt(vel/tc->jerk));
            // AT = AT + JT
            t1 = ceil(tc->maxaccel / tc->jerk);   // max time for S4
            if (t > t1) {
                // S4 -> S5 -> S6
                dist += t1 * vel;    // dist of (S4 + S6)
                // calc decel.dist for ACCEL_S5
                // t: time for S5
                t = (vel - tc->jerk * t1 * t1) / tc->maxaccel;
                v1 = vel - 0.5 * tc->jerk * t1 * t1;
                // PT = P0 + V0T + 1/2A0T^2 + 1/6JT^3
                dist += (v1 * t - 0.5 * tc->maxaccel * t * t);
            } else {
                // S4 -> S6
                dist += t * vel;    // dist of (S4 + S6)
            }

            if (tc_target < dist) {
                tc->accel_state = ACCEL_S2;
                break;
            }

            break;
        
        case ACCEL_S1:
            // jerk is 0 at this state
            // VT = VT + AT + 1/2JT
            // PT = PT + VT + 1/2AT + 1/6JT
            tc->cur_vel = tc->cur_vel + tc->cur_accel;
            tc->progress = tc->progress + tc->cur_vel + 0.5 * tc->cur_accel;
            
            // check if we will hit velocity limit; 
            // assume we start decel from here to "accel == 0"
            //
            // AT = A0 + JT (let AT = 0 to calculate T)
            // VT = V0 + A0T + 1/2JT2
            // t = ceil(tc->cur_accel / tc->jerk);
            t = tc->cur_accel / tc->jerk;
            req_vel = tc->reqvel * tc->feed_override * tc->cycle_time;
            if (req_vel > tc->maxvel) {
                req_vel = tc->maxvel;
            }
            vel = req_vel - tc->cur_accel * t + 0.5 * tc->jerk * t * t;
            if (tc->cur_vel >= vel) {
                tc->accel_state = ACCEL_S2;
                break;
            }
            
            // check if we will hit progress limit
            // distance for S2
            t = ceil(tc->cur_accel/tc->jerk);
            dist = tc->progress + tc->cur_vel * t + 0.5 * tc->cur_accel * t * t
                   - 1.0/6.0 * tc->jerk * t * t * t;
            vel = tc->cur_vel + tc->cur_accel * t - 0.5 * tc->jerk * t * t;
            // distance for S3
            dist += (vel);
            
            /* 
            0.5 * vel = vel + 0 * t1 - 0.5 * j * t1 * t1;
            t1 = sqrt(vel/j)
            */
            t = ceil(sqrt(vel/tc->jerk));
            // AT = AT + JT
            t1 = ceil(tc->maxaccel / tc->jerk);   // max time for S4
            if (t > t1) {
                // S4 -> S5 -> S6
                dist += t1 * vel;    // dist of (S4 + S6)
                // calc decel.dist for ACCEL_S5
                // t: time for S5
                t = (vel - tc->jerk * t1 * t1) / tc->maxaccel;
                v1 = vel - 0.5 * tc->jerk * t1 * t1;
                // PT = P0 + V0T + 1/2A0T^2 + 1/6JT^3
                dist += (v1 * t - 0.5 * tc->maxaccel * t * t);
            } else {
                // S4 -> S6
                dist += t * vel;    // dist of (S4 + S6)
            }

            if (tc_target < dist) {
                tc->accel_state = ACCEL_S2;
                break;
            }
            break;
        
        
        case ACCEL_S2: 
            // to DECELERATE to ACCEL==0
            
            // AT = AT + JT
            // VT = VT + AT + 1/2JT
            // PT = PT + VT + 1/2AT + 1/6JT
            tc->cur_accel = tc->cur_accel - tc->jerk;
            tc->cur_vel = tc->cur_vel + tc->cur_accel - 0.5 * tc->jerk;
            tc->progress = tc->progress + tc->cur_vel + 0.5 * tc->cur_accel - 1.0/6.0 * tc->jerk;
           
            // check accel == 0
            if (tc->cur_accel <= 0) {
                tc->accel_state = ACCEL_S3;
                break;
            }

            // check if we will hit velocity limit at next BP
            req_vel = tc->reqvel * tc->feed_override * tc->cycle_time;
            if (req_vel > tc->maxvel) {
                req_vel = tc->maxvel;
            }
            // vel: velocity at next BP 
            vel = tc->cur_vel + tc->cur_accel - 1.5 * tc->jerk;
            if (vel > req_vel) {
                tc->cur_vel = vel;
                tc->accel_state = ACCEL_S3;
                break;
            } 
            
            // check if we will hit progress limit
            // refer to 2011-10-17 ysli design note
            // AT = AT + JT
            // VT = V0 + A0T + 1/2 JT^2
            // PT = P0 + V0T + 1/2A0T^2 + 1/6JT^3
            vel = tc->cur_vel;
            // distance for S3
            dist = tc->progress + (vel);
            
            /* 
            0.5 * vel = vel + 0 * t1 - 0.5 * j * t1 * t1;
            t1 = sqrt(vel/j)
            */
            t = ceil(sqrt(vel/tc->jerk));
            // AT = AT + JT
            t1 = ceil(tc->maxaccel / tc->jerk);   // max time for S4
            if (t > t1) {
                // S4 -> S5 -> S6
                dist += t1 * vel;    // dist of (S4 + S6)
                // calc decel.dist for ACCEL_S5
                // t: time for S5
                t = (vel - tc->jerk * t1 * t1) / tc->maxaccel;
                v1 = vel - 0.5 * tc->jerk * t1 * t1;
                // PT = P0 + V0T + 1/2A0T^2 + 1/6JT^3
                dist += (v1 * t - 0.5 * tc->maxaccel * t * t);
            } else {
                // S4 -> S6
                dist += t * vel;    // dist of (S4 + S6)
            }

            if (tc_target < dist) {
                tc->accel_state = ACCEL_S3;
                break;
            }

            break;
        
        case ACCEL_S3:
            // PT = PT + VT + 1/2AT + 1/6JT
            // , where (jerk == 0) and (accel == 0)
            tc->cur_accel = 0;
            tc->progress = tc->progress + tc->cur_vel;
            
            // check if we will hit progress limit
            // refer to 2011-10-17 ysli design note
            // AT = AT + JT
            // VT = V0 + A0T + 1/2 JT^2
            // PT = P0 + V0T + 1/2A0T^2 + 1/6JT^3
            /* 
            0.5 * vel = vel + 0 * t1 - 0.5 * j * t1 * t1;
            t1 = sqrt(vel/j)
            */
            vel = tc->cur_vel;
            // t = floor(sqrt(vel/tc->jerk) - 0.5);
            t = sqrt(vel/tc->jerk);
            // t = sqrt(vel/tc->jerk);
            // AT = AT + JT
            // t1 = floor(tc->maxaccel / tc->jerk - 0.5);   // max time for S4
            t1 = tc->maxaccel / tc->jerk;   // max time for S4
            // t1 = tc->maxaccel / tc->jerk;   // max time for S4
            if (t > t1) {
                // S4 -> S5 -> S6
                dist = tc->progress + t1 * vel;    // dist of (S4 + S6)
                // calc decel.dist for ACCEL_S5
                // t: time for S5
                // t = floor((vel - tc->maxaccel * t1) / tc->maxaccel - 0.5);
                t = (vel - tc->maxaccel * t1) / tc->maxaccel - 0.5;
                // t = (vel - tc->maxaccel * t1) / tc->maxaccel;
                v1 = vel - 0.5 * tc->jerk * t1 * t1;
                // PT = P0 + V0T + 1/2A0T^2 + 1/6JT^3
                dist += (v1 * t - 0.5 * tc->maxaccel * t * t);
            } else {
                // S4 -> S6
                dist = tc->progress + t * vel;    // dist of (S4 + S6)
            }

            // check if dist would be greater than tc_target at next cycle
            if (tc_target < (dist - vel)) {
                tc->accel_state = ACCEL_S4;
                // blending at largest velocity for G64 w/o P<tolerance>
                if (!tc->tolerance) {
                    tc->tolerance = tc->target - tc->progress; // tc->distance_to_go
                } 
                break;
            }

            // check for changes of feed_override and request-velocity
            req_vel = tc->reqvel * tc->feed_override * tc->cycle_time;
            if (req_vel > tc->maxvel) {
                req_vel = tc->maxvel;
            }
            if ((tc->cur_vel + 1.5 * tc->jerk) < req_vel) {
                tc->accel_state = ACCEL_S0;
                break;
            } else if ((tc->cur_vel - 1.5 * tc->jerk) > req_vel) {
                tc->accel_state = ACCEL_S4;
                break;
            }
            tc->cur_vel = req_vel;
            break;


        case ACCEL_S4:
            // AT = AT + JT
            // VT = VT + AT + 1/2JT
            // PT = PT + VT + 1/2AT + 1/6JT
            tc->cur_accel = tc->cur_accel - tc->jerk;
            tc->cur_vel = tc->cur_vel + tc->cur_accel - 0.5 * tc->jerk;
            if (tc->cur_vel <= 0) {
                tc->cur_vel = 0;
                tc->accel_state = ACCEL_S3;
                break;
            }
            tc->progress = tc->progress + tc->cur_vel + 0.5 * tc->cur_accel - 1.0/6.0 * tc->jerk;

            // (accel < 0) and (jerk < 0)
            assert (tc->cur_accel < 0);
           
            // check if we hit accel limit at next BP
            if ((tc->cur_accel - tc->jerk) <= -tc->maxaccel) {
                tc->cur_accel = -tc->maxaccel;
                tc->accel_state = ACCEL_S5;
                break;
            }
            
            // should we stay in S4 and keep decel?
            // calculate dist for S6 -> S4 -> (maybe S5) -> S6
            t = - tc->cur_accel / tc->jerk;
            // target dist after switching to S6 (jerk is positive for S6)
            dist = tc->progress + tc->cur_vel * t 
                   + 0.5 * tc->cur_accel * t * t
                   + 1.0 / 6.0 * tc->jerk * t * t * t;
            // VT = V0 + A0T + 1/2JT2
            // obtain vel for S6 -> S3
            vel = tc->cur_vel + tc->cur_accel * t + 0.5 * tc->jerk * t * t;
            
            if (vel > 0) {    
                /* 
                0.5 * vel = vel + 0 * t1 - 0.5 * j * t1 * t1;
                t1 = sqrt(vel/j)
                */
                t = ceil(sqrt(vel/tc->jerk));
                // AT = AT + JT
                t1 = ceil(tc->maxaccel / tc->jerk);   // max time for S4
                if (t > t1) {
                    // S4 -> S5 -> S6
                    dist += t1 * vel;    // dist of (S4 + S6)
                    // calc decel.dist for ACCEL_S5
                    // t: time for S5
                    t = (vel - tc->jerk * t1 * t1) / tc->maxaccel;
                    v1 = vel - 0.5 * tc->jerk * t1 * t1;
                    // PT = P0 + V0T + 1/2A0T^2 + 1/6JT^3
                    dist += (v1 * t - 0.5 * tc->maxaccel * t * t);
                } else {
                    // S4 -> S6
                    dist += t * vel;    // dist of (S4 + S6)
                }
            }

            // check if dist would be greater than tc_target at next cycle
            if (tc_target < (dist - (tc->cur_vel + 1.5 * tc->cur_accel - 2.1666667 * tc->jerk))) {
                tc->accel_state = ACCEL_S4;
                DPS("should stay in S4 and keep decel\n");
                break;
            }
                    
            // check if we will approaching requested velocity
            // vel should not be greater than "request velocity" after
            // starting acceleration to "accel == 0".
            //
            // AT = A0 + JT (let AT = 0 to calculate T)
            // VT = V0 + A0T + 1/2JT2
            t = - tc->cur_accel / tc->jerk;
            req_vel = tc->reqvel * tc->feed_override * tc->cycle_time;
            if (req_vel > tc->maxvel) {
                req_vel = tc->maxvel;
            }
            if ((tc->cur_vel + tc->cur_accel * t + 0.5 * tc->jerk * t * t) <= req_vel) {
                tc->accel_state = ACCEL_S6;
                DPS("S4: hit velocity rule; move to S6\n");
                break;
            }
            
            break;
        
        case ACCEL_S5:
            // jerk is 0 at this state
            // accel < 0
            // VT = VT + AT + 1/2JT
            // PT = PT + VT + 1/2AT + 1/6JT
            tc->cur_vel = tc->cur_vel + tc->cur_accel;
            tc->progress = tc->progress + tc->cur_vel + 0.5 * tc->cur_accel;
            
            // should we stay in S5 and keep decel?
            // calculate dist for S6 -> S4 -> (maybe S5) -> S6
            t = - tc->cur_accel / tc->jerk;
            // target dist after switching to S6 (jerk is positive for S6)
            dist = tc->progress + tc->cur_vel * t 
                   + 0.5 * tc->cur_accel * t * t
                   + 1.0 / 6.0 * tc->jerk * t * t * t;
            // VT = V0 + A0T + 1/2JT2
            // obtain vel for S6 -> S3
            vel = tc->cur_vel + tc->cur_accel * t + 0.5 * tc->jerk * t * t;
            
            if (vel > 0) { 
                /* S6 -> S3 -> S4 -> S5(maybe) -> S6 */
                /* 
                0.5 * vel = vel + 0 * t1 - 0.5 * j * t1 * t1;
                t1 = sqrt(vel/j)
                */
                t = ceil(sqrt(vel/tc->jerk));
                // AT = AT + JT
                t1 = ceil(tc->maxaccel / tc->jerk);   // max time for S4
                if (t > t1) {
                    // S4 -> S5 -> S6
                    dist += t1 * vel;    // dist of (S4 + S6)
                    // calc decel.dist for ACCEL_S5
                    // t: time for S5
                    t = (vel - tc->jerk * t1 * t1) / tc->maxaccel;
                    v1 = vel - 0.5 * tc->jerk * t1 * t1;
                    // PT = P0 + V0T + 1/2A0T^2 + 1/6JT^3
                    dist += (v1 * t - 0.5 * tc->maxaccel * t * t);
                } else {
                    // S4 -> S6
                    dist += t * vel;    // dist of (S4 + S6)
                }
            }
            
            // check if dist would be greater than tc_target at next cycle
            if (tc_target < (dist - (tc->cur_vel + 1.5 * tc->cur_accel))) {
                tc->accel_state = ACCEL_S5;
                DPS("should stay in S5 and keep decel\n");
                break;
            }

            // check if we will approaching requested velocity
            // vel should not be greater than "request velocity" after
            // starting acceleration to "accel == 0".
            //
            // AT = A0 + JT (let AT = 0 to calculate T)
            // VT = V0 + A0T + 1/2JT2
            // t: cycles for accel to decel to 0
            t = - tc->cur_accel / tc->jerk;
            req_vel = tc->reqvel * tc->feed_override * tc->cycle_time;
            if (req_vel > tc->maxvel) {
                req_vel = tc->maxvel;
            }
            if ((tc->cur_vel + tc->cur_accel * t + 0.5 * tc->jerk * t * t) <= req_vel) {
                tc->accel_state = ACCEL_S6;
                break;
            }

            break;
        
        case ACCEL_S6:
            // AT = AT + JT
            // VT = VT + AT + 1/2JT
            // PT = PT + VT + 1/2AT + 1/6JT
            tc->cur_accel = tc->cur_accel + tc->jerk;
            tc->cur_vel = tc->cur_vel + tc->cur_accel + 0.5 * tc->jerk;
            if (tc->cur_vel <= 0) {
                tc->cur_accel = 0;
                tc->cur_vel = 0.5 * tc->jerk;   // give some velocity for approaching target
            }
            dist = tc->cur_vel + 0.5 * tc->cur_accel + 1.0/6.0 * tc->jerk;
            tc->progress = tc->progress + dist;

            if (tc->cur_accel >= 0) {
                tc->accel_state = ACCEL_S3;
            }
            
            break;
        
        default:
            assert(0);
        } // switch (tc->accel_state)
    } while (immediate_state);
    
    if (tc->seamless_blend_mode != SMLBLND_ENABLE) {
        if (tc->progress >= tc->target) {
            // finished
            // DPS("hit target, cur_accel(%f), cur_vel(%f)\n", tc->cur_accel, tc->cur_vel);
            tc->progress = tc->target;
            tc->cur_accel = 0;
            tc->cur_vel = 0;
        }
    }

    DPS("%11u%6d%15.5f%15.5f%15.5f%15.5f%15.5f%15.5f%15.5f\n",
        _dt, tc->accel_state, tc->reqvel * tc->feed_override * tc->cycle_time, 
        tc->cur_accel, tc->cur_vel, tc->progress/tc->target, tc->target, 
        (tc->target - tc->progress), tc_target);
    tc->distance_to_go = tc->target - tc->progress;
    //TODO: this assert will be triggered with rockman.ini: 
    //      assert (tc->cur_vel >= 0);
}
Каких-то 6 различных случая для ускорения , и вообще все как-то очень длинно и сложно.

По идее, все, что нам надо - ввести еще один параметр для оси - a2 - максимальное изменение ускорения. Тогда функция перемещения будет
PT = P0 + V*T + 1/2A*T^2 + 1/6A2*T^3
Т.е. имеем уравнение 3-й степени от T, которое можно решить. Зачем все эти 6 разных случаев???
aftaev
Зачётный участник
Зачётный участник
Сообщения: 34042
Зарегистрирован: 04 апр 2010, 19:22
Репутация: 6191
Откуда: Казахстан.
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение aftaev »

Nick писал(а):В воздухе летает настойчивая мысль реализовать таки S-разгон в LinuxCNC.
:hehehe:
Дилетанту сложные вещи кажутся очень простыми, и только профессионал понимает насколько сложна самая простая вещь
Кто хочет - ищет возможности, кто не хочет - ищет оправдание.
Найди работу по душе и тебе не придется работать.
Аватара пользователя
tooshka
Почётный участник
Почётный участник
Сообщения: 1803
Зарегистрирован: 24 окт 2012, 14:26
Репутация: 209
Настоящее имя: Андрей
Откуда: Нижний Новгород
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение tooshka »

Nick писал(а): вообще все как-то очень длинно и сложно.
не только это, а еще голова разболелась от попыток понять)))
Милая, ты услышь меня
под окном стою со своим я ЧПУ! (Протяжно; с надрывом; форте)
Внимание!!! Чрезмерное увлечение ЧПУ приводит к проблемам в семейных отношениях!
Аватара пользователя
Starik
Опытный
Сообщения: 136
Зарегистрирован: 13 май 2012, 21:22
Репутация: 17
Откуда: Долгопрудный

Re: LinuxCNC S-разгон и торможение

Сообщение Starik »

look-ahead-s-shape.pdf
(926.28 КБ) 9252 скачивания
Вот статья примерно об том же, может помочь с пониманием:
Аватара пользователя
tooshka
Почётный участник
Почётный участник
Сообщения: 1803
Зарегистрирован: 24 окт 2012, 14:26
Репутация: 209
Настоящее имя: Андрей
Откуда: Нижний Новгород
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение tooshka »

aystarik писал(а):может помочь с пониманием:
:beer_blow: *3,14 скорее поможет
Милая, ты услышь меня
под окном стою со своим я ЧПУ! (Протяжно; с надрывом; форте)
Внимание!!! Чрезмерное увлечение ЧПУ приводит к проблемам в семейных отношениях!
Аватара пользователя
Nick
Мастер
Сообщения: 22776
Зарегистрирован: 23 ноя 2009, 16:45
Репутация: 1735
Заслуга: Developer
Откуда: Gatchina, Saint-Petersburg distr., Russia
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение Nick »

Да, статья хорошая, надо будет по подробнее ее изучить. Пока навскидку не совсем понятно зачем делить на 7 случаев, понятно, что у нас есть 7 различных "вариантов" движения, но все это все равно описывается одой единственной функцией...
Аватара пользователя
Starik
Опытный
Сообщения: 136
Зарегистрирован: 13 май 2012, 21:22
Репутация: 17
Откуда: Долгопрудный

Re: LinuxCNC S-разгон и торможение

Сообщение Starik »

А они машину семи состояний сделали... типа для разгона одно, для торможения -- другое, для круиза третье... только тут еще набор/сброс ускорения добавился...
Аватара пользователя
Сергей Саныч
Мастер
Сообщения: 9116
Зарегистрирован: 30 май 2012, 14:20
Репутация: 2857
Откуда: Тюмень
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение Сергей Саныч »

- А давай заведем новую переменную!
- Сам за ней ухаживать будешь?
:)
Если я правильно понял, там рассматривается куча возникающих ограничений - по максимальному ускорению, скорости, достижению требуемой позиции. Кроме того, учитывается, что время тут дискретно.
Чудес не бывает. Бывают фокусы.
Аватара пользователя
PKM
Почётный участник
Почётный участник
Сообщения: 4263
Зарегистрирован: 31 мар 2011, 18:11
Репутация: 705
Настоящее имя: Андрей
Откуда: Украина
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение PKM »

Nick писал(а):В воздухе летает настойчивая мысль реализовать таки S-разгон в LinuxCNC.
Вот это было бы шикарно!
Nick писал(а):Вроде как уже есть что-то подобное:
https://github.com/araisrobo/linuxcnc/b ... s/tp.c#808
Интересно, оно работает? Почему его не вносят в тестовые версии?
Аватара пользователя
Starik
Опытный
Сообщения: 136
Зарегистрирован: 13 май 2012, 21:22
Репутация: 17
Откуда: Долгопрудный

Re: LinuxCNC S-разгон и торможение

Сообщение Starik »

Интересно, оно работает? Почему его не вносят в тестовые версии?
Да вроде в ja3 внесли уже... на youtube плазма ездит с этой версией... Там хвосты остались вроде как, типа синхронизацию со шпинделем еще не дописали... А может уже и ее дописали -- вроде как "rigid tapping" работает тоже.
aftaev
Зачётный участник
Зачётный участник
Сообщения: 34042
Зарегистрирован: 04 апр 2010, 19:22
Репутация: 6191
Откуда: Казахстан.
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение aftaev »

aystarik писал(а): на youtube плазма ездит с этой версией...
сцылку :)
Дилетанту сложные вещи кажутся очень простыми, и только профессионал понимает насколько сложна самая простая вещь
Кто хочет - ищет возможности, кто не хочет - ищет оправдание.
Найди работу по душе и тебе не придется работать.
Аватара пользователя
PKM
Почётный участник
Почётный участник
Сообщения: 4263
Зарегистрирован: 31 мар 2011, 18:11
Репутация: 705
Настоящее имя: Андрей
Откуда: Украина
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение PKM »

aystarik писал(а):синхронизацию со шпинделем еще не дописали... А может уже и ее дописали -- вроде как "rigid tapping" работает тоже
Разве они для рабочих ходов используют S-кривые?
Аватара пользователя
Starik
Опытный
Сообщения: 136
Зарегистрирован: 13 май 2012, 21:22
Репутация: 17
Откуда: Долгопрудный

Re: LinuxCNC S-разгон и торможение

Сообщение Starik »

aftaev писал(а):сцылку
https://www.youtube.com/watch?v=BraEMAu5UkY
Аватара пользователя
Starik
Опытный
Сообщения: 136
Зарегистрирован: 13 май 2012, 21:22
Репутация: 17
Откуда: Долгопрудный

Re: LinuxCNC S-разгон и торможение

Сообщение Starik »

PKM писал(а):Разве они для рабочих ходов используют S-кривые?
А для чего же их еще использовать???? :)
aftaev
Зачётный участник
Зачётный участник
Сообщения: 34042
Зарегистрирован: 04 апр 2010, 19:22
Репутация: 6191
Откуда: Казахстан.
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение aftaev »

aystarik писал(а):Да вроде в ja3 внесли уже... на youtube плазма ездит с этой версией...
на вид ничего не обычного
Дилетанту сложные вещи кажутся очень простыми, и только профессионал понимает насколько сложна самая простая вещь
Кто хочет - ищет возможности, кто не хочет - ищет оправдание.
Найди работу по душе и тебе не придется работать.
Аватара пользователя
Starik
Опытный
Сообщения: 136
Зарегистрирован: 13 май 2012, 21:22
Репутация: 17
Откуда: Долгопрудный

Re: LinuxCNC S-разгон и торможение

Сообщение Starik »

aftaev писал(а):на вид ничего не обычного
в этом и щастье :)
aftaev
Зачётный участник
Зачётный участник
Сообщения: 34042
Зарегистрирован: 04 апр 2010, 19:22
Репутация: 6191
Откуда: Казахстан.
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение aftaev »

Сняли бы видео и так и так чтоб было видна разница :)
Дилетанту сложные вещи кажутся очень простыми, и только профессионал понимает насколько сложна самая простая вещь
Кто хочет - ищет возможности, кто не хочет - ищет оправдание.
Найди работу по душе и тебе не придется работать.
Аватара пользователя
Starik
Опытный
Сообщения: 136
Зарегистрирован: 13 май 2012, 21:22
Репутация: 17
Откуда: Долгопрудный

Re: LinuxCNC S-разгон и торможение

Сообщение Starik »

А разве не видно _удивительной_ плавности и легкости перемещений? Прямо ж как лебедь белая плывет... :hehehe:
Аватара пользователя
PKM
Почётный участник
Почётный участник
Сообщения: 4263
Зарегистрирован: 31 мар 2011, 18:11
Репутация: 705
Настоящее имя: Андрей
Откуда: Украина
Контактная информация:

Re: LinuxCNC S-разгон и торможение

Сообщение PKM »

aystarik писал(а):А для чего же их еще использовать????
Почти во всех контроллерах только для ускоренных. А для рабочих при невысоких скоростях не особо и нужны.
Ответить

Вернуться в «LinuxCNC»