[VicPiMakers Projects] Challenge 2: final results C++ program

Mark G. vpm at palaceofretention.ca
Sun Nov 15 14:11:29 EST 2020


Thanks Jim.

I rechecked my formulas and found an errant factor
of 2 in my calculation of the a value (not acceleration)
for the ax^2 + bx + c equation.

Re-running:

$ echo  33009 9002 11 | ../bin/cnc
Input:
RegP: 33009	 bits: 1000000011110001
RegM: 9002	 bits: 0010001100101010
RegS: 11	 bits: 00001011
Output #1: 241	 (position) 	 bits: 11110001
Output #2: 35	 (velocity) 	 bits: 00100011
Output #3: 2	 (accel.) 	 bits: 00000010
Output #4: 10	 (time) 	 bits: 00001010

Error status:
Position error.
Velocity ok.
Acceleration error.
Time error.

Error corrected:
Output #5: 240	 (position) 	 bits: 11110000
Output #6: 35	 (velocity) 	 bits: 00100011
Output #7: 10	 (accel.) 	 bits: 00001010
Output #8: 9	 (time) 	 bits: 00001001

Error status:
Position ok.
Velocity ok.
Acceleration ok.
Time ok.

Output #9:
  Travel time t: 6.93 (s)
  final velocity v: 69.28 (cm/sec)

Output #10:
  Testung t1 solution 1: 5.68 (s)
  Invalid t2 with t1 solution 1: -2.36
  trying t1 solution 2: 1.32 (s)
  Valid t2 with t1 solution 2: 6.36 (s)

  Solution t1: 1.32 (s)
  Solution t2: 6.36 (s)

Output #11:
Solutions involving a negative amount for t2 are not
physically possible without time travel.

===========

I wrote the program in C++, using a class named PointPlotter
and a main program, just to get practice using classes in
C++.

Mark



On 2020-11-15 12:25 a.m., James Briante wrote:
> Hi Mark,
> 
> Congratulations for 100% on Challenge 2 (Bonus helped!)
> 
> I’ve used your times for (t_1 , t_2 ) to compute total distance covered.
> 
> P = 2p_1  +  p_2
> 
>     = at_1 ^2 + vt_2 , using your values gives
> 
>     = 10(1.17)^2 + 35(6.66)
> 
>     = 246.789, past desired position (p =240)
> 
> Check your solution to the quadratic equation.
> 
> Jim
> 
> 
> 
> On Sat, Nov 14, 2020 at 9:29 PM Mark G. <vpm at palaceofretention.ca 
> <mailto:vpm at palaceofretention.ca>> wrote:
> 
>     Hi Jim,
> 
>     Thanks for the corrections.  Here are my updated results
>     with some trial solutions for outputs 9 and 10.
>     I differ in output 10.
> 
>     $ echo  33009 9002 11 | ../bin/cnc
>     Input:
>     RegP: 33009      bits: 1000000011110001
>     RegM: 9002       bits: 0010001100101010
>     RegS: 11         bits: 00001011
>     Output #1: 241   (position)      bits: 11110001
>     Output #2: 35    (velocity)      bits: 00100011
>     Output #3: 2     (accel.)        bits: 00000010
>     Output #4: 10    (time)          bits: 00001010
> 
>     Error status:
>     Position error.
>     Velocity ok.
>     Acceleration error.
>     Time error.
> 
>     Error corrected:
>     Output #5: 240   (position)      bits: 11110000
>     Output #6: 35    (velocity)      bits: 00100011
>     Output #7: 10    (accel.)        bits: 00001010
>     Output #8: 9     (time)          bits: 00001001
> 
>     Error status:
>     Position ok.
>     Velocity ok.
>     Acceleration ok.
>     Time ok.
> 
>     Output #9:
>        Travel time t: 6.93 (s)
>        final velocity v: 69.28 (cm/sec)
> 
>     Output #10:
>        Testung t1 solution 1: 12.83 (s)
>        Invalid t2 with t1 solution 1: -16.66
>        trying t1 solution 2: 1.17 (s)
>        Valid t2 with t1 solution 2: 6.66 (s)
> 
>        Solution t1: 1.17 (s)
>        Solution t2: 6.66 (s)
> 
>     Output #11:
>     Solutions involving a negative amount for t2 are not
>     physically possible without time travel.
> 
> 
> 
>     On 2020-11-12 8:00 p.m., James Briante wrote:
>      >
>      >
>      > Mark -a big thanks for pointing out the errors! v & t in the
>      > Callenge2.pdf are typing errors. I should have included the actual
>      > output screen (see attachment) with the other files. I've blacked
>     out
>      > the answer to Output #11.
>      >
>      > Things have been quiet on project talk re: challenge 2. Could these
>      > errors be the reason?
>      >
>      > I don't have a read on what I should do for output #10. Should I
>     provide
>      > the solution to the quadratic equation?
>      >
>      > Jim
>      >
>      >
>      > On Wed, Nov 11, 2020 at 5:09 PM Mark G. <vpm at palaceofretention.ca
>     <mailto:vpm at palaceofretention.ca>
>      > <mailto:vpm at palaceofretention.ca
>     <mailto:vpm at palaceofretention.ca>>> wrote:
>      >
>      >     Hi Jim,
>      >
>      >     I've completed up-to output #8 of the challenge and have
>      >     some discrepancies with your challenge specification.
>      >     Specifically, velocity/acceleration error switch, differing
>      >     values for uncorrected time (t) and velocity (v).
>      >
>      >     Your values:
>      >     Input Data: 33009,9002,11 (initial values - RegP, RegM, RegS)
>      >     Output #1: 241 (value of p, transferred from RegP)
>      >     Output #2: 186 (value of v, transferred from RegM)
>      >     Output #3: 10 (value of a, transferred from RegM)
>      >     Output #4: 220 (value of t, transferred RegM)
>      >   
>       --------------------------------------------------------------------------------
>      >
>      >     Output # 5 to #8 – values of p, v, a, and t with corrections
>      >   
>       --------------------------------------------------------------------------------
>      >
>      >     Output #5: 240 (p)
>      >     Output #6: 35 (v)
>      >     Output #7: 10 (a)
>      >     Output #8: 9 (t)
>      >
>      >     My values:
>      >
>      >     $ echo  33009 9002 11 | ../bin/cnc
>      >     Input:
>      >     RegP: 33009      bits: 1000000011110001
>      >     RegM: 9002       bits: 0010001100101010
>      >     RegS: 11         bits: 00001011
>      >     Output #1: 241   (position)      bits: 11110001
>      >     Output #2: 35    (velocity)      bits: 00100011
>      >     Output #3: 2     (accel.)        bits: 00000010
>      >     Output #4: 10    (time)          bits: 00001010
>      >     Position error.
>      >     Velocity ok.
>      >     Acceleration error.
>      >     Time error.
>      >     Error corrected:
>      >     Output #5: 240   (position)      bits: 11110000
>      >     Output #6: 35    (velocity)      bits: 00100011
>      >     Output #7: 10    (accel.)        bits: 00001010
>      >     Output #8: 9     (time)          bits: 00001001
>      >     Position ok.
>      >     Velocity ok.
>      >     Acceleration ok.
>      >     Time ok.
>      >
>      >     What do you think?
>      >
>      >     Mark
>      >
>      >     --
>      >     Projects mailing list
>      > Projects at vicpimakers.ca <mailto:Projects at vicpimakers.ca>
>     <mailto:Projects at vicpimakers.ca <mailto:Projects at vicpimakers.ca>>
>      > http://vicpimakers.ca/mailman/listinfo/projects_vicpimakers.ca
>      >
>      >
> 
>     -- 
>     Projects mailing list
>     Projects at vicpimakers.ca <mailto:Projects at vicpimakers.ca>
>     http://vicpimakers.ca/mailman/listinfo/projects_vicpimakers.ca
> 
> 
-------------- next part --------------
#pragma once

/* Declarations for point plotter class.  This mimics
 * a single axis (x) CNC machine.
 * Mark G. 2020-11-07
 */

#include <iostream>
#include <cstddef>
#include <cstdlib>
#include <vector>
#include <bitset>
#include <complex>
#include <cmath>

/*
 * Masks for bit patterns.
 */

const unsigned short int position_mask = 0x00ff;
const unsigned short int position_shift = 0x0;
const unsigned short int direction_mask = 0x8000;
const unsigned short int velocity_mask = 0xff00;
const unsigned short int velocity_shift = 0x8;
const unsigned short int acceleration_mask = 0x00f0;
const unsigned short int acceleration_shift = 0x4;
const unsigned short int time_mask = 0x000f;
const unsigned short int time_shift = 0x0;

const unsigned char POS_ERROR {8};
const unsigned char VEL_ERROR {4};
const unsigned char ACC_ERROR {2};
const unsigned char TIME_ERROR {1};

enum directions { reverse, forward };
enum motion_representations { integer, real_number };

using namespace std::complex_literals;

struct Quadratic_tuple 
{
    std::complex<float> solution1 { 0.0f + 0if};
    std::complex<float> solution2 { 0.0f + 0if};
};

struct timepair 
{
    float t1 {0.0f};
    float t2 {0.0f};
};

class PointPlotter {
  public:

    PointPlotter() = default;
    ~PointPlotter() = default;

    void decode_reg_p(unsigned short int p);
    void decode_reg_m(unsigned short int m);
    void decode_reg_s(unsigned char s);

    bool pos_error() { return ((reg_s & POS_ERROR) != 0); }
    bool vel_error() { return ((reg_s & VEL_ERROR) != 0); }
    bool acc_error() { return ((reg_s & ACC_ERROR) != 0); }
    bool time_error() { return ((reg_s & TIME_ERROR) != 0); }

    void correct_errors();
    void show_errors();
    void set_direction();

    void print_pva();

    unsigned char get_position() { return position; }
    unsigned char get_velocity() { return velocity; }
    unsigned char get_acceleration() { return acceleration; }
    unsigned char get_time() { return time; }

    timepair& solve_trapezoid(timepair& t);
    float solve_no_profile(float& velocity);

  private:
    uint16_t reg_p { 0 }; 
    uint16_t reg_m { 0 }; 
    unsigned char reg_s { 0 }; 

    directions direction { directions::forward };

    unsigned char position { 0 };
    unsigned char velocity { 0 };
    unsigned char acceleration { 0 };
    unsigned char time { 0 };

    float f_position {0.0};
    float f_velocity {0.0};
    float f_acceleration {0.0};
    float f_time {0.0};

};

-------------- next part --------------

/* Definitions for point plotter class.  This mimics
 * a single axis (x) CNC machine.
 * Mark G. 2020-11-07
 */

#include "point_plotter.hxx"

void PointPlotter::decode_reg_p(uint16_t p) {
    reg_p = p; 
    position = (reg_p & position_mask) >> position_shift;
    f_position = (float)position;
    set_direction();
}

void PointPlotter::decode_reg_m(uint16_t m) 
{
    reg_m = m; 

    velocity = (reg_m & velocity_mask) >> velocity_shift;
    f_velocity = (float)velocity;

    acceleration = (reg_m & acceleration_mask) >> acceleration_shift;
    f_acceleration = (float)acceleration;

    time = (reg_m & time_mask) >> time_shift;
    f_time = (float)time;
}

void PointPlotter::decode_reg_s(unsigned char s) {
    reg_s = s; 
}

void PointPlotter::show_errors() 
{
    std::cout << std::endl;
    std::cout << "Error status:" << std::endl;
    if (pos_error()) std::cout << "Position error." << std::endl;
    else std::cout << "Position ok." << std::endl;
    if (vel_error()) std::cout << "Velocity error." << std::endl;
    else std::cout << "Velocity ok." << std::endl;
    if (acc_error()) std::cout << "Acceleration error." << std::endl;
    else std::cout << "Acceleration ok." << std::endl;
    if (time_error()) std::cout << "Time error." << std::endl;
    else std::cout << "Time ok." << std::endl;
    std::cout << std::endl;
}

void PointPlotter::correct_errors() 
{
    if (pos_error()) {
        position = position & ~0x01;
        reg_s = reg_s & 0xF7;
        f_position = (float)position;
    }

    if (vel_error()) {
        velocity = ~velocity;
        reg_s = reg_s & 0xFB;
        f_velocity = (float)velocity;
    }

    if (acc_error()) {
        acceleration = acceleration | (1<<3);
        reg_s = reg_s & 0xFD;
        f_acceleration = (float)acceleration;
    }

    if (time_error()) {
        if ( (time & 0x01) ^ (time & 0x02) ) {
            //std::cout << "Time: bits 1 and 0 differ (xor)" << std::endl;
            if (time & 0x01) {
                //std::cout << "Time: bit 0 set " << std::bitset<8>(time) << std::endl;
                time = (time | 0x02) & 0xfe;
                //std::cout << "Time: bit 1 and 0 swapped " << std::bitset<8>(time) << std::endl;
            } else {
                //std::cout << "Time: bit 1 set " << std::bitset<8>(time) << std::endl;
                time = (time | 0x01) & 0xfd;
                //std::cout << "Time: bit 1 and 0 swapped " << std::bitset<8>(time) << std::endl;
            }
        }
        reg_s = reg_s & 0xFE;
        f_time = (float)time;
    }
}

void PointPlotter::set_direction() {
    if (reg_p & direction_mask) {
        direction = directions::forward;
    } else {
        direction = directions::reverse;
    }
}

void PointPlotter::print_pva() {
    std::cout << "Position: " << (int)position << "\t" << std::bitset<8>(position) << std::endl;
    std::cout << "Velocity: " << (int)velocity << "\t" << std::bitset<8>(velocity) << std::endl;
    std::cout << "Acceleration: " << (int)acceleration << "\t" << std::bitset<8>(acceleration) << std::endl;
    std::cout << "Time: " << (int)time << "\t" << std::bitset<8>(time) << std::endl;
    std::cout << std::endl;
}

timepair& PointPlotter::solve_trapezoid(timepair& t) 
{
    Quadratic_tuple t1;

    t.t1 = NAN;
    t.t2 = NAN;

    float a = f_acceleration;
    float b = (-2.0f)*f_velocity;
    float c = (f_velocity * f_time) - f_position;

    float discriminant = b*b - 4*a*c;
    float part1 = (-1.0f * b) / (2.0f * a);

    if (discriminant < 0.0f) {
        t1.solution1 = part1 + 1if * std::sqrt(-discriminant) / (2.0f * a);
        t1.solution2 = part1 - 1if * std::sqrt(-discriminant) / (2.0f * a);
    } else {
        t1.solution1 = part1 + std::sqrt(discriminant) / (2.0f * a);
        t1.solution2 = part1 - std::sqrt(discriminant) / (2.0f * a);
    }

    //std::cout << "Part 1 of t1 solution (-b/2a): " << part1 << std::endl;
    //std::cout << "Discriminant of t1 solutions (b^2-4ac): " << discriminant << std::endl;
    if (std::imag(t1.solution1) > 0.0f) {
        std::cout << "no solution" << std::endl;
        std::cout << " quadratic solutions for t1 are complex numbers: " << std::endl;
        std::cout << " " << t1.solution1 << std::endl;
        std::cout << " " << t1.solution2 << std::endl;
    } else {
        std::cout << " Testung t1 solution 1: " << std::real(t1.solution1) << " (s)" << std::endl;
        float t2 = f_time - 2.0f * std::real(t1.solution1);

        if (t2 < 0.0f) {
            std::cout << " Invalid t2 with t1 solution 1: " << t2 << std::endl;
            std::cout << " trying t1 solution 2: " << std::real(t1.solution2) << " (s)" << std::endl;

            t2 = f_time - 2.0f * std::real(t1.solution2);
            if (t2 < 0.0f) {
                std::cout << " Invalid t2 with t1 solution 2: " << t2 << " (s)" << std::endl;
            } else {
                std::cout << " Valid t2 with t1 solution 2: " << t2 << " (s)" << std::endl;
                t.t1 = std::real(t1.solution2);
                t.t2 = t2;
            }
        } else {
            std::cout << " Valid t2 with t1 solution 1: " << t2 << " (s)" << std::endl;
            t.t1 = std::real(t1.solution1);
            t.t2 = t2;
        }

    }
    std::cout << std::endl;

    return t; 
}


float PointPlotter::solve_no_profile(float& vel) 
{
    float travel_time = 0.0f;

    travel_time = std::sqrt(2.0f * f_position / f_acceleration);
    vel = f_acceleration * travel_time;

    return travel_time;
}
-------------- next part --------------
/*
 * Program to complete the second programming challenge given
 * by Jim B.
 * Writtem by Mark G. 2020-11-07
 */

#include <iostream>
#include <algorithm>
#include <numeric>
#include <vector>
#include <string>
#include <map>
#include <cctype>
#include <iomanip>

#include "point_plotter.hxx"

void print_output_and_number(int number) {
    std::cout << "Output #" << number << ": ";
}

int main() 
{

    using namespace std::complex_literals;

    uint16_t reg_p { 0 };
    uint16_t reg_m { 0 };
    uint16_t reg_s { 0 };

    timepair times;

    std::cin >> reg_p;
    std::cin >> reg_m;
    std::cin >> reg_s;

    std::cout << "Input: " << std::endl;
    std::cout << "RegP: " << (int)reg_p << "\t bits: " << std::bitset<16>(reg_p) << std::endl;
    std::cout << "RegM: " << (int)reg_m << "\t bits: " << std::bitset<16>(reg_m) << std::endl;
    std::cout << "RegS: " << (int)reg_s << "\t bits: " << std::bitset<8>(reg_s) << std::endl;

    PointPlotter xaxis;

    xaxis.decode_reg_p(reg_p);
    xaxis.decode_reg_m(reg_m);
    xaxis.decode_reg_s(reg_s);

    int output_number {1};
    print_output_and_number(output_number++);
    std::cout << (int)xaxis.get_position() << "\t (position) " << "\t bits: " << std::bitset<8>(xaxis.get_position()) << std::endl;
    print_output_and_number(output_number++);
    std::cout << (int)xaxis.get_velocity() << "\t (velocity) " << "\t bits: " << std::bitset<8>(xaxis.get_velocity()) << std::endl;
    print_output_and_number(output_number++);
    std::cout << (int)xaxis.get_acceleration() << "\t (accel.) " << "\t bits: " << std::bitset<8>(xaxis.get_acceleration()) << std::endl;
    print_output_and_number(output_number++);
    std::cout << (int)xaxis.get_time() << "\t (time) " << "\t bits: " << std::bitset<8>(xaxis.get_time()) << std::endl;

    
    xaxis.show_errors();
    xaxis.correct_errors();

    std::cout << "Error corrected: " << std::endl;
    print_output_and_number(output_number++);
    std::cout << (int)xaxis.get_position() << "\t (position) " << "\t bits: " << std::bitset<8>(xaxis.get_position()) << std::endl;
    print_output_and_number(output_number++);
    std::cout << (int)xaxis.get_velocity() << "\t (velocity) " << "\t bits: " << std::bitset<8>(xaxis.get_velocity()) << std::endl;
    print_output_and_number(output_number++);
    std::cout << (int)xaxis.get_acceleration() << "\t (accel.) " << "\t bits: " << std::bitset<8>(xaxis.get_acceleration()) << std::endl;
    print_output_and_number(output_number++);
    std::cout << (int)xaxis.get_time() << "\t (time) " << "\t bits: " << std::bitset<8>(xaxis.get_time()) << std::endl;

    xaxis.show_errors();
    //xaxis.print_pva();

    std::cout << std::fixed << std::setprecision(2);

    print_output_and_number(output_number++);
    std::cout << std::endl;
    float final_velocity {0.0f};
    float travel_time = xaxis.solve_no_profile(final_velocity);
    std::cout << " Travel time t: " << travel_time << " (s)" << std::endl;
    std::cout << " final velocity v: " << final_velocity << " (cm/sec)" << std::endl;
    std::cout << std::endl;

    print_output_and_number(output_number++);
    std::cout << std::endl;
    times = xaxis.solve_trapezoid(times);
    
    std::cout << " Solution t1: " << times.t1 << " (s)" << std::endl;
    std::cout << " Solution t2: " << times.t2 << " (s)" << std::endl;

    std::cout << std::endl;
    print_output_and_number(output_number++);
    std::cout << std::endl;
    std::cout << "Solutions involving a negative amount for t2 are not " << std::endl << "physically possible without time travel." << std::endl;

    return 0;
}


More information about the Projects mailing list