• 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: Jetson Nano Development ESP32 S3 LCD Development Board 1.3 inch Display 1.3inch Screen ST7789 240x240 Mini TV SD-Port QST QMI8658 Gyro Sensor LVGL For Arduino Industrial Modbus RTU 8 ch Relay Module Raspberry Pi Pico 2 Plus RP2350 Board RP2350A Raspberry Pi 5 Raspberry Pi 5 RTC charge configuration RM520N GL 5G/4G/3G M.2 Moudle IoT EMBB For LTE-A/NSA/SA And GNSS For DFOTA /VoLTE For Quectel Raspberry Pi 4 Camera 800x480 Raspberry Pi 5/4B easy Adapter Micro HDMI to HDMI 4K All Ports To Pi's USB Side DeepSeek XiaoZhi AI Voice Chat Robot BOX ESP32-S3 Development Board 3.5 inch LCD N16R8 Touchscreen Display 6-Axis /Camera /SD Milk-V Duo RJ45 RK3566 ESP32-S3 Relay 6-Channel IOT WiFi Bluetooth RS485 Pico Protection Circuits Digital Photo Magnetic Encoder Servo Motor 120KG.CM 24V 360° RS485 High Precision And Large Torque PC Monitor LCD Electronic EYE 0.71inch Round LCD Display Screen For Arduino Raspberry Pi ESP32 Pico STM32 Raspberry Pi 5 PCM5122 I2S Audio Card DAC Also For PI4 /PI3 /Zero Series Raspberry Pi 7 inch HMI industrial DSI Display LCD 7inch TouchScreen Computer 720×1280