Environment Setup
Installing the ROS Environment
Refer to ROS1 Environment Setup
Installing p1_ros
Refer to UltraArm P1 p1_ros Installation
Execute the following command to install the ultraArm P1 ROS code:
$ cd ~/catkin_ws/src
$ git clone -b ultraarm-P1 https://github.com/elephantrobotics/p1_ros.git
$ cd ~/catkin_ws
$ catkin_make
$ source ~/catkin_ws/devel/setup.bash
$ sudo echo 'source ~/catkin_ws/devel/setup.bash' >> ~/.bashrc
Controlling the Robotic Arm
Note: The ultraArm_P1_lib driver library version must be greater than 4.0.4
Preparation Before Use
Before using the example functions, please ensure the following hardware and environment are ready:
Hardware Equipment
ultraArm P1 robotic arm
Power adapter
USB Type-C serial cable
Software and Environment
PC virtual machine Ubuntu 20.04 system
Python 3.6 or later is installed
The
ultraArm_P1_liblibrary is installed (installed via the terminal commandpip install ultraArm_P1_lib)Ensure the ultraArm P1 is correctly powered on, the serial cable is connected, and the virtual machine system can detect the serial port number.
Verification: Verify if the robotic arm's serial port exists. Enter the following in the terminal:
ls /dev/tty*
If the output serial port information includes
/dev/ttyACM*or/dev/ttyUSB*, the serial port has been detected.- Serial Port Permissions: If the serial port exists, execute permissions need to be granted:
sudo chmod 777 /dev/ttyUSB* # or sudo chmod 777 /dev/ttyACM*
1 Slider Control
Open a command prompt and run:
roslaunch ultraarm_p1 slider_control.launch
Open rviz and a slider component. You will see an interface like this:

Then you can control the model in rviz by dragging the slider to move it. To make the real robotic arm move with the model, you need to open another command line and run:
# Default serial port name is "/dev/ttyUSB0", baud rate is 1000000.
rosrun ultraarm_p1 slider_control.py _port:=/dev/ttyUSB0 _baud:=1000000
Please note: Since the robotic arm will move to the model's current position while the command is being entered, please ensure that the model in rviz is not clipping through the model before using the command.
Do not quickly drag the slider after connecting the robotic arm to prevent damage to the robotic arm.
2 Model Following
In addition to the above control, we can also make the model follow the real robotic arm.
Open the command line and start the ROS node:
roscore

Then open a new command line and run:
# Default serial port name is "/dev/ttyUSB0", baud rate is 1000000.
rosrun ultraarm_p1 follow_display.py _port:=/dev/ttyUSB0 _baud:=1000000
After successful execution, the robotic arm joints will relax, and the terminal output will be as follows:
All Servos released
Publishing ...
Finally, open another command line and run:
roslaunch ultraarm_p1 follow_display.launch
This will open rviz and display the model following effect. Now, dragging the real robotic arm joints will cause the simulation model to follow the real robotic arm's movements.
roslaunch ultraarm_p1 follow_display.launch
This will open rviz and display the model following the effect. Now, dragging the real robotic arm joints will cause the simulation model to follow the real robotic arm's movements.

3 GUI Control
Building upon the foregoing, this package also provides a simple graphical user interface (GUI) control interface. Connect to ultraArm.
Open command line:
# Default serial port name is "/dev/ttyUSB0", baud rate is 1000000.
roslaunch ultraarm_p1 simple_gui.launch port:=/dev/ttyUSB0 baud:=1000000

After successful execution, the terminal output will be as follows:
SUMMARY
========
PARAMETERS
* /p1_services/baud: 1000000
* /p1_services/port: /dev/ttyUSB0
* /robot_description: <?xml version="1....
* /rosdistro: noetic
* /rosversion: 1.16.0
NODES
/
p1_services (ultraarm_communication/p1_services.py)
real_listener (ultraarm_p1/listen_real.py)
robot_state_publisher (robot_state_publisher/robot_state_publisher)
rviz (rviz/rviz)
simple_gui (ultraarm_p1/simple_gui.py)
ROS_MASTER_URI=http://localhost:11311
process[robot_state_publisher-1]: started with pid [128931]
process[rviz-2]: started with pid [128932]
process[p1_services-3]: started with pid [128933]
process[real_listener-4]: started with pid [128939]
process[simple_gui-5]: started with pid [128941]
Current ultraArm_P1_lib library version: 4.0.4b3
ultraArm_P1_lib library version meets the requirements!
[INFO] [1764746055.634703]: Starting ultraArm P1 service node...
[INFO] [1764746055.638701]: /dev/ttyUSB0,115200
ultraArm P1 Status
--------------------------------
Joint Limit:
joint 1: -165 ~ +165
joint 2: -18 ~ +85
joint 3: +89 ~ +200
joint 4: -179 ~ +179
[INFO] [1764746057.175403]: Services are ready
Then, input the relevant angle and coordinate information in the GUI interface and click the corresponding button to achieve synchronized movement between the real machine and the simulation model.
4 Keyboard Control
Keyboard control functionality has been added to the ultraarm_p1 package and is synchronized in real-time within rviz. This functionality relies on the Python API, so it is essential to connect it to the actual robotic arm.
Open the command line and run:
# Default serial port name is "/dev/ttyUSB0", baud rate is 1000000.
roslaunch ultraarm_p1 teleop_keyboard.launch port:=/dev/ttyUSB0 baud:=1000000
The running effect is as follows:

The information from ultraArm will be output to the command line as follows:
SUMMARY
========
PARAMETERS
* /p1_topics/baud: 1000000
* /p1_topics/port: /dev/ttyUSB0
* /robot_description: <?xml version="1....
* /rosdistro: noetic
* /rosversion: 1.16.0
NODES
/
p1_topics (ultraarm_communication/p1_topics.py)
real_listener_topic (ultraarm_p1/listen_real_of_topic.py)
robot_state_publisher (robot_state_publisher/robot_state_publisher)
rviz (rviz/rviz)
ROS_MASTER_URI=http://localhost:11311
process[robot_state_publisher-1]: started with pid [135652]
process[rviz-2]: started with pid [135653]
process[p1_topics-3]: started with pid [135654]
process[real_listener_topic-4]: started with pid [135657]
Current ultraArm_P1_lib library version: 4.0.4b3
ultraArm_P1_lib library version meets the requirements!
[INFO] [1764747322.418629]: /dev/ttyUSB1,115200
UltraArm P1 Status
--------------------------------
Joint Limit:
joint 1: -165 ~ +165
joint 2: -18 ~ +85
joint 3: +89 ~ +200
joint 4: -179 ~ +179
然后打开另一个命令行运行:
rosrun ultraarm_p1 teleop_keyboard.py
你将看到命令行输出如下:
ultraArm P1 Teleop Keyboard Controller (ROS1 - Topic Version)
---------------------------------------------------------
Movement (Cartesian):
w (x+)
a (y+) s (x-) d (y-)
z (z-) x (z+)
Rotation (Euler angles):
u (rx+)
j (rx-)
Movement Step:
+ : Increase movement step size
- : Decrease movement step size
Other:
1 - Go to init pose
2 - Go to home pose
3 - Save current pose as home
q - Quit
currently: speed: 50 change percent: 5
[INFO] [1764747657.221866]: Current moving step: position 12.5 mm, angle attitude 9.0°
In this terminal, you can control the state of the robotic arm and move it using command-line keys.
Note: After inputting "2" to return the robotic arm to the starting point, and then performing other coordinate control operations, the terminal will display the following prompt:
[WARN] [1758001794.385321]: Coordinate control disabled. Please press '2' first.
[INFO] [1758001804.552778]: Home pose reached. Coordinate control enabled.
[INFO] [1758001817.069637]: Home pose reached. Coordinate control enabled.
[WARN] [1758001836.301070]: Returned to zero. Press '2' to enable coordinate control.
[WARN] [1758001848.830702]: Coordinate control disabled. Please press '2' first.
[INFO] [1758001863.383565]: Home pose reached. Coordinate control enabled.
[WARN] [1758001933.596504]: Returned to zero. Press '2' to enable coordinate control.
[WARN] [1758001942.051899]: Coordinate control disabled. Please press '2' first.
5 Moveit Usage
p1_ros integrates the MoveIt component.
Open the command line and run:
roslaunch ultraarm_p1_moveit demo.launch
The running result is as follows:
<img src =../../../../resources/C-FunctionsAndApplications/6-SoftwareDevelopment/6.2-ROS1/moveit-2.png
width ="500" align = "center">
The terminal will output the following information, indicating that moveit has started successfully:
[ INFO] [1764748767.950062231]: Using planning interface 'Pilz Industrial Motion Planner'
[ INFO] [1764748767.979214606]: Loading robot model 'firefighter'...
[ INFO] [1764748768.672492877]: Set joints of group 'arm_group' to pose 'init_pose'.
[ INFO] [1764748768.674325697]: Fake controller 'fake_arm_group_controller' with joints [ J1 J2 J3 J4 ]
[ INFO] [1764748768.676474671]: Returned 1 controllers in list
[ INFO] [1764748768.709682299]: Trajectory execution is managing controllers
[ INFO] [1764748768.709847401]: MoveGroup debug mode is ON
Loading 'move_group/ApplyPlanningSceneService'...
Loading 'move_group/ClearOctomapService'...
Loading 'move_group/MoveGroupCartesianPathService'...
Loading 'move_group/MoveGroupExecuteTrajectoryAction'...
Loading 'move_group/MoveGroupGetPlanningSceneService'...
Loading 'move_group/MoveGroupKinematicsService'...
Loading 'move_group/MoveGroupMoveAction'...
Loading 'move_group/MoveGroupPickPlaceAction'...
Loading 'move_group/MoveGroupPlanService'...
Loading 'move_group/MoveGroupQueryPlannersService'...
Loading 'move_group/MoveGroupStateValidationService'...
Loading 'pilz_industrial_motion_planner/MoveGroupSequenceAction'...
[ INFO] [1764748768.849945586]: initialize move group sequence action
[ INFO] [1764748768.871537834]: Reading limits from namespace /robot_description_planning
Loading 'pilz_industrial_motion_planner/MoveGroupSequenceService'...
[ INFO] [1764748768.903345564]: Reading limits from namespace /robot_description_planning
[ INFO] [1764748768.933101019]:
********************************************************
* MoveGroup using:
* - ApplyPlanningSceneService
* - ClearOctomapService
* - CartesianPathService
* - ExecuteTrajectoryAction
* - GetPlanningSceneService
* - KinematicsService
* - MoveAction
* - PickPlaceAction
* - MotionPlanService
* - QueryPlannersService
* - StateValidationService
* - SequenceAction
* - SequenceService
********************************************************
[ INFO] [1764748768.934931311]: MoveGroup context using planning plugin ompl_interface/OMPLPlanner
[ INFO] [1764748768.935042611]: MoveGroup context initialization complete
You can start planning now!
[ INFO] [1764748772.433527325]: Starting planning scene monitor
[ INFO] [1764748772.438227267]: Listening to '/move_group/monitored_planning_scene'
[ERROR] [1764748773.125892638]: Group 'arm_group' has a mimic joint. Will not initialize dynamics solver
[ INFO] [1764748773.138298263]: Constructing new MoveGroup connection for group 'arm_group' in namespace ''
[ INFO] [1764748774.394846420]: Ready to take commands for planning group arm_group.
The basic path planning operation is as follows:
To have the actual robotic arm execute the plan synchronously, you need to open another command line and run:
# Default serial port name is "/dev/ttyUSB0", baud rate is 1000000.
rosrun ultraarm_p1_moveit sync_plan.py _port:=/dev/ttyUSB0 _baud:=1000000
Modify the movement speed
To prevent joints from wobbling during actual robotic arm movement, the joint movement speed needs to be reduced.
- In the
sync_plan.pyfile, modify the speed parameter of the robotic arm's Python API; here, change it to 50.
...
def callback(data: JointState):
"""Callback function for ROS JointState subscription.
This function converts incoming joint positions (radians) to angles
in degrees and sends them to the P1 robotic arm.
Args:
data (JointState): Joint state message containing joint positions.
"""
data_list = []
for _, value in enumerate(msg.position):
radians_to_angles = round(math.degrees(value), 2)
data_list.append(radians_to_angles)
joint1 = data_list[0]
joint2 = data_list[1]
joint3 = data_list[5] + 90
joint4 = data_list[-1]
angles_list = [joint1, joint2, joint3, joint4]
self.ua.set_angles(angles_list, 50, _async=False)
...
- In the Moveit RViz interface, modify the scaling ratio for velocity and acceleration. Here, change it to 0.1 and then save the current configuration.
