The Robotic Arm Controller Feature in PSLab Android Application.

Recently while working on PSLab Android Project, a new feature was implemented to add a controller for a Robotic Arm in the Android Application. In this blog, I will explain what this new feature is, how it has been implemented and what are some of the functionalities of it.

What is Robotic Arm?

Robotic Arm, as the name suggests is a small arm-like structure, which moves with the help of 4 servo motors connected to it. The image of the robotic arm is as under, 

(Figure 1 : Robotic Arm)

What is the Robotic Arm Controller Feature in Android App?

As mentioned earlier, the robotic arm uses 4 servos for the movements. The aim of the controller feature in the Android app is to allow users to adjust the rotation of each servo with a very intuitive UI, so they can move the robotic arm as they wish. Further, in this blog, I will discuss UI, implementation and some cool features of the robotic Arm Controller.

User Interface


(figure 2: UI of the robotic arm controller)

In the screenshot above, there are 4 circular controllers for each respective servo. The user can use the knob or enter the values using the keyboard by tapping on the value at the center of the knobs. Each value indicates the value in degrees the user wishes to move that servo.

Timeline

Below the 4 servo controllers is a black timeline. There are 60 boxes in each of the 4 timelines. These 60 boxes indicates the seconds. So basically if the user wants the robotic arm to perform some set of actions sequentially, using these timelines, users can set the rotation for each servo at each second, then user can use the play button on the red control panel to play this timeline and the app will send the degree value at each second to the respective servo. A filled timeline would look something like below, 


(Figure 3: Timeline)

As can be seen, there are different values for each servo at each second, so when the user starts the timeline, values at each second will be sent to the respective servos. servo4() function of the ScienceLab class is called to set values for all for servos at each second.

How to add the values to the timeline?

There is a small handle on the top right corner of each servo controller, user can long-press the handle and drag and drop the values to desired seconds for respective servos.  This functionality can be found in this video between 0:33 to 0:43

This feature uses Android’s drag and drops listener. The code for this drag and drop function is as under,

private View.OnDragListener servo1DragListener = new View.OnDragListener() {
        @Override
        public boolean onDrag(View v, DragEvent event) {
            if (event.getAction() == DragEvent.ACTION_DRAG_ENTERED) {
                View view = (View) event.getLocalState();
                TextView text = view.findViewById(R.id.degreeText);
                if (view.getId() == R.id.servo_1) {
                    ((TextView) v.findViewById(R.id.timeline_box_degree_text)).setText(text.getText());
                }
            }
            return true;
        }
    };

Such drag listeners are created for each servo controller.

Save Timeline Feature

Suppose user has set a whole 60 seconds timeline for some action, and the user wants to use that set of values again and again, it doesn’t make sense if the user has to set the values every time. So there is a feature to save the timeline as well. Whenever user has created some timeline, user can just click on the save button on the control panel and the timeline will be saved both as a CSV file and as a realm object. So the timeline will be visible in the DataLoggerActivity as well. Whenever user opens a logged timeline, values for the respective servo timeline will be set automatically.

The code to save the timeline is as below.  For each second a new ServoData object is created with degree values for all 4 servos at that second.

private void saveTimeline() {
        long block = System.currentTimeMillis();
        servoCSVLogger.prepareLogFile();
        servoCSVLogger.writeMetaData(getResources().getString(R.string.robotic_arm));
        String data = "Timestamp,DateTime,Servo1,Servo2,Servo3,Servo4,Latitude,Longitude\n";
        long timestamp;
        recordSensorDataBlockID(new SensorDataBlock(block, getString(R.string.robotic_arm)));

So first we create a block variable using the current timestamp, this block will be used for all the realm object stored for this timeline. We also prepare a CSV file and CSV header for the log. 

String degree1, degree2, degree3, degree4;
for (int i = 0; i < 60; i++) {
     timestamp = System.currentTimeMillis();
     degree1 = degree2 = degree3 = degree4 = "0";
     if (((TextView) servo1TimeLine.getChildAt(i).findViewById(R.id.timeline_box_degree_text)).getText().length() > 0) {
         degree1 = ((TextView) servo1TimeLine.getChildAt(i).findViewById(R.id.timeline_box_degree_text)).getText().toString();
     }

Now, we run a for loop for each 60 second timeline and store the set value of each servo in degree1, degree2, degree3 and degree4 variables. In the above code snippet only degree1 is shown, but the same thing is done for other values as well. Once we have 4 degree values for each servo at for a second, we store it as an ServoData Object in realm and also write it to the CSV file using the following lines of code,

recordSensorData(new ServoData(timestamp, block, degree1, degree2, degree3, degree4, lat, lon);
servoCSVLogger.writeCSVFile(data);

Here the data variable is a string with comma-separated values of the degree values of each servo.

Once the user saves the timeline the generated CSV looks something like below,


(Figure 4: Saved timeline CSV)

To set the timeline from the saved logged data, a small function just iterates over all the ServoData objects stored in the realm and set the value for the respective servo in the timeline. The function is as under,

private void setReceivedData() {
        ArrayList servoDataList = new ArrayList(recordedServoData);
        for (int i = 0; i < servoDataList.size(); i++) {
            ServoData servoData = (ServoData) servoDataList.get(i);
            ((TextView) servo1TimeLine.getChildAt(i).findViewById(R.id.timeline_box_degree_text)).setText(servoData.getDegree1());
            ((TextView) servo2TimeLine.getChildAt(i).findViewById(R.id.timeline_box_degree_text)).setText(servoData.getDegree2());
            ((TextView) servo3TimeLine.getChildAt(i).findViewById(R.id.timeline_box_degree_text)).setText(servoData.getDegree3());
            ((TextView) servo4TimeLine.getChildAt(i).findViewById(R.id.timeline_box_degree_text)).setText(servoData.getDegree4());
        }
    }

Conclusion

This feature enables the user to control the robotic arm with a very intuitive user interface. And the save timeline feature allows the user to use/share already stored timeline for some actions with other users. 

A small video to explain the save timeline functionality can be seen below,

References

Tags : GSoC ‘19, PSLab, Android, Robotic Arm

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.