• sales

    +86-0755-88291180

WAVEGO Custom Action Development Tutorial

WAVEGO: Custom Action Development Tutorial

In the demo of ServoCtrl.h, we provide six functions for custom actions:

void functionStayLow();
void functionHandshake();
void functionJump();
void functionActionA();
void functionActionB();
void functionActionC();

For the first three of them, we designed some actions: staying low, shaking hands, and jumping.
The last three you can use to design some custom actions, you can also extend more functions and change the HTML code in WebPage.h for more buttons, the code for the function call is in app_httpd.cpp.
In this tutorial, we'll cover how to program actions.
Take "stay low" as an example:

void functionStayLow(){
// The robot squatted from the normal standing height WALK_HEIGHT to the minimum height WALK_HEIGHT_MIN
for(float i = 0; i<=1; i+=0.02){
standUp(besselCtrl(WALK_HEIGHT, WALK_HEIGHT_MIN, i));
GoalPosAll();
delay(1);
}
delay(300);
// The robot rises from the lowest standing height WALK_HEIGHT_MIN to the highest standing height WALK_HEIGHT_MAX
for(float i = 0; i<=1; i+=0.02){
standUp(besselCtrl(WALK_HEIGHT_MIN, WALK_HEIGHT_MAX, i));
GoalPosAll();
delay(1);
}
// The robot descends from the highest standing height WALK_HEIGHT_MAX to the normal standing height WALK_HEIGHT
for(float i = 0; i<=1; i+=0.02){
standUp(besselCtrl(WALK_HEIGHT_MAX, WALK_HEIGHT, i));
GoalPosAll();
delay(1);
 }
}

The complete code is as above. After calling this function, the robot will first squat to the lowest point, then stand up to the highest point, and finally, return to the normal standing height.
standUp() function is used to control the standing height of the robot.
For example, if you want the robot to stand at a height of 70mm, you can write as follows:

standUp(70); // Call this function to calculate the angle to which each joint needs to rotate if the robot stands at a height of 70mm.
             // and store the target position of the angle each joint should turn to in GoalPWN[].
            // Calling this function alone will not make the servos start turning.
GoalPosAll(); // After calling this function, all servos of the robot will rotate to the corresponding position in GoalPWM[].

The purpose of GoalPosAll() is that the joint operation of each leg takes time, especially when performing complex movements, and the calculation is more.
If it is larger, it needs the servos to start moving at the same time to make the movements more coordinated.
If you want the movement to be linear, you can write the squat and rise as follows.

for(int i = 0; i<=10; i++){
standUp(70-i);
GoalPosAll();
delay(10);
}
for(int i = 0; i<=10; i++){
standUp(60+i);
GoalPosAll();
delay(10);
}

If you want the action to be flexible, you can use the following function to achieve the effect of a flexible action.

besselCtrl(VAL_START, VAL_END, i); // VAL_START: initial value
                                  // VAL_END: end value
                                 // i: the locating point for linear changing 
                                // The return value of this function is the value of the nonlinear change calculated based on VAL_START, VAL_END, and the linearly changing anchor point i, we will explain how this is used below.


As shown in the figure above, the horizontal axis is the variable "i", the fixed point with linear changing, and the value of "i" changes linearly between 0-1 (the increment does not change at the same time).
The VAL_START and VAL_END of the vertical axis are the initial value and the end value respectively, but it should be noted that the initial value is not necessarily smaller than the end value.
The output value is between VAL_START and VAL_END. When the "i" value changes linearly from 0 to 1, the change speed of the output value is changing, starting slow, then fast and finally slow.
Use this function to make the robot's movements look more natural.
For example, when you want to reduce the standing height of the robot from WALK_HEIGHT to WALK_HEIGHT_MIN, you can write as follows:

for(float i = 0; i<=1; i+=0.02){
    standUp(besselCtrl(WALK_HEIGHT, WALK_HEIGHT_MIN, i));
    GoalPosAll();
    delay(1);
}

So besselCtrl() can also be used for other more complex purposes, taking the following handshake as an example:

void functionHandshake(){
   // Each leg can be edited individually, then call GoalPosAll() to unify the movement.
   for(float i = 0; i<=1; i+=0.02){
      // Control the front two legs to retract a bit and raise them so the robot looks up.
      singleLegCtrl(1, besselCtrl(WALK_EXTENDED_X, 0, i), besselCtrl(WALK_HEIGHT,
WALK_HEIGHT_MAX, i), besselCtrl(WALK_EXTENDED_Z, -15, i));
      singleLegCtrl(3, besselCtrl(WALK_EXTENDED_X, 0, i), besselCtrl(WALK_HEIGHT,
WALK_HEIGHT_MAX, i), WALK_EXTENDED_Z);

   // Control the rear two legs to retract and lower so the robot appears to sit down while looking up.
   singleLegCtrl(2, -WALK_EXTENDED_X, besselCtrl(WALK_HEIGHT, WALK_HEIGHT_MIN10, i), besselCtrl(WALK_EXTENDED_Z, 2*WALK_EXTENDED_Z, i));
   singleLegCtrl(4, -WALK_EXTENDED_X, besselCtrl(WALK_HEIGHT, WALK_HEIGHT_MIN10, i), besselCtrl(WALK_EXTENDED_Z, 2*WALK_EXTENDED_Z, i));

   // After all the above calculations are completed, perform a unified movement, otherwise it will look uncoordinated if it is counted one step at a time.
GoalPosAll();
   // Symbolically give some delay, in fact, the calculation process of the leg link above will also take some delay.
delay(1);
}

  // The following is used for handshake action.
  for(float i = 0; i<=1; i+=0.02){
    singleLegCtrl(3, besselCtrl(0, WALK_RANGE/2+WALK_EXTENDED_X, i),
besselCtrl(WALK_HEIGHT_MAX, WALK_HEIGHT_MIN, i), besselCtrl(WALK_EXTENDED_Z, 0,
i));
   GoalPosAll();
   delay(1);
}
for(int shakeTimes = 0; shakeTimes < 3; shakeTimes++){
   for(float i = 0; i<=1; i+=0.03){
    singleLegCtrl(3, WALK_RANGE/2+WALK_EXTENDED_X,
besselCtrl(WALK_HEIGHT_MIN, WALK_HEIGHT_MIN+30, i), 0);

      GoalPosAll();
      delay(1);
      }
      for(float i = 0; i<=1; i+=0.03){
        singleLegCtrl(3, WALK_RANGE/2+WALK_EXTENDED_X,
besselCtrl(WALK_HEIGHT_MIN+30, WALK_HEIGHT_MIN, i), 0);

      GoalPosAll();
      delay(1);
    }
   }
   // Contrary to the sit-down motion in the first part, here is the return to the standing motion of the robot
   for(float i = 0; i<=1; i+=0.02){
      singleLegCtrl(1, besselCtrl(0, WALK_EXTENDED_X, i),
besselCtrl(WALK_HEIGHT_MAX, WALK_HEIGHT, i), besselCtrl(-15, WALK_EXTENDED_Z,
i));
      singleLegCtrl(3, besselCtrl(WALK_RANGE/2+WALK_EXTENDED_X, WALK_EXTENDED_X,
i), besselCtrl(WALK_HEIGHT_MIN, WALK_HEIGHT, i), besselCtrl(0, WALK_EXTENDED_Z,
i));

       singleLegCtrl(2, -WALK_EXTENDED_X, besselCtrl(WALK_HEIGHT_MIN-10,
WALK_HEIGHT, i), besselCtrl(2*WALK_EXTENDED_Z, WALK_EXTENDED_Z, i));
        singleLegCtrl(4, -WALK_EXTENDED_X, besselCtrl(WALK_HEIGHT_MIN-10,
WALK_HEIGHT, i), besselCtrl(2*WALK_EXTENDED_Z, WALK_EXTENDED_Z, i));

        GoalPosAll();
        delay(1);
 }
TAG: Spotpear Raspberry Pi 5 PoE MINI HAT(G) Power over RJ45 Ethernet 802.3af/at Moudle for Pi5 Raspberry Pi 14 inch LCD 2K HDMI /Type C Display Capacitive TouchScreen 2160x1440 For Jetson Nano/mini Computer PC ESP32 S3 Development Board 2.8 inch Round LCD Display 480x480 QMI8658 Sensor / SD /MP3 Audio /Battery Port LVGL/HMI For Arduino Luckfox PicoKVM KVM NanoKVM RV1106 Pico Remote Control /Power /Desktop Maintenance Server HDMI USB For PiKVM Raspberry Pi Raspberry Pi Pico Display ESP32 1.9inch LCD 0.96inch RGB OLED Raspberry Pi RP2040 LoRa-HF 2.13Inch E-Ink 4inch Round LCD HDMI Capacitive Touchscreen Display 720x720 For Raspberry Pi/Jetson Nano/mini PC Raspberry Pi 5 5V5A Power ESP32-S3 ST7789 Raspberry Pi Pico 2 W RP2350 Pico2W ARM Cortex-M33 And RISC-V Hazard3 Wi-Fi4 Bluetooth5.2 CYW43439 Pi5 Industrial Modbus RTU Dual Ethernet RJ45 To 8ch POE ETH Relay (C) PoE Power over Ethernet wide dynamic range Serial UART Bus Servo ST3215-HS 20KG.CM High Speed Magnetic Encoder 360&deg; Large Torque X1011 Raspberry Pi 5 PCIe to M.2 NVMe 4-Ports SSD Board HAT Pi5 Four-Times 2280 Raspberry Pi Pico 2 RP2350 1.28 inch Round LCD Development Board 240x240 Display Screen QMI8658 6-Axis