Lynxmotion SES V2 Hexapod Robot

Well, aside from the fact the servo is always in “holding” state and trying to reach the position assigned to it… I think that’s about it.

By default, IPE=0 so you have to keep feeding the same position to the servo until it does reach it. If you switch to IPE=1 sending the target position once is enough to make it do the work itself (i.e.: saturating the filter) and you will reach the position.

IPE=0 is useful is you want to control the rate of commands; maybe you want to updated the filter / target position at a slower rate, lets say every 50 ms or something.

IPE=1 is probably more useful in your case.

Yes I did where do you think I got the fpc, and angluar/holding stiffness’s from. Think it was you or was it cmackenzie you talked about sending it 3 times. But that all got me confused.

Also, this thread is really really long, and got longer once I joined.

2 Likes

Like the explanation.

Maybe this public post can help.

edit: and this one, of course.

It fact the IPE=1 by default.

@cyberpalin
What are you trying to smooth out (which part of the movement) ?
As i said a couple of time that my example had math issues where the two final positions sent are not calculated right. There is a big step in between and the longer the movement, the worst it is.

Maybe that’s not your problem but just wanted to clear this out first. (HERE)

1 Like

:sweat_smile: :sweat_smile: :sweat_smile:
Confirmed, it should be on by default… haha…

@cyberpalin
You should probably send a QIPE and see what value yours is set at. If it is set to 1 then a D command sent in EM=0 with FPC=2+ (optimally 3+) when the QDT should update every ~20 ms towards your desired location (from the D command) until it arrives there.

Thanks - don’t think that the my problem- used what you posted as a guide and I think I fixed it so last position ends up where its suppose to go - did confirm that with the LA.

Here’s my current sketch - only uses one servo.

// LSS Setup & Variables
#include <Wire.h>
#include "SparkFun_Qwiic_Keypad_Arduino_Library.h" //Click here to get the library: http://librarymanager/All#SparkFun_keypad
KEYPAD keypad1; //Create instance of this object


#include <LSS.h>
#define LSS_BAUD  (921600)

LSS LSS_1 = LSS(0); 

int Timing = 250;                        // Time in ms for the motion (T Parameter) 
int delais_frame = 1000;                  // Time between each Frame
int em0_rate = 25;                        // Rate at wich the positions are sent (20ms)

void setup() {

  Serial.begin(115200);
  
  if (keypad1.begin() == false)   // Note, using begin() like this will use default I2C address, 0x4B. 
                  // You can pass begin() a different address like so: keypad1.begin(Wire, 0x4A).
  {
    Serial.println("Keypad does not appear to be connected. Please check wiring. Freezing...");
    while (1);
  }
  Serial.print("Initialized. Firmware Version: ");
  Serial.println(keypad1.getVersion());
  
// Initialize the LSS bus
  LSS::initBus(Serial1, LSS_BAUD);
  Serial.println("Initial Reset: ");
  LSS_1.reset();
  delay(2000);
  LSS_1.setServoID(6);
  // LSS Settings
  Serial.println("Set AngularStiffness to -4: ");
  LSS_1.setAngularStiffness(-4);
  Serial.println("");
  delay(250);
  Serial.print("Set Holding Stiffness to 4: ");
  LSS_1.setAngularHoldingStiffness(4);
  Serial.println("");
  delay(250);
  Serial.println("Set Motion Control: ");
  LSS_1.setMotionControlEnabled(0);
  delay(250);
  LSS_1.setMaxSpeed(1800, LSS_SetSession);

  
  Serial.println("Do not Set FPC: ");
  //Serial1.println("#6FPC5\r");
  delay(250);
  #ifdef LSS_SupportsSettingTimeouts
  LSS::setReadTimeouts(20, 5); // define we will wait for 20ms for response to start and 5ms for in message characters
  #endif
  
}

void sequence(){
  // Frame 1:
  Serial.printf("\nFRAME 1\n--------------\n");
  Spoofing(-450,Timing);
  delay(delais_frame*3);
  Serial.printf("\nFRAME 2\n--------------\n");
  // Frame 2:
  Spoofing(450,Timing);
  delay(delais_frame);
  }

void Spoofing(int32_t LSS_S_1,int32_t p2_timing){
  int pos_num = p2_timing/em0_rate;
  int32_t temp[pos_num];
  uint32_t stime;
  
  int32_t   LSS_1_qd = query_LSS_1();
  int32_t   LSS_1_delta = LSS_S_1 - LSS_1_qd;
  int32_t     LSS_1_min_pos = LSS_1_delta/pos_num;
  Serial.printf("goal: %d, time: %d, pos_num: %d\n", LSS_S_1, p2_timing, pos_num);
  Serial.printf("Current pos: (qd: %d), dPos(%d), tStep(%d)\n", LSS_1_qd, LSS_1_delta, LSS_1_min_pos); 

  temp[0] = LSS_1.getPosition();
  stime = millis();
  for (int32_t i = 1; i < pos_num+1; i++){
    Serial.printf("i: %d, move: %d\n", i, (LSS_1_min_pos * i) + LSS_1_qd);
    LSS_1.move((LSS_1_min_pos * i) + LSS_1_qd);
    delay(em0_rate);
    checkStatus();
    temp[i] = query_LSS_1();
  } 
    LSS_1.move(LSS_S_1);
    delay(2);
    Serial.printf("Final Move: %d\n", LSS_S_1);
    uint32_t dt = millis() - stime;
    
    Serial.println("Time(ms)/ Pos(deg)");
    Serial.printf("%d / ", dt);
    for(int i = 0; i < pos_num; i++) {
      Serial.printf("%d, ", temp[i]);
    }
    Serial.print(LSS_1.getPosition()); 
    Serial.println();
    
}

int32_t query_LSS_1()
{
  int32_t posLSS = 0;
  int32_t lastPosLSS = -1;
  char readBuffer[100];
  lastPosLSS = posLSS;
  Serial1.write("#6QD\r");
  while(Serial1.available() == 0)
  {
  }
  size_t readLength = 0;
  readLength = Serial1.readBytesUntil('D', readBuffer, 100);  // Read until after the command (QD), indicating the start of the returned value (position in 1/10 deg)
  readLength = Serial1.readBytesUntil('\r', readBuffer, 100); // Read until the carriage return (\r), indicating the end of the reply
  readBuffer[readLength]=0;
  if(readLength > 0)
  {
    if(LSS_1.charToInt(readBuffer, &posLSS))
    {
      Serial.printf("Returned Postition: %d\n", posLSS);
      return posLSS;
    }
  } 
}

void loop() {
  keypad1.updateFIFO();  // necessary for keypad to pull button from stack to readable register
  char button = keypad1.getButton();
  
      // only toggle the LED if the new button state is HIGH
       if (button == '#') {
        //Start the sequence
        Serial.println("Sequence Start");
        sequence(); 
      }                  
}

void checkStatus()
{
  int8_t status1 = -1;
  uint32_t statusTime = 0;
  while (status1 != 6) {
    if (status1 != 6) status1 = LSS_1.getStatus();
    //delay(2);
    statusTime += 1;
  }
  Serial.printf("Status Loop CNT: %d: %d\n", statusTime, status1);
}

@dialfonzo - @scharette

Thanks for the info has help - have to play now and see what happens. One of things was to kind of sort of doing a work around for a timed move since that doesn’t seem to be operational yet.

My delay in responding was because I was copy an pasting all this info into a word document for further reading :slight_smile:

As more of a mechanical guy, I’m building some intermediate support structures or else it might become too long and fall down :rofl:

@dialfonzo @scharette @cyberpalin @cbenson

Thanks everyone lots to reread…

Some reason, some of this feels a bit screwy to me… That is, I don’t know of other servos, where I have to tell them N times to go to same position to get there. Just feels wrong, especially for defaults…

It should not be hard for people for people to get the results they expect…

Sorry if this sounds simplistic:
But when the impression is that you choose to use the SSC-32 like command set, you expect that you should be able to port your program using an SSC-32 with RC servos to the LSS servos, and in theory you should be able to do so by just switching the Serial port… And maybe switch from PWM position to D positions…

That is what I want to do is something like, sort of our cycle stance code, similar to my ‘k’ command.
For example suppose I have code like this for SSC-32

#define SSCSerial Serial1
void legsMoving() {
  while(!Serial.available()) {
    SSCSerial.println("#2P0#4P -900#6P -600T1000\r");
    delay(1000);
    SSCSerial.println("#2P100#4P -450#6P -300T1000\r");
    delay(1000);
    SSCSerial.println("#2P200#4P  0#6P  0T1000\r");
    delay(1000);
    SSCSerial.println("#2P0#4P  450#6P 450T1000\r");
    delay(1000);
    SSCSerial.println("#2P -100#4P  0#6P  0T1000\r");
    delay(1000);
    SSCSerial.println("#2P -200#4P -450#6P -300T1000\r");
    delay(1000);
    SSCSerial.println("#2P0#4P -900#6P -600T1000\r");
    delay(1000);      
  }
}

Yes these strings are not valid for SSC-32. need to change P to as I need to convert the degrees here to their PWM values… Also some of these values may need to be negated depending on leg…

In fact maybe later today or tomorrow I will hook up one of my old Hexapods like Phoenix with SSC-32 to processor and run this. But what I expect I will see is that the three servos will all move smoothly to their positions and there should be no pausing at all between each of the 7 moves in the cycle…

What I would like to see is how do I convert this to LSS and get the same results? What I may try once I have an SSC-32 working with this, is I would like to output to both legs at the same time with the same logical command string, and be able to observe the two legs to see if they are following the exact same motion…

Is this possible?

Not optimized code, but this would ask all servos to do a timed moved of 1sec

  Serial.print("#2D300T1000\r");
  Serial.print("#4D-900T1000\r");
  Serial.print("#6D1200T1000\r");
  delay(1000);

I misremembered, which @dialfonzo corrected afterwards. IPE=1 by default and you do not need to repeat positions.

It is not.

Just a side note here; if in EM=0 I think the T modifier (well, its impact) will be ignored by the servo.

Yes - But I refer to his example which use T so EM1

1 Like

Sorry simple question, why are all the code bases going to EM=0?

But for first step
OK, I added the ‘S’ command to my test sketch which does like the i command where it moves through 7 moves… I defined them in a more confined space as I will also maybe tomorrow convert them to RC and output to SSC-32…
I pushed the code up…

int16_t rf_stance_smooth [RF_STANCE_COUNT][3] =
{
  {0, -600, -600},       //Low
  // 0, -900, 510 degrees
  {100, -300, -300},      //mid Low
  {200,  0,  0},          //Med
  {0,  300, 300},         //High
  { -100,  0,  0},        //Med
  { -200, -300, -300},    //mid Low
  {0, -600, -600}       //Low
};

int LSSGetServoPosition(uint8_t servo_id) {
  myLSS.setServoID(servo_id);
  return myLSS.getPosition();
}

void cycleSmoothTimed() {
  Serial.println("Cycle Smooth - speed changes each loop");
  for (uint8_t leg = 0; leg < COUNT_LEGS; leg++) {
    if (legs[leg].leg_found) {
      myLSS.setServoID(legs[leg].coxa.id);
      myLSS.moveT(rf_stance_smooth[0][0], 500);
      myLSS.setServoID(legs[leg].femur.id);
      myLSS.moveT(rf_stance_smooth[0][1], 500);
      myLSS.setServoID(legs[leg].tibia.id);
      myLSS.moveT(rf_stance_smooth[0][2], 500);
    }
  }
  delay(1000); // extra long time...

  int move_time = 500; // start off time
  int move_time_change = 250; // how much to change per loop
  static const int MOVE_TIME_MAX = 1000;
  static const int MOVE_TIME_MIN = 250;

  Serial.println("Press any key to exit");
  while (Serial.read() != -1);  // clear it out
  while (!Serial.available()) {
    Serial.printf("Cycle Move Times %d\n", move_time);
    for (uint8_t position = 0; (position < RF_STANCE_COUNT) && !Serial.available(); position++) {
      elapsedMillis em = 0;
      for (uint8_t leg = 0; leg < COUNT_LEGS; leg++) {
        if (legs[leg].leg_found) {
          myLSS.setServoID(legs[leg].coxa.id);
          myLSS.moveT(rf_stance_smooth[position][0], move_time);
          myLSS.setServoID(legs[leg].femur.id);
          myLSS.moveT(rf_stance_smooth[position][1], move_time);
          myLSS.setServoID(legs[leg].tibia.id);
          myLSS.moveT(rf_stance_smooth[position][2], move_time);
        }
      }
      for (uint8_t leg = 0; leg < COUNT_LEGS; leg++) {
        if (legs[leg].leg_found) {
          Serial.printf("\t%u C:%d->%d F:%d->%d T:%d->%d", leg,
                        LSSGetServoPosition(legs[leg].coxa.id), rf_stance_smooth[position][0],
                        LSSGetServoPosition(legs[leg].femur.id), rf_stance_smooth[position][1],
                        LSSGetServoPosition(legs[leg].tibia.id), rf_stance_smooth[position][2] );
        }
      }
      Serial.println();
      // normalize move time...
      delay(move_time - em);
    }
    // Ok we finished one cycle, lets update the timing for next
    if ((move_time == MOVE_TIME_MAX) || (move_time == MOVE_TIME_MIN)) move_time_change = -move_time_change;
    move_time += move_time_change;
  }
}

So it loops through each leg tells them to go to some new position in time T in range 250-1000 and then asks all of the servos for their current position. You would expect that the positions should be very near the previous targets… At times close other times off…

Cycle Smooth - speed changes each loop
Press any key to exit
Cycle Move Times 500
	0 C:-4->0 F:-594->-600 T:-613->-600	1 C:0->0 F:-594->-600 T:-595->-600	2 C:-4->0 F:-593->-600 T:-595->-600	3 C:-3->0 F:-594->-600 T:-614->-600	4 C:-2->0 F:-594->-600 T:-608->-600	5 C:-3->0 F:-595->-600 T:-596->-600
	0 C:-4->100 F:-594->-300 T:-609->-300	1 C:0->100 F:-594->-300 T:-595->-300	2 C:-4->100 F:-593->-300 T:-595->-300	3 C:-3->100 F:-593->-300 T:-609->-300	4 C:-2->100 F:-594->-300 T:-608->-300	5 C:-3->100 F:-595->-300 T:-596->-300
	0 C:90->200 F:-422->0 T:-383->0	1 C:87->200 F:-424->0 T:-425->0	2 C:91->200 F:-430->0 T:-420->0	3 C:85->200 F:-414->0 T:-370->0	4 C:88->200 F:-412->0 T:-374->0	5 C:85->200 F:-410->0 T:-407->0
	0 C:193->0 F:-5->300 T:-25->300	1 C:194->0 F:-2->300 T:-13->300	2 C:193->0 F:-2->300 T:-7->300	3 C:186->0 F:0->300 T:-25->300	4 C:195->0 F:1->300 T:-26->300	5 C:187->0 F:0->300 T:-9->300
	0 C:69->-100 F:287->0 T:296->0	1 C:44->-100 F:285->0 T:310->0	2 C:67->-100 F:273->0 T:310->0	3 C:63->-100 F:283->0 T:296->0	4 C:62->-100 F:280->0 T:295->0	5 C:61->-100 F:300->0 T:313->0
	0 C:-97->-200 F:136->-300 T:103->-300	1 C:-96->-200 F:136->-300 T:183->-300	2 C:-97->-200 F:119->-300 T:174->-300	3 C:-96->-200 F:116->-300 T:99->-300	4 C:-96->-200 F:124->-300 T:104->-300	5 C:-95->-200 F:196->-300 T:144->-300
	0 C:-190->0 F:-251->-600 T:-279->-600	1 C:-192->0 F:-252->-600 T:-272->-600	2 C:-191->0 F:-253->-600 T:-276->-600	3 C:-188->0 F:-262->-600 T:-287->-600	4 C:-189->0 F:-261->-600 T:-283->-600	5 C:-188->0 F:-282->-600 T:-273->-600
Cycle Move Times 750
	0 C:-46->0 F:-593->-600 T:-596->-600	1 C:-38->0 F:-594->-600 T:-620->-600	2 C:-45->0 F:-593->-600 T:-619->-600	3 C:-46->0 F:-594->-600 T:-614->-600	4 C:-36->0 F:-594->-600 T:-616->-600	5 C:-44->0 F:-619->-600 T:-596->-600
	0 C:-9->100 F:-593->-300 T:-596->-300	1 C:-7->100 F:-594->-300 T:-635->-300	2 C:-9->100 F:-593->-300 T:-631->-300	3 C:-8->100 F:-593->-300 T:-623->-300	4 C:-8->100 F:-594->-300 T:-628->-300	5 C:-8->100 F:-629->-300 T:-596->-300
	0 C:88->200 F:-360->0 T:-361->0	1 C:88->200 F:-359->0 T:-325->0	2 C:89->200 F:-359->0 T:-326->0	3 C:88->200 F:-352->0 T:-329->0	4 C:95->200 F:-352->0 T:-323->0	5 C:89->200 F:-313->0 T:-357->0
	0 C:184->0 F:1->300 T:-2->300	1 C:182->0 F:1->300 T:-2->300	2 C:184->0 F:0->300 T:-1->300	3 C:189->0 F:-1->300 T:0->300	4 C:216->0 F:1->300 T:-4->300	5 C:190->0 F:1->300 T:0->300
	0 C:43->-100 F:269->0 T:274->0	1 C:34->-100 F:259->0 T:283->0	2 C:41->-100 F:266->0 T:290->0	3 C:50->-100 F:268->0 T:278->0	4 C:24->-100 F:273->0 T:279->0	5 C:50->-100 F:281->0 T:279->0
	0 C:-95->-200 F:84->-300 T:72->-300	1 C:-100->-200 F:89->-300 T:74->-300	2 C:-95->-200 F:80->-300 T:66->-300	3 C:-94->-200 F:71->-300 T:66->-300	4 C:-96->-200 F:79->-300 T:60->-300	5 C:-94->-200 F:75->-300 T:82->-300
	0 C:-191->0 F:-276->-600 T:-281->-600	1 C:-184->0 F:-275->-600 T:-277->-600	2 C:-191->0 F:-281->-600 T:-290->-600	3 C:-190->0 F:-285->-600 T:-289->-600	4 C:-189->0 F:-284->-600 T:-291->-600	5 C:-191->0 F:-288->-600 T:-282->-600
Cycle Move Times 1000
	0 C:-35->0 F:-597->-600 T:-596->-600	1 C:-34->0 F:-596->-600 T:-597->-600	2 C:-34->0 F:-595->-600 T:-595->-600	3 C:-33->0 F:-597->-600 T:-598->-600	4 C:-26->0 F:-596->-600 T:-597->-600	5 C:-31->0 F:-597->-600 T:-597->-600
	0 C:-9->100 F:-597->-300 T:-596->-300	1 C:-9->100 F:-596->-300 T:-597->-300	2 C:-8->100 F:-595->-300 T:-596->-300	3 C:-8->100 F:-596->-300 T:-598->-300	4 C:-9->100 F:-596->-300 T:-597->-300	5 C:-8->100 F:-597->-300 T:-597->-300
	0 C:83->200 F:-339->0 T:-348->0	1 C:97->200 F:-348->0 T:-349->0	2 C:83->200 F:-343->0 T:-351->0	3 C:84->200 F:-336->0 T:-346->0	4 C:87->200 F:-338->0 T:-344->0	5 C:84->200 F:-335->0 T:-344->0
	0 C:186->0 F:-2->300 T:-5->300	1 C:216->0 F:-3->300 T:-3->300	2 C:186->0 F:-2->300 T:-2->300	3 C:184->0 F:-2->300 T:-4->300	4 C:191->0 F:-2->300 T:-3->300	5 C:185->0 F:-2->300 T:-4->300
	0 C:35->-100 F:280->0 T:278->0	1 C:13->-100 F:280->0 T:283->0	2 C:35->-100 F:287->0 T:273->0	3 C:44->-100 F:281->0 T:298->0	4 C:49->-100 F:281->0 T:289->0	5 C:43->-100 F:281->0 T:279->0
	0 C:-90->-200 F:62->-300 T:43->-300	1 C:-96->-200 F:62->-300 T:57->-300	2 C:-91->-200 F:58->-300 T:57->-300	3 C:-93->-200 F:60->-300 T:72->-300	4 C:-92->-200 F:63->-300 T:43->-300	5 C:-94->-200 F:54->-300 T:42->-300
	0 C:-193->0 F:-288->-600 T:-289->-600	1 C:-197->0 F:-288->-600 T:-282->-600	2 C:-193->0 F:-293->-600 T:-285->-600	3 C:-187->0 F:-294->-600 T:-296->-600	4 C:-190->0 F:-291->-600 T:-291->-600	5 C:-187->0 F:-288->-600 T:-292->-600
Cycle Move Times 750
	0 C:-51->0 F:-594->-600 T:-594->-600	1 C:-49->0 F:-596->-600 T:-595->-600	2 C:-51->0 F:-595->-600 T:-595->-600	3 C:-23->0 F:-593->-600 T:-577->-600	4 C:-20->0 F:-593->-600 T:-595->-600	5 C:-22->0 F:-594->-600 T:-596->-600
	0 C:-9->100 F:-594->-300 T:-594->-300	1 C:-8->100 F:-596->-300 T:-595->-300	2 C:-9->100 F:-594->-300 T:-595->-300	3 C:-8->100 F:-593->-300 T:-595->-300	4 C:-8->100 F:-594->-300 T:-595->-300	5 C:-8->100 F:-595->-300 T:-596->-300
	0 C:86->200 F:-356->0 T:-366->0	1 C:89->200 F:-357->0 T:-363->0	2 C:87->200 F:-356->0 T:-362->0	3 C:89->200 F:-352->0 T:-374->0	4 C:100->200 F:-351->0 T:-359->0	5 C:90->200 F:-348->0 T:-359->0
	0 C:187->0 F:1->300 T:-2->300	1 C:193->0 F:-1->300 T:-3->300	2 C:188->0 F:0->300 T:1->300	3 C:183->0 F:-1->300 T:-1->300	4 C:210->0 F:1->300 T:-1->300	5 C:183->0 F:1->300 T:-2->300
	0 C:48->-100 F:275->0 T:262->0	1 C:41->-100 F:275->0 T:283->0	2 C:48->-100 F:266->0 T:282->0	3 C:43->-100 F:270->0 T:257->0	4 C:28->-100 F:268->0 T:278->0	5 C:42->-100 F:275->0 T:280->0
	0 C:-95->-200 F:93->-300 T:64->-300	1 C:-98->-200 F:87->-300 T:74->-300	2 C:-95->-200 F:80->-300 T:81->-300	3 C:-94->-200 F:73->-300 T:74->-300	4 C:-92->-200 F:80->-300 T:82->-300	5 C:-94->-200 F:72->-300 T:60->-300
	0 C:-195->0 F:-279->-600 T:-282->-600	1 C:-184->0 F:-279->-600 T:-284->-600	2 C:-195->0 F:-281->-600 T:-283->-600	3 C:-182->0 F:-283->-600 T:-281->-600	4 C:-193->0 F:-282->-600 T:-286->-600	5 C:-182->0 F:-291->-600 T:-291->-600
Cycle Move Times 500
	0 C:-75->0 F:-596->-600 T:-597->-600	1 C:-37->0 F:-596->-600 T:-596->-600	2 C:-74->0 F:-595->-600 T:-596->-600	3 C:-29->0 F:-598->-600 T:-598->-600	4 C:-70->0 F:-596->-600 T:-597->-600	5 C:-29->0 F:-597->-600 T:-596->-600
	0 C:-8->100 F:-596->-300 T:-597->-300	1 C:-3->100 F:-596->-300 T:-596->-300	2 C:-8->100 F:-595->-300 T:-596->-300	3 C:-8->100 F:-598->-300 T:-598->-300	4 C:-8->100 F:-596->-300 T:-597->-300	5 C:-8->100 F:-597->-300 T:-596->-300
	0 C:56->200 F:-391->0 T:-399->0	1 C:87->200 F:-391->0 T:-402->0	2 C:56->200 F:-392->0 T:-398->0	3 C:86->200 F:-381->0 T:-393->0	4 C:58->200 F:-387->0 T:-396->0	5 C:87->200 F:-381->0 T:-393->0
	0 C:193->0 F:-15->300 T:-19->300	1 C:194->0 F:-9->300 T:-15->300	2 C:193->0 F:-7->300 T:-18->300	3 C:188->0 F:-14->300 T:-15->300	4 C:196->0 F:-5->300 T:-17->300	5 C:188->0 F:-9->300 T:-12->300
	0 C:55->-100 F:317->0 T:315->0	1 C:58->-100 F:318->0 T:314->0	2 C:53->-100 F:315->0 T:315->0	3 C:55->-100 F:321->0 T:316->0	4 C:43->-100 F:318->0 T:296->0	5 C:52->-100 F:320->0 T:315->0
	0 C:-96->-200 F:169->-300 T:135->-300	1 C:-97->-200 F:162->-300 T:132->-300	2 C:-96->-200 F:141->-300 T:132->-300	3 C:-95->-200 F:156->-300 T:139->-300	4 C:-96->-200 F:129->-300 T:95->-300	5 C:-95->-200 F:152->-300 T:123->-300
	0 C:-188->0 F:-252->-600 T:-275->-600	1 C:-188->0 F:-253->-600 T:-267->-600	2 C:-189->0 F:-260->-600 T:-275->-600	3 C:-188->0 F:-262->-600 T:-276->-600	4 C:-190->0 F:-276->-600 T:-287->-600	5 C:-189->0 F:-259->-600 T:-278->-600
Cycle Move Times 250
	0 C:-46->0 F:-593->-600 T:-616->-600	1 C:-37->0 F:-592->-600 T:-595->-600	2 C:-45->0 F:-594->-600 T:-595->-600	3 C:-39->0 F:-593->-600 T:-595->-600	4 C:-34->0 F:-594->-600 T:-617->-600	5 C:-38->0 F:-594->-600 T:-596->-600
	0 C:-7->100 F:-593->-300 T:-627->-300	1 C:-2->100 F:-592->-300 T:-595->-300	2 C:-7->100 F:-594->-300 T:-595->-300	3 C:-8->100 F:-593->-300 T:-595->-300	4 C:-3->100 F:-594->-300 T:-623->-300	5 C:-8->100 F:-594->-300 T:-596->-300
	0 C:77->200 F:-498->0 T:-440->0	1 C:79->200 F:-495->0 T:-503->0	2 C:80->200 F:-492->0 T:-494->0	3 C:81->200 F:-484->0 T:-496->0	4 C:73->200 F:-486->0 T:-430->0	5 C:82->200 F:-480->0 T:-486->0
	0 C:186->0 F:-139->300 T:-100->300	1 C:194->0 F:-130->300 T:-155->300	2 C:187->0 F:-134->300 T:-139->300	3 C:181->0 F:-120->300 T:-143->300	4 C:184->0 F:-110->300 T:-92->300	5 C:184->0 F:-113->300 T:-124->300
	0 C:99->-100 F:262->0 T:264->0	1 C:117->-100 F:274->0 T:249->0	2 C:96->-100 F:265->0 T:252->0	3 C:99->-100 F:283->0 T:259->0	4 C:79->-100 F:278->0 T:269->0	5 C:96->-100 F:275->0 T:266->0
	0 C:-90->-200 F:271->-300 T:316->-300	1 C:-107->-200 F:276->-300 T:245->-300	2 C:-93->-200 F:266->-300 T:233->-300	3 C:-91->-200 F:295->-300 T:242->-300	4 C:-100->-200 F:301->-300 T:316->-300	5 C:-94->-200 F:287->-300 T:240->-300
	0 C:-222->0 F:-36->-600 T:-55->-600	1 C:-157->0 F:-50->-600 T:-71->-600	2 C:-222->0 F:-58->-600 T:-83->-600	3 C:-221->0 F:-41->-600 T:-130->-600	4 C:-219->0 F:-48->-600 T:-59->-600	5 C:-221->0 F:-48->-600 T:-139->-600
Cycle Move Times 500

To be continued

Have not been able to follow all of the discussion in its entirety, so there’s more than likely something I’ve missed (my apologies in advance), but fundamentally, what is the best way to program the motion of each joint of a “smart” legged robot (real-time ROS vs pre-programmed Arduino)?

Only the P command was reused from the SSC-32U, but not the group move (as well as other features), as the LSS were programmed from scratch. Set aside the SSC-32 / 32U protocol / functionality for this exercise.

Approach 1: Rely on the onboard motion controller (EM1) for timed moves (T modifier).

Approach 2: Create an external controller and send many commands to the servo regarding position (EM0)

The motion controller under EM1 is made for a move without any additional / intermediate position commands (which therefore allows T and S to be calculated knowing start and end positions, and can therefore make use of modifiers. Group moves would indeed be the next logical step, but not implemented (as of yet).

The EM0 motion controller mode is made for receiving many small position commands where the servo holds at each position (and hence max torque can be provided), but does not include any modifiers: since it receives a new command each time where the positions are so close, not knowing the next position, timing cannot be anticipated.

1 Like

For a bit of clarity, if IPE=1 (default), you do not need intermediate positions either (kinda the point of the Intermediate Position Engine, after all). That being said, EM=0 & IPE=0 would basically work like an RC servomotor in the sense that you continuously send positions to it (therefore saturating the internal buffer, configured by FPC).

But EM=0 (IPE=0 or 1) is definitely better suited for managing the motions using intermediate positions than EM=1 is (where the control tries to accel/travel/decel and that may not be appropriate for all types of motions).

1 Like

True and agreed :+1:

Thanks for the clarification. It helps. Added to my notes on EM0/EM1. Definitely need to add all this to a wiki page one of these days.

1 Like